apumail / blog

AI 智能体如何接收 OTP 验证码

邮箱验证几乎是每个自主智能体撞上的第一堵墙。注册表单很简单,难的是那六位数字——它们躺在一个智能体根本没有的收件箱里。

2026年7月14日

一个正在注册某项服务的智能体,大概只能完成四十秒的有效工作,就会遇到一个写着 我们已向您的邮箱发送验证码的页面。从这一刻起,一切都依赖于智能体通常并不具备的机制: 一个能收信的地址,一种得知邮件已到达的方式,以及一种从为人眼设计的 HTML 大杂烩里 抠出六位数字的方法。

这句话里藏着三项工作,值得把它们拆开来看,因为大部分痛苦都源于按错误的顺序去解决它们。

1. 一个在你需要之前就存在的地址

最天真的做法是把智能体接入一个真实邮箱——一个用应用专用密码登录的 Gmail 账号, 或者通过 IMAP 连接到团队共享收件箱。这在你只有一个智能体时完全可行。一旦有了两个, 它们就会读到彼此的验证码,而这种故障是不确定的,调试起来苦不堪言。

你真正需要的是:每个智能体、每项任务一个一次性地址,在需要的那一刻创建,用完即弃。 这意味着开通必须足够便宜,便宜到可以内联完成——没有控制台,没有 API 密钥,没有人工介入:

INBOX=$(curl -sS -X POST https://api.apumail.com/api/v1/inboxes)
ADDR=$(echo "$INBOX" | jq -r .address)
TOK=$(echo "$INBOX" | jq -r .token)

echo "$ADDR"   # vivid-llama-4a2c@apumail.com

这个调用不需要认证。返回的令牌是该收件箱的凭证,仅此而已——正是这一特性让它可以安全地交给智能体: 令牌泄露的影响范围只是一个一次性收件箱。

2. 无需轮询循环即可得知邮件已到达

这是大多数自研实现出错的地方。本能的做法是轮询:检查收件箱,睡两秒,再检查。 在你的笔记本上能跑,到了生产环境就是隐患——每次唤醒都在烧 token,而且你在和一个 通常十分钟就过期的验证码赛跑。

长轮询把这件事反过来。智能体只发一个请求,该请求会一直阻塞,直到邮件到达或超时:

curl -sS -H "Authorization: Bearer $TOK" \
  "https://api.apumail.com/api/v1/inbox/$ADDR/wait?timeout=120"

一个请求,一次唤醒。连接保持打开,在 SMTP 监听器接收邮件的那一刻立即返回。 对智能体来说,这比对普通服务更重要:每多一次轮询就是一次模型往返,而模型往返 意味着真金白银的成本和实实在在的延迟。

3. 把数字取出来

这是悄悄吃掉最多工程时间的部分。一封验证邮件本质上是营销产物——嵌套表格、跟踪像素、 被三层 span 和一个 font 标签包裹的验证码。把它交给 LLM 去“找验证码”,大约 95% 的情况下能成功, 而当它处在你的关键路径上时,这是个糟糕的数字。

可行的做法是在服务端、在保存时、在智能体看到邮件之前就完成提取。apumail 在接收邮件时运行提取, 并把结果放进邮件的 otp 字段:

{
  "messages": [{
    "from": "noreply@stripe.com",
    "subject": "Your Stripe verification code",
    "otp": "482910"
  }]
}

智能体读取 .messages[0].otp 即可。无需解析,无需提示词,也没有那个 95%。 整个流程——开通、等待、提取——只有三次调用,完全不涉及模型,这意味着它不可能幻觉出一个验证码。

完整流程

# 1. provision
INBOX=$(curl -sS -X POST https://api.apumail.com/api/v1/inboxes)
ADDR=$(echo "$INBOX" | jq -r .address)
TOK=$(echo "$INBOX" | jq -r .token)

# 2. use $ADDR in the signup form, then block until the mail lands
CODE=$(curl -sS -H "Authorization: Bearer $TOK" \
  "https://api.apumail.com/api/v1/inbox/$ADDR/wait?timeout=120" \
  | jq -r '.messages[0].otp')

# 3. submit $CODE
echo "$CODE"   # 482910

如果你的智能体支持 MCP,同样的三步就是三次工具调用,完全可以跳过 HTTP——参见 把临时邮箱作为 MCP 服务器。如果你的智能体撞上的是短信验证码 而不是邮件验证码,同一套等待/提取层也覆盖电话号码。

试一试——无需注册

一次无需认证的 POST,即可返回一个可用的地址及其令牌。

curl -sS -X POST https://api.apumail.com/api/v1/inboxes