docs: update registration and email pool interface documentation

This commit is contained in:
胡绍康 committed 2026-03-17 23:22:55 +08:00
1 parent 70d1f4a8e9
commit 47296f80a8
1 file changed
+369 -370
+369 -370
View File
@@ -1,128 +1,103 @@
# 注册机接入与邮箱池使用说明
# 注册机接入与邮箱池 API 文档
这份文档不是给开发框架人员看的,而是给注册机业务方、脚本接入方、流程运营方看的。
## 📖 概览 Overview
你们真正需要关心的只有 4 件事:
本文档描述邮箱池管理系统的公开 API,供注册机业务方、脚本接入方使用。
1. 账号怎么进入池子
2. 注册机怎么拿号
3. 注册完成后怎么回传结果
4. 不同结果会把账号变成什么状态
**服务定位**:为注册机提供邮箱领取、状态回传、池管理等功能。
如果你只想先跑通,直接看「一页版接入流程」。
**数据格式**:所有请求和响应均使用 JSON 格式。
## 一页版接入流程
**支持 CORS**:支持跨域请求。
### 业务流程
---
1. 运营或后台人员先把邮箱账号导入系统
2. 导入时显式勾选或传入 `add_to_pool=true`
3. 注册机调用领取接口拿一个邮箱
4. 注册机拿到邮箱后去执行注册任务
5. 任务结束后必须回传结果
6. 系统按结果把邮箱改成 `used` / `cooldown` / `available` 等状态
## 🔐 鉴权与通用规则
### 你们只需要调用这 3 个接口
### API Key 获取
- `POST /api/pool/claim-random`
- `POST /api/pool/claim-complete`
- `POST /api/pool/claim-release`
联系系统管理员获取 API Key,在请求头中携带:
`GET /api/pool/stats` 只是查池子情况,可选。
## 先说结论
### 什么样的账号能被注册机拿到
只有同时满足下面条件的账号才会被分配出来:
- 已经导入系统
- 导入时加入了邮箱池
- 当前池状态是 `available`
- 当前账号状态是 `active`
### 注册机拿到邮箱后必须做什么
拿到邮箱后,任务结束时必须二选一:
- 成功或失败后,调用 `claim-complete`
- 中途放弃不用了,调用 `claim-release`
不能拿完不回传。
### 最重要的状态流转
| 任务结果 | 你们回传的 `result` | 邮箱最终状态 |
|---|---|---|
| 注册成功,账号已消耗 | `success` | `used` |
| 长时间没等到验证码,建议冷却后再试 | `verification_timeout` | `cooldown` |
| 供应商风控、被封、被限制 | `provider_blocked` | `frozen` |
| 邮箱密码或凭据已失效 | `credential_invalid` | `retired` |
| 网络问题、临时故障,可以马上重试 | `network_error` | `available` |
这张表就是注册机接入时最关键的业务规则。
## 角色分工
### 后台人员负责
- 导入邮箱账号
- 决定是否把账号加入池子
- 查看池子数量和状态
### 注册机负责
- 领取邮箱
- 用领取到的邮箱执行注册
- 把最终结果准确回传
### 你们不需要关心的内容
- Outlook OAuth 内部换 token 细节
- 后台导入时的内部校验逻辑
- 数据库存储方式
- 内部控制器和仓库层实现
## 账号如何进入邮箱池
账号不是导入后自动进池。
必须在导入账号时明确指定 `add_to_pool=true`,这个账号才会进入池子,初始状态才会是 `available`。
如果没有加池:
- 账号只是存在系统里
- 注册机永远领不到它
这点是整个流程里最容易出错的地方。
## 注册机标准接入流程
## 第一步:领取一个邮箱
接口:
```text
POST /api/pool/claim-random
```
Authorization: Bearer YOUR_API_KEY
```
请求示例:
**测试环境**:联系管理员获取测试 Key(调用限制:100 次/分钟)
### 统一响应格式
所有接口遵循统一的响应格式:
```json
{
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"provider": "outlook"
"success": true,
"data": { ... },
"message": "操作成功"
}
```
字段说明:
失败时:
- `caller_id`:谁在调用,建议写固定的业务方标识或机器标识
- `task_id`:当前这次注册任务的唯一 ID
- `provider`:可选。如果你们只想领 Outlook,就传 `outlook`
```json
{
"success": false,
"error": "error_code",
"message": "错误描述"
}
```
成功返回示例:
### 时间字段约定
所有时间字段使用 ISO 8601 格式:`YYYY-MM-DDTHH:MM:SSZ`
---
## 📋 API 端点列表
### 快速开始
注册机接入只需关注以下 3 个核心接口:
| 接口 | 用途 | 必要性 |
|------|------|--------|
| `POST /api/pool/claim-random` | 领取邮箱 | 必需 |
| `POST /api/pool/claim-complete` | 完成任务回传 | 必需 |
| `POST /api/pool/claim-release` | 释放邮箱 | 必需 |
| `GET /api/pool/stats` | 查看池状态 | 可选 |
---
## 1️⃣ 领取邮箱
### 基本信息
```
POST /api/pool/claim-random
需要鉴权:是
```
### 请求示例
```bash
curl -X POST https://api.example.com/api/pool/claim-random \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"provider": "outlook"
}'
```
### 参数说明
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `caller_id` | string | 是 | 调用方标识,建议使用固定的业务方标识或机器标识,如:`register-worker-1`、`register-cluster-a` |
| `task_id` | string | 是 | 当前注册任务的唯一 ID,如:`job-20260317-0001`、`order-928371` |
| `provider` | string | 否 | 邮箱提供商筛选,传 `outlook` 则只领取 Outlook 邮箱 |
### 成功响应示例
```json
{
@@ -132,25 +107,21 @@ POST /api/pool/claim-random
"email": "demo@outlook.com",
"claim_token": "clm_xxxxx",
"lease_expires_at": "2026-03-17T10:00:00Z"
}
},
"message": "邮箱领取成功"
}
```
你们拿到后要保存这 4 个值:
### 响应字段说明
- `account_id`
- `email`
- `claim_token`
- `lease_expires_at`
| 字段名 | 类型 | 说明 |
|--------|------|------|
| `account_id` | integer | 账号 ID,回传时必需 |
| `email` | string | 邮箱地址 |
| `claim_token` | string | 领取令牌,回传时必需 |
| `lease_expires_at` | string | 租约过期时间,过期前需完成回传或释放 |
其中真正必须原样带回来的,是:
- `account_id`
- `claim_token`
- `caller_id`
- `task_id`
### 领取失败是什么样
### 失败响应示例
```json
{
@@ -160,50 +131,55 @@ POST /api/pool/claim-random
}
```
这表示当前没有可分配邮箱,不是系统崩了。
---
注册机这时应该:
## 2️⃣ 完成任务并回传结果
- 等待
- 稍后重试
- 或切换 provider
### 基本信息
## 第二步:执行注册任务
这一步是你们自己的业务逻辑,系统不关心你们怎么注册,只关心最终结果。
常见动作包括:
- 打开目标网站
- 输入邮箱
- 收验证码
- 验证邮箱
- 完成注册
## 第三步:回传结果
任务做完以后,必须回传。
接口:
```text
```
POST /api/pool/claim-complete
需要鉴权:是
```
请求示例:
### 请求示例
```json
{
"account_id": 12,
"claim_token": "clm_xxxxx",
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"result": "success",
"detail": "注册成功"
}
```bash
curl -X POST https://api.example.com/api/pool/claim-complete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": 12,
"claim_token": "clm_xxxxx",
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"result": "success",
"detail": "注册成功"
}'
```
成功返回示例:
### 参数说明
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `account_id` | integer | 是 | 领取时返回的账号 ID |
| `claim_token` | string | 是 | 领取时返回的令牌 |
| `caller_id` | string | 是 | 必须与领取时的 `caller_id` 一致 |
| `task_id` | string | 是 | 必须与领取时的 `task_id` 一致 |
| `result` | string | 是 | 任务结果,见下方【result 可选值】 |
| `detail` | string | 否 | 详细说明,建议填写失败原因、目标站名称、风控现象等 |
### result 可选值及对应状态
| result 值 | 说明 | 邮箱最终状态 | 使用场景 |
|-----------|------|--------------|----------|
| `success` | 注册成功,账号已消耗 | `used` | 成功完成注册任务 |
| `verification_timeout` | 未收到验证码 | `cooldown` | 长时间未收到验证码,建议冷却后再试 |
| `provider_blocked` | 被供应商风控 | `frozen` | 供应商风控、被封、被限制 |
| `credential_invalid` | 凭据失效 | `retired` | 邮箱密码或凭据已失效 |
| `network_error` | 网络故障 | `available` | 网络问题、临时故障,可立即重试 |
### 成功响应示例
```json
{
@@ -211,35 +187,58 @@ POST /api/pool/claim-complete
"data": {
"account_id": 12,
"pool_status": "used"
}
},
"message": "结果回传成功"
}
```
这里返回的 `pool_status` 就是这个邮箱的最终状态。
## 中途放弃时怎么处理
如果你们已经领到了号,但这次任务不做了,不想把它记成成功或失败,就不要调 `claim-complete`,而是调释放接口。
接口:
```text
POST /api/pool/claim-release
```
请求示例:
### 失败响应示例
```json
{
"account_id": 12,
"claim_token": "clm_xxxxx",
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"reason": "任务取消"
"success": false,
"error": "invalid_claim",
"message": "claim_token 已失效或与 account_id 不匹配"
}
```
成功返回示例:
---
## 3️⃣ 释放邮箱
### 基本信息
```
POST /api/pool/claim-release
需要鉴权:是
```
### 请求示例
```bash
curl -X POST https://api.example.com/api/pool/claim-release \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": 12,
"claim_token": "clm_xxxxx",
"caller_id": "register-worker-1",
"task_id": "job-20260317-0001",
"reason": "任务取消"
}'
```
### 参数说明
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `account_id` | integer | 是 | 领取时返回的账号 ID |
| `claim_token` | string | 是 | 领取时返回的令牌 |
| `caller_id` | string | 是 | 必须与领取时一致 |
| `task_id` | string | 是 | 必须与领取时一致 |
| `reason` | string | 否 | 释放原因 |
### 成功响应示例
```json
{
@@ -247,216 +246,216 @@ POST /api/pool/claim-release
"data": {
"account_id": 12,
"pool_status": "available"
}
},
"message": "邮箱已释放回池"
}
```
这表示该邮箱被放回池子,可以再次分配。
---
## 最推荐的业务回传规则
## 4️⃣ 查看池状态
为了避免业务方乱传结果,建议你们内部直接按下面这套规则接:
### 基本信息
### 场景 1:注册成功
回传:
```json
{
"result": "success"
}
```
结果:
- 邮箱状态变 `used`
- 默认理解为这个号已经消耗掉
### 场景 2:一直收不到验证码
回传:
```json
{
"result": "verification_timeout"
}
```
结果:
- 邮箱状态变 `cooldown`
- 表示不要立刻继续发给下一个任务
### 场景 3:网站风控、邮箱域名被卡、供应商限制
回传:
```json
{
"result": "provider_blocked"
}
```
结果:
- 邮箱状态变 `frozen`
### 场景 4:密码失效、refresh token 失效、邮箱已经不可登录
回传:
```json
{
"result": "credential_invalid"
}
```
结果:
- 邮箱状态变 `retired`
### 场景 5:代理挂了、网络抖动、请求失败,但邮箱本身没问题
回传:
```json
{
"result": "network_error"
}
```
结果:
- 邮箱状态回到 `available`
- 后续可以再次分配
## 业务方最容易踩的坑
### 坑 1:账号导入了,但注册机领不到
一般原因只有两个:
- 导入时没有 `add_to_pool=true`
- 账号不是 `active` 或不在 `available`
### 坑 2:重复回传或回传错任务
`claim-complete` 和 `claim-release` 都要求下面 4 个字段对应同一笔领取记录:
- `account_id`
- `claim_token`
- `caller_id`
- `task_id`
任何一个不一致,系统都会拒绝。
所以注册机必须把领取时的原始参数保存好,不能自己拼。
### 坑 3:拿了号但不回传
这会导致邮箱停留在 `claimed`,影响后续分配。
你们内部必须保证:
- 成功就 `claim-complete`
- 失败也 `claim-complete`
- 放弃就 `claim-release`
### 坑 4:把所有失败都回成 `network_error`
这样会导致本来已经废掉的号继续回池,被重复分配。
特别是下面两种情况不能回 `network_error`:
- 邮箱凭据失效
- 明确被目标站或供应商风控
## 推荐接入规范
### `caller_id` 怎么写
建议固定,不要一会一个名字。
例如:
- `register-worker-1`
- `register-cluster-a`
- `tg-signup-service`
### `task_id` 怎么写
建议每次任务唯一。
例如:
- `job-20260317-0001`
- `order-928371`
- `signup-batch-7-item-23`
### `detail` 怎么写
不是必填,但建议写。
可以写:
- 失败原因
- 目标站名称
- 风控现象
- 错误摘要
这样后面排查方便。
## 你们真正要记住的 5 行规则
1. 只有 `add_to_pool=true` 的邮箱才会被注册机拿到
2. 注册机用 `claim-random` 拿号
3. 任务结束必须回传
4. 成功或失败用 `claim-complete`
5. 中途放弃用 `claim-release`
## 常用接口清单
### 1. 领取邮箱
```text
POST /api/pool/claim-random
```
### 2. 完成任务并回传结果
```text
POST /api/pool/claim-complete
```
### 3. 放弃任务并释放邮箱
```text
POST /api/pool/claim-release
```
### 4. 查看池子数量
```text
GET /api/pool/stats
需要鉴权:是
```
## 补充说明
### 请求示例
如果你们不是直接调用内网接口,而是走外部受控接口,那么路径会对应变成:
```bash
curl -X GET https://api.example.com/api/pool/stats \
-H "Authorization: Bearer YOUR_API_KEY"
```
### 成功响应示例
```json
{
"success": true,
"data": {
"total": 1000,
"available": 850,
"claimed": 120,
"used": 20,
"cooldown": 5,
"frozen": 3,
"retired": 2
},
"message": "查询成功"
}
```
---
## ⚠️ 错误处理
### HTTP 状态码一览
| 状态码 | 说明 |
|--------|------|
| 200 | 请求成功 |
| 400 | 请求参数错误 |
| 401 | 未授权(缺少或无效的 API Key) |
| 403 | 禁止访问 |
| 404 | 资源不存在 |
| 429 | 请求频率超限 |
| 500 | 服务器内部错误 |
### 常见错误响应
#### 缺少 API Key
```json
{
"success": false,
"error": "missing_api_key",
"message": "请在请求头中携带 Authorization: Bearer YOUR_API_KEY"
}
```
#### 请求频率超限
```json
{
"success": false,
"error": "rate_limit_exceeded",
"message": "请求频率超限,请稍后重试"
}
```
#### 无可用邮箱
```json
{
"success": false,
"error": "no_available_account",
"message": "池中没有符合条件的可用邮箱"
}
```
#### claim_token 不匹配
```json
{
"success": false,
"error": "invalid_claim",
"message": "claim_token 已失效或与 account_id 不匹配"
}
```
---
## 📝 使用限制
### 频率限制
- 领取邮箱:60 次/分钟
- 回传结果:120 次/分钟
- 查询状态:300 次/分钟
### 租约超时
领取邮箱后,必须在 `lease_expires_at` 前完成回传或释放。超时未处理的邮箱将自动释放回池。
### 建议重试策略
- 遇到 `429` 错误时,等待 1 秒后重试
- 遇到 `no_available_account` 时,等待 5-10 秒后重试
- 建议使用指数退避算法
---
## 🔄 业务流程图
```
运营导入邮箱(add_to_pool=true)
↓
邮箱进入池子(status=available)
↓
注册机调用 claim-random 领取邮箱
↓
注册机执行注册任务
↓
┌────┴────┐
↓ ↓
成功/失败 中途放弃
↓ ↓
claim-complete claim-release
↓ ↓
邮箱状态更新 邮箱返回池子
```
---
## 🎯 常见问题
### Q1: 账号导入了,但注册机领不到?
**原因**:
1. 导入时没有设置 `add_to_pool=true`
2. 账号状态不是 `active` 或不在 `available`
**解决**:检查导入参数,确保账号正确入池。
### Q2: 回传时提示参数不匹配?
**原因**:`account_id`、`claim_token`、`caller_id`、`task_id` 四个字段必须与领取时完全一致。
**解决**:注册机必须保存领取时的原始参数,不能自行修改。
### Q3: 领取后忘记回传会怎样?
**后果**:邮箱会停留在 `claimed` 状态,影响后续分配。
**建议**:
- 成功或失败都调用 `claim-complete`
- 中途放弃调用 `claim-release`
### Q4: 所有失败都回传 `network_error` 会怎样?
**后果**:已失效的邮箱会继续回池,被重复分配,浪费资源。
**建议**:根据实际失败原因选择正确的 `result` 值。
---
## 📞 联系方式
- 技术支持:[联系管理员]
- 问题反馈:[提交 Issue]
- API 更新通知:[订阅更新]
---
## 📅 更新日志
### v1.0.0 (2026-03-17)
- 初始版本发布
- 支持邮箱领取、回传、释放、查询功能
---
## ⚖️ 使用条款
使用本 API 即表示您同意以下条款:
1. 仅用于合法业务用途
2. 不得恶意刷接口或占用资源
3. 遵守频率限制和租约规则
4. 及时回传任务结果
5. 不得将 API Key 泄露给第三方
---
## 外部接口路径
如果通过外部受控接口调用,路径对应为:
- `/api/external/pool/claim-random`
- `/api/external/pool/claim-complete`
- `/api/external/pool/claim-release`
- `/api/external/pool/stats`
但业务含义和回传规则是一致的。
## 最后一句
注册机业务方不需要理解系统内部实现,你们只要按这套规则接:
- 领号
- 干活
- 准确回传结果
这套流程就能跑通。
业务含义与内部接口完全一致。