邮箱验证码 API:用 Python 在测试中接收验证码

在 Python 脚本里读取邮箱验证码,归结起来就是三个 HTTP 请求:租用邮箱、轮询直到验证码出现、不想等了就取消订单。这篇教程只用 requests 和标准库,通过 OTPGmail 的 REST API 把这个流程搭起来。说明用中文,代码保持英文。

这个示例是写给测试自家注册流程的开发者和 QA 团队的。OTPGmail 的邮箱是真实的 @gmail.com 或 @icloud.com 邮箱,只接收邮件,不接收短信。如果你在第三方平台上注册账号,请遵守该平台的条款。

开始之前

流程:三个请求

  1. 用 POST /v1/orders 为指定服务租用一个地址。
  2. 每 3–5 秒调用一次 GET /v1/orders/{orderId};otp 数组里出现内容,就说明验证码到了。
  3. 不想等了,调用 POST /v1/orders/{orderId}/cancel;第一个验证码到达前取消,费用 100% 退回。

就算你什么都不做,没有收到验证码的订单也会在等待时间(最长 25 分钟)结束后自动取消并退款。所以第三步不是必需的,只是让余额更早回来。

租用邮箱

import time
import uuid
import requests

HOST = "otpgmail.net"
BASE = f"https://{HOST}/v1"
HEADERS = {"Authorization": "Bearer og_YOUR_API_KEY"}


def rent(service, domain="gmail.com"):
    resp = requests.post(
        f"{BASE}/orders",
        json={"service": service, "domain": domain},
        headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
        timeout=15,
    )
    body = resp.json()
    if not body.get("success"):
        raise RuntimeError(body["error"]["code"])
    return body["data"][0]  # data 是数组:每个邮箱一个订单

domain 是可选参数,不传就是 gmail.com;服务提供 iCloud 时可以传 icloud.com。Idempotency-Key 请求头很重要:每个新订单生成一个新的 UUID,超时后重试同一个订单时沿用同一个密钥,这样就不会为第二个邮箱付费。创建订单的请求在高峰期可能要几秒钟,客户端超时请设为 15 秒左右。

请用 requests,不要用标准库的 urllib:urllib 默认的 User-Agent 可能会被 API 前面的 CDN 拒绝。

等待验证码与取消

def wait_for_code(order_id, max_wait=600, interval=4):
    deadline = time.time() + max_wait
    while time.time() < deadline:
        resp = requests.get(f"{BASE}/orders/{order_id}", headers=HEADERS, timeout=15)
        order = resp.json()["data"]
        if order["otp"]:
            return order["otp"][-1]["code"]  # 最新的验证码在数组末尾
        if order["status"] == "cancelled":
            return None  # 等待时间已过,费用已退回
        time.sleep(interval)
    # 到了自己设定的上限:在第一个验证码前取消并退款
    requests.post(f"{BASE}/orders/{order_id}/cancel", headers=HEADERS, timeout=15)
    return None

3–5 秒的间隔既能及时拿到验证码,又远低于速率限制。otp 数组按到达顺序排列,最早的在前,所以 otp[-1] 永远是最新的验证码。有些服务发的不是数字验证码,而是验证链接,这时链接也会出现在 code 字段里。如果该服务会发送多个验证码,后续的验证码会在订单有效期内自动追加到数组末尾;很多服务只发一个。

串起来

try:
    order = rent("git", domain="icloud.com")
except RuntimeError as e:
    if str(e) in ("DOMAIN_UNAVAILABLE", "NO_MAILS_AVAILABLE", "OUT_OF_STOCK"):
        order = rent("git", domain="gmail.com")  # 换 Gmail 再试
    else:
        raise

print("地址:", order["email"])
# 把这个地址填进注册表单并提交,然后开始等待
code = wait_for_code(order["orderId"])
print("验证码:", code or "没有收到")

先把地址填进目标网站的表单、请求发送验证码,再开始等待;表单没提交,验证码自然不会来。Gmail 和 iCloud 的区别见接收验证码用 Gmail 还是 iCloud,GitHub 的具体情况见 GitHub 说明页。

用 curl 走一遍

HOST=otpgmail.net
KEY=og_YOUR_API_KEY

# 创建订单
curl -s -X POST "https://$HOST/v1/orders" \
  -H "Authorization: Bearer $KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"service":"git","domain":"gmail.com"}'

# 查询订单(每 3-5 秒一次)
curl -s "https://$HOST/v1/orders/ORDER_ID" -H "Authorization: Bearer $KEY"

# 在第一个验证码前取消
curl -s -X POST "https://$HOST/v1/orders/ORDER_ID/cancel" -H "Authorization: Bearer $KEY"

错误码

可选参数 warehouse 决定订单用 GET /v1/services 返回的 offers[] 中的哪一项:0 表示有库存且最便宜的一项,99 表示自动选择,缺货时换下一项。用 99 时如果全部都租不到邮箱,会返回 ALL_WAREHOUSES_EXHAUSTED,同样不扣费。

测试自动化建议

Python、Node.js、PHP、C# 和 curl 的现成客户端,都在公开的 otpgmail-email-otp-api 仓库里。完整的退款规则见退款与质保政策,获取 API 密钥请登录应用。

在 CI 和测试环境中使用

常见问题

为什么需要 Idempotency-Key 请求头?

为了在连接中断、请求被重发时,不会再租一个邮箱。只有重试同一个订单时才复用同一个密钥,每个新订单都要生成新的 UUID。

max_wait 应该设多少?

取决于服务:GitHub 的验证码通常约 1 分钟就到,ChatGPT 通常要约 1 分钟,有时更久。设得比等待时间还长没有作用,到时系统会自动取消订单并退款。

一次请求可以租多个邮箱吗?

可以,在请求体里加上 quantity 字段,最多 200 个。这时 data 数组里每个邮箱对应一个订单。

验证码到达前,otp[-1] 会返回什么?

在第一个验证码到达之前,otp 是空数组,直接取 otp[-1] 会报错。示例里的 if order["otp"]: 判断正是为了避免这种情况。

相关教程

现在就获取你的验证码

注册账户不收费。分配到邮箱才扣费;等待时间内(最长 25 分钟)没有收到验证码,自动 100% 退款。

找不到你需要的服务?在租用页面点添加服务,如果我们的基础设施支持,就会把它加上。

需要可以登录的 Gmail 账号,而不只是验证码?请看购买短效 Gmail 账号 · 退款与质保