电子邮件是人类互联网最古老的异步通信协议之一,其地址体系覆盖了从个人到企业的每一个实体。当 AI Agent 需要与人类或其他 Agent 进行跨边界通信时,邮件几乎是唯一天然具备全局可达性的渠道 —— 无需预先部署 SDK、不依赖特定框架、收件方的客户端现成可用。然而,传统 SMTP 协议栈对 Agent 并不友好:缺乏结构化身份验证、难以验证发件方真实性、Webhook 投递需要公网可达性、消息去重和会话追踪需要业务层自行实现。e2a 正是针对这些痛点构建的专用邮件网关,它在 SMTP 之上叠加了一层面向 Agent 的结构化协议,使邮件收发成为可控、可验证且与业务代码类型对齐的操作。
架构概览:从 MX 记录到 Agent 入口
e2a 的部署形态是一个自包含的 Go 服务,核心依赖只有 PostgreSQL 14+ 和标准 SMTP 协议栈。邮件流向遵循一个清晰的四阶段管道:接收 → 验证 → 签名 → 投递。当一封邮件抵达 MX 记录指向 e2a 实例的域名时,SMTP 接收层首先执行 SPF 和 DKIM 检查,这两步验证解决了公开互联网上最难解决的信任问题 —— 你如何确认这封邮件确实来自声明的发件域。验证结果不会直接透传给 Agent,而是被封装进一组 X-E2A-Auth-* 签名头中。e2a 会剥离所有外部传入的同名头部(防止伪造),用 HMAC-SHA256 重新签名,签名内容绑定消息 ID、邮件正文哈希、发件人、验证结果和时间戳。这意味着即使攻击者截获了一次完整的投递,他也无法将这组签名移植到另一封邮件或篡改后的正文中。
签名完成后,e2a 根据接收方 Agent 的注册模式选择投递路径。模式由 agent_mode 字段决定:cloud 模式将邮件作为 HTTPS POST 发送到 Agent 预先注册的 webhook_url,local 模式则通过 WebSocket 推送通知,Agent 无需拥有公网地址。这两种模式共享同一套身份验证基础设施,对于 WebSocket 路径,Agent 使用 API Key 认证并建立持久连接;对于 Webhook 路径,接收方通过 X-E2A-Auth-* 头中的 HMAC 签名验证消息完整性。
身份层:从邮件地址到结构化实体
邮件地址在 e2a 中不只是 SMTP 信封地址,它是 Agent 的全局唯一标识符。注册一个 Agent 只需提供 slug,e2a 自动在共享域名上分配 slug@agents.e2a.dev 格式的地址,无需配置 DNS 记录。如果需要使用自定义域名,则需要进行 DNS TXT 验证以证明域名所有权。验证通过后,e2a 能够区分两类实体:human 和 agent,这一分类记录在 X-E2A-Auth-Entity-Type 头中,Agent 可以据此决定如何处理来自人类的请求与来自其他 Agent 的指令。
这种实体类型的区分在多 Agent 编排场景中尤为重要。假设你构建了一个包含分析 Agent、审批 Agent 和执行 Agent 的工作流,分析 Agent 可能只信任来自 *.agents.e2a.dev 域名且 entity_type=agent 的消息,而审批 Agent 可能在 entity_type=human 时触发人工复核流程。结构化的实体标识使得这类路由逻辑可以在代码中以类型安全的条件分支表达,而不是依赖邮件主题或正文的启发式解析。
签名验证:为什么 X-E2A-Auth-Verified 不能直接信任
对于首次接触 e2a 的开发者,一个常见的误解是看到 X-E2A-Auth-Verified: true 就认为发件人已通过身份验证。事实上,这个字段只是 e2a 服务器在网关层的声明 —— 任何能够向 Agent 的 Webhook URL 发送请求的人都可以在 HTTP 请求中设置这个头。真正的安全决策必须基于 HMAC 签名的本地验签。
e2a 的 SDK 默认将字段访问保护起来:未经验证的 Webhook payload 上访问 email.sender 或 email.subject 会抛出 UnverifiedEmailError。开发者需要调用一次 client.parse_webhook(request_body) 来完成验签,该函数依次检查邮件正文的 SHA-256 哈希是否与 X-E2A-Auth-Body-Hash 匹配、HMAC 签名是否有效、以及时间戳是否在 5 分钟 replay window 内。如果验签失败或时间戳过期,SDK 拒绝暴露任何邮件内容。这种强制验签的设计将安全边界固定在业务代码层:Agent 永远无法意外处理未验证的邮件字段,因为类型系统会在编译期或运行时阻止这类操作。
对于通过 REST API 直接获取消息的场景(如 client.get_message(message_id)),验签步骤被省略,因为 HTTP Bearer 认证已经验证了请求通道的安全性。SDK 在这两种场景下的行为差异反映了 e2a 对威胁模型的精确建模:Webhook 路径面对的是公开互联网(任何人都可能发送 POST 请求),REST API 路径面对的是持有有效 API Key 的已认证客户端。
Human-in-the-Loop:可配置的消息审批门
对于需要人工监督的高风险操作,e2a 提供了内置的 HITL(Human-in-the-Loop)机制。当 Agent 的 hitl_enabled 标志被激活后,所有出站 send 和 reply 调用不会立即投递 —— 消息被存入 pending_approval 状态,API 返回 HTTP 202 Accepted。审批者可以通过三种渠道处理:Dashboard UI、CLI 命令 e2a pending 或邮件中的 magic-link(点击链接完成一键审批或拒绝)。Magic-link 路由使用 HMAC 编码的 token,包含消息 ID 和操作类型,无需会话状态存储 —— 这是 stateless approval 设计的一个务实选择。
HITL 还支持 auto-expiration:消息在可配置的 TTL 后根据 hitl_expiration_action 执行自动操作。若设置为 auto_send,消息在超时后自动投递;若设置为 auto_reject,消息被丢弃并标记为 expired_rejected。这一机制解决了审批者长时间未响应的灰度发布或限时任务场景,避免消息无限期悬停。
投递模式选型:WebSocket 与 Webhook 的工程权衡
选择 cloud 还是 local 模式并非功能差异问题,而是基础设施约束下的工程决策。cloud 模式要求 Agent 拥有公网可达的 HTTPS 端点(Webhook URL 必须解析到公网 IP,且在生产环境中强制使用 HTTPS),适合部署在云函数、容器服务或拥有固定公网 IP 的服务器上的 Agent。local 模式为零公网暴露的运行环境而设计 —— 开发者笔记本、边缘设备、企业内网环境 ——Agent 通过 WebSocket 长连接接收通知,离线期间的消息在服务器端排队,重连后自动 drain。
一个值得关注的细节是 WebSocket 通知本身是轻量的元数据推送,包含 message_id 等引用信息而非邮件全文。Agent 收到通知后主动调用 client.get_message() 获取完整内容和验签。这一设计避免了长连接上的大数据传输开销,同时将消息内容的完整性和验证逻辑保留在有状态的 API 调用中。需要毫秒级响应或高吞吐的场景下,Agent 可以并发获取历史消息或启用 polling fallback。
开发体验:SDK 与 CLI 的分工
e2a 提供了 TypeScript 和 Python SDK,以及一个功能完备的 CLI。SDK 的核心价值在于类型安全的消息解析和验签封装。以 Python 为例:
from e2a.v1 import E2AClient
client = E2AClient() # 读取 E2A_API_KEY
email = client.parse_webhook(request_body) # 解析 + 验签
print(email.sender, email.subject)
email.reply("Got it!", conversation_id="conv_123")
这一调用序列完成了传统方案中需要数行代码才能实现的功能:原始请求体的接收、HMAC 签名验证、字段提取、以及基于 conversation_id 的回复线程关联。SDK 内部处理了 replay window 检查、正文哈希校验和 canonical 签名字符串的构造。对于需要异步处理或需要同时维护多个 Agent 的场景,AsyncE2AClient 提供了 async for 语法的消息监听循环。
CLI 则面向运维和调试场景:e2a listen 实时输出 WebSocket 消息(--json 输出完整 JSON、--forward 转发到本地 HTTP 端点),e2a inbox 列出最近消息,e2a pending 查看待审批队列。对于调试中的 Agent,e2a listen --forward http://localhost:18789/v1/responses --forward-token <token> 提供了与 OpenAI Responses API 的开箱即用集成 —— 这实际上是 e2a 对 AI 原生邮件处理的一个示范性集成路径。
配置参数与安全边界
自托管部署时,有几个关键配置项直接影响安全性和可用性。E2A_ENV=production 启用严格模式,强制 Webhook URL 必须为公网 HTTPS、禁止本地 IP 范围解析、启用完整的 SSRF 保护。signing.hmac_secret 是验签的核心密钥,泄露后需通过 Dashboard 立即轮换,SDK 会在轮换后拒绝旧签名。shared_domain 配置允许多租户共享域名(如 agents.e2a.dev),用户注册 slug 时直接获得地址而无需 DNS 配置 —— 这对快速验证和小规模部署极为便利。数据保留方面,入站消息体默认保留 30 天,出站消息体在 HITL 终止后清除,API Key 始终以哈希形式存储,应用日志不记录邮件正文或原始密钥。
应用场景与集成思路
e2a 特别适合以下场景。第一,跨组织 Agent 通信:两个不同公司各自的 e2a 实例可以通过标准 SMTP 互相投递邮件,实体身份通过 e2a-to-e2a 的 X-E2A-Conversation-Id 头保持线程连续性,无需建立共享基础设施。第二,人工审批的工作流:AI Agent 生成的内容通过 HITL 审批后再发出,保证输出质量且无需 Agent 代码自行维护审批状态机。第三,带验证的事务邮件:Agent 需要向外部系统发送需要收件人验证的邮件(如邮箱确认链接),e2a 作为出站代理确保每封邮件都有可追溯的 Agent 来源和审批记录。
对于已经在使用 SendGrid、Resend 或 SES 作为出站投递的团队,e2a 并不取代这些服务 —— 它被设计为接收侧的基础设施,出站投递仍然可以通过 outbound_smtp 配置指向这些平台。e2a 在 SMTP 协议层之上的结构化抽象层,与底层投递平台的专业投递优化形成互补。
e2a 的设计哲学清晰地反映了一个趋势:当 AI Agent 从单一个体走向多 Agent 协作和跨边界通信时,协议层的身份验证、消息完整性和审计追溯能力不再是可选项,而是基础设施的必备层。邮件作为已有数十年积累的全局可达协议,在 Agent 时代找到了新的定位 —— 它不再只是人与人的沟通工具,而是 Agent 与人类、Agent 与 Agent 之间跨越组织边界的可信通信轨道。
资料来源:GitHub Mnexa-AI/e2a(https://github.com/mnexa-ai/e2a)
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。