codex / docs /temp-mail-external-api.md
webhook's picture
Upload 137 files
89419ea verified
|
Raw History Blame Contribute Delete
9.85 kB

Temp Mail 域名池与外部注册 API 说明

本文档说明本项目最近新增/补强的两部分能力:

  1. temp_mail 邮箱服务支持域名池与 Worker 域名 API
  2. 外部调用方可通过 HTTP API 创建注册批次、查询状态、取消任务

配套文档:


1. Temp Mail 域名池

1.1 适用场景

项目内新增了 temp_mail 邮箱类型,用于接入你自建的临时邮箱服务,例如:

  • https://apmail.889110.xyz/

服务端支持通过管理接口返回当前可用域名池,例如:

  • GET /admin/domains

请求头:

  • x-admin-auth: <admin_password>

1.2 支持的配置项

temp_mail 服务配置支持以下字段:

字段 必填 说明
base_url 是 临时邮箱服务地址,如 https://apmail.889110.xyz
admin_password 是 管理接口密码,对应请求头 x-admin-auth
domains 否 域名池,数组或逗号分隔字符串,优先级最高
domain 否 单个回退域名
enable_prefix 否 是否保留旧版 tmp 前缀,默认 false
timeout 否 请求超时,默认 30
max_retries 否 请求重试次数,默认 3

1.3 域名解析优先级

创建邮箱时,域名来源按以下优先级解析:

  1. config.domains
  2. Worker GET /admin/domains
  3. config.domain

如果三者都拿不到可用域名,则创建邮箱失败。

1.4 随机邮箱生成规则

  • 默认生成纯随机本地名,不再强制 tmp 前缀
  • 如果配置 enable_prefix=true,则继续使用旧版 tmpxxxxx 风格
  • 最终会从当前可用域名池中随机选择一个域名拼接地址

1.5 可用服务展示

以下两个接口会展示 temp_mail 的域名摘要:

  • Web UI: GET /api/registration/available-services
  • 外部 API: GET /api/external/capabilities

返回中会包含:

  • domain_count
  • domains_preview
  • domain_source

其中 domain_source 可能为:

  • config_domains
  • worker_api
  • config_fallback
  • none

注意:接口只暴露安全摘要,不会把 admin_password 等敏感信息返回给前端或外部调用方。


2. 外部注册 API

2.1 功能概览

外部 API 允许调用方不直接操作 Web UI,而是通过 HTTP 请求:

  • 查询当前可用邮箱类型与上传目标
  • 创建异步注册批次
  • 查询批次状态
  • 取消批次

2.2 鉴权方式

需要在系统设置中启用:

  • external_api_enabled
  • external_api_key

请求头使用:

X-API-Key: <your_api_key>

未启用时返回 403;密钥错误时返回 401。

2.2.1 API Key 从哪里来

当前项目里,外部 API Key 不是“调用方自己申请”的,也不是接口动态下发的。

它来自系统管理员在项目配置中设置的:

  • external_api_enabled
  • external_api_key

也就是说:

  1. 管理员先在系统里启用外部 API
  2. 管理员在系统里填写一个 external_api_key
  3. 再把这个值发给第三方调用方

第三方真正拿到的就是这个管理员配置的值,然后放到:

X-API-Key: 你拿到的那个值

当前版本没有单独的“获取 API Key / 轮换 API Key”开放接口。
如果要换 Key,需要由系统管理员修改配置后,再重新发给对接方。

2.3 能力查询

接口:

GET /api/external/capabilities

用于返回:

  • 支持的邮箱类型
  • 当前可用邮箱服务
  • 当前可用上传目标
  • 外部 API 是否启用

其中邮箱类型包含数据库内启用的:

  • outlook / moe_mail / temp_mail / duck_mail / freemail / imap_mail

其中临时邮箱能力在外部 API 中统一使用 temp_mail 枚举,不再暴露旧的 tempmail 占位。

能力接口返回的每个可选服务,都会带:

  • id
  • name
  • priority

对于 temp_mail,还会带:

  • domain_count
  • domains_preview
  • domain_source

2.3.1 service_id 不是 0/1 猜出来的

第三方在创建批次时看到的:

  • email.service_id
  • upload.service_id

都不是让你自己猜 “0 代表哪个、1 代表哪个”。

正确方式是:

  1. 先调 GET /api/external/capabilities
  2. 读取返回里的服务列表
  3. 按 name 找到你想用的服务
  4. 把该服务对应的 id 填回创建请求里的 service_id

也就是说,真正的映射关系来自 capabilities 返回值,而不是文档里写死。

例如能力返回里可能是:

