File size: 9,846 Bytes
89419ea | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | # Temp Mail 域名池与外部注册 API 说明
本文档说明本项目最近新增/补强的两部分能力:
1. `temp_mail` 邮箱服务支持域名池与 Worker 域名 API
2. 外部调用方可通过 HTTP API 创建注册批次、查询状态、取消任务
配套文档:
- [External API 调用示例](external-api-examples.md)
- [External API 第三方对接速览](external-api-quickstart.md)
- [External API 网站内管理与 API Key 生成方案](external-api-webui-management-plan.md)
---
## 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`
请求头使用:
```http
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. 再把这个值发给第三方调用方
第三方真正拿到的就是这个管理员配置的值,然后放到:
```http
X-API-Key: 你拿到的那个值
```
> 当前版本没有单独的“获取 API Key / 轮换 API Key”开放接口。
> 如果要换 Key,需要由系统管理员修改配置后,再重新发给对接方。
### 2.3 能力查询
接口:
```http
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` 返回值,而不是文档里写死。
例如能力返回里可能是:
```json
{
"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 创建注册批次
接口:
```http
POST /api/external/registration/batches
```
请求体示例:
```json
{
"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 查询批次状态
接口:
```http
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 取消批次
接口:
```http
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 如果你想固定只用部分域名
直接在该邮箱服务配置中填写:
```json
{
"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`
这样调用方只负责“下发任务”和“查结果”,实际邮箱、上传、执行模式等策略仍由系统内配置统一兜底。
|