diff --git a/注册与邮箱池接口文档.md b/注册与邮箱池接口文档.md index c986a21..46af820 100644 --- a/注册与邮箱池接口文档.md +++ b/注册与邮箱池接口文档.md @@ -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` -但业务含义和回传规则是一致的。 - -## 最后一句 - -注册机业务方不需要理解系统内部实现,你们只要按这套规则接: - -- 领号 -- 干活 -- 准确回传结果 - -这套流程就能跑通。 +业务含义与内部接口完全一致。