{
  "email_types": [
    {
      "type": "temp_mail",
      "services": [
        {"id": 3, "name": "Worker temp mail A"},
        {"id": 7, "name": "Worker temp mail B"}
      ]
    }
  ],
  "upload_providers": [
    {
      "provider": "sub2api",
      "services": [
        {"id": 1, "name": "sub2-main"},
        {"id": 4, "name": "sub2-backup"}
      ]
    }
  ]
}

那你在创建批次时:

  • 传 email.service_id=3,表示使用 Worker temp mail A
  • 传 upload.service_id=4,表示上传到 sub2-backup

结论:service_id 只认 capabilities 当前返回的 id,不要手写猜测,也不要假设某个数字永远对应某个服务。

2.4 创建注册批次

接口:

POST /api/external/registration/batches

请求体示例:

{
  "count": 5,
  "idempotency_key": "demo-batch-001",
  "email": {
    "type": "temp_mail",
    "service_id": 1
  },
  "upload": {
    "enabled": true,
    "provider": "sub2api",
    "service_id": 1
  },
  "execution": {
    "mode": "pipeline",
    "concurrency": 1,
    "interval_min": 5,
    "interval_max": 15
  }
}

字段约束:

  • count: 1 ~ 100
  • email.type: 必填
  • email.service_id: 可选
  • upload.provider: 仅在 upload.enabled=true 时必填
  • upload.provider: 仅支持 sub2api / cpa / tm
  • execution.mode: pipeline 或 parallel
  • execution.concurrency: 1 ~ 50
  • execution.interval_max >= execution.interval_min

关于 service_id 的默认行为:

  • email.service_id 不传:系统按该邮箱类型的当前可用规则自动选
  • upload.service_id 不传:系统按该上传 provider 当前启用且优先级最高的服务自动选

返回规则:

  • 首次创建成功:HTTP 202
  • 如果 idempotency_key 命中历史批次:HTTP 200

2.5 查询批次状态

接口:

GET /api/external/registration/batches/{batch_uuid}

返回字段包含:

  • batch_uuid
  • status
  • requested_count
  • completed_count
  • success_count
  • failed_count
  • upload_success_count
  • upload_failed_count
  • failure_reason
  • recent_errors

状态可能包括:

  • pending
  • running
  • completed
  • completed_partial
  • failed
  • cancelled

2.6 取消批次

接口:

POST /api/external/registration/batches/{batch_uuid}/cancel

规则:

  • pending / running 可取消
  • 已结束批次不可重复取消,返回 400
  • 批次不存在返回 404

2.7 错误码约定

场景 状态码
API 未启用 403
API Key 错误 401
请求体验证失败 422
批次不存在 404
业务参数不合法 400
外部批次服务不可用 503

3. 外部批次执行行为

3.1 持久化

外部批次及其子项会持久化到数据库:

  • external_registration_batches
  • external_registration_batch_items

同时为每个子项生成独立 registration_task_uuid,便于复用现有注册执行链路。

3.2 幂等

如果创建批次时传入 idempotency_key,系统会优先复用已有批次,避免重复创建。

3.3 重启恢复

服务启动时会尝试恢复中断批次:

  • pending / running 的外部批次会被标记为失败
  • 失败原因记为 service_restarted

这样可以避免系统重启后外部调用方看到“永远卡在运行中”的脏状态。

3.4 上传行为

如果启用了上传:

  • 注册成功后才会执行上传
  • 会优先按注册结果里的 email 查账号
  • 如找不到,再按 account_id 回退查找
  • 上传结果会分别统计成功数和失败数

4. 当前测试覆盖

本轮功能已补充并验证以下覆盖:

  • temp_mail 本地名生成与域名随机选择
  • temp_mail 域名解析优先级与回退逻辑
  • Worker 域名 API 集成路径
  • available-services / capabilities 的域名摘要展示
  • 外部 API 鉴权、参数校验、错误码映射
  • 外部批次创建、幂等、状态汇总、取消、重启恢复
  • 外部批次执行中的预失败项、上传成功/失败、account_id 回退查找
  • 服务选择的拒绝分支与边界约束

全量测试验证结果:

  • 134 passed

5. 使用建议

5.1 如果你想让 temp_mail 自动从多个域名中随机取

建议只配置:

  • base_url
  • admin_password
  • domain(仅作回退)

然后由 Worker GET /admin/domains 统一返回真实域名池。

5.2 如果你想固定只用部分域名

直接在该邮箱服务配置中填写:

{
  "domains": ["a.example.com", "b.example.com"]
}

此时系统会优先使用配置内域名池,而不会再请求 Worker 域名接口。

5.3 如果你要给第三方系统对接

优先使用:

  • GET /api/external/capabilities
  • POST /api/external/registration/batches
  • GET /api/external/registration/batches/{batch_uuid}
  • POST /api/external/registration/batches/{batch_uuid}/cancel

这样调用方只负责“下发任务”和“查结果”,实际邮箱、上传、执行模式等策略仍由系统内配置统一兜底。