# iCloud / yx66.email 邮箱系统 API 文档

更新时间：2026-08-25

本文档覆盖当前 Flask 服务暴露的全部 HTTP API。示例中的 token 均为占位符，文档不会包含任何真实凭据。

## 1. 基础信息

- 默认内网服务：`http://127.0.0.1:5050`
- 生产入口：以实际反代域名为准
- 数据格式：除 `/pickup/<token>` 页面、`/api/docs` Markdown、SSE 流之外，API 默认返回 JSON
- 时间字段：ISO-8601 字符串；界面按北京时间展示

## 2. 认证

如果服务配置了 `ADMIN_ACCESS_TOKEN`、`API_ACCESS_TOKEN` 或 `API_ACCESS_TOKENS`，所有 `/api/*` 业务接口默认需要认证；公共例外是 `/api/docs`、`/api/openapi.json`，以及带独立 SMS token 的 `/api/sms/webhook`。

支持两种 API 调用认证方式：

```bash
Authorization: Bearer <API_TOKEN>
```

或：

```bash
X-API-Token: <API_TOKEN>
```

兼容：`X-Admin-Token: <API_TOKEN>`。

`API_ACCESS_TOKEN` / `API_ACCESS_TOKENS` 用于外部 API 客户端；未单独设置时，`ADMIN_ACCESS_TOKEN` 也可作为 Bearer token 使用。不要把 token 放在 query string。

未认证时返回：

```json
{"ok": false, "error": "unauthorized", "message": "API 调用请使用 Authorization: Bearer <token> 或 X-API-Token。"}
```

HTTP 状态码：`401`。

## 3. CORS

默认不开放跨域。需要浏览器跨域调用时设置：

```bash
API_CORS_ORIGINS="https://your-admin.example,https://another.example"
```

或仅在受控环境里使用：

```bash
API_CORS_ORIGINS="*"
```

允许请求头：`Authorization, Content-Type, X-API-Token, X-Admin-Token, X-SMS-Webhook-Token, X-Webhook-Token`。

## 4. 通用约定

- 成功通常包含 `ok: true`，部分历史接口只返回业务字段。
- 失败通常包含 `ok: false` 或 `error`。
- 删除/启停/导出接口只作用于持久化地址池，不删除历史邮件文件。
- `@icloud.com` HME alias 是 Apple 隐私邮箱；`@yx66.email` 是自建域名收信地址池，两者不会混用。
- `include_discovered=1` 只表示展示“收信发现地址”，不是持久化地址池。

## 5. 快速调用示例

```bash
export BASE_URL="https://your-domain.example"
export API_TOKEN="替换成实际 API token"

curl -sS "$BASE_URL/api/local-mail/status" \
  -H "Authorization: Bearer $API_TOKEN"

curl -sS "$BASE_URL/api/local-mail/mailboxes/generate" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domain":"yx66.email","mode":"sequence","prefix":"signup","start":0,"width":3,"count":10,"label":"landing"}'
```

## 6. 健康检查与文档

### GET `/api-docs`

浏览器可读的 API 文档页面。未登录时可从登录页进入；登录 Web UI 后也可从首页左侧栏或顶部按钮进入。

### GET `/docs`

`/api-docs` 的短路径别名。

### GET `/healthz`

公共健康检查，不需要认证。

响应：

```json
{"ok": true}
```

### GET `/api/docs`

返回本 Markdown 文档。公共可读，不需要 API 认证。

### GET `/api/openapi.json`

返回机器可读 OpenAPI 3.0 描述。公共可读，不需要 API 认证。

## 7. 账号与 Apple/HME 登录 API

### GET `/api/state`

返回全局状态、账号统计、任务状态。

响应字段：`running`, `creating`, `round_status`, `total_created`, `today_created`, `cookies_ok`, `alias_count`, `alias_active`, `active_accounts` 等。

### GET `/api/accounts`

返回账号列表。不会返回 cookie、Apple 密码、App 专用密码、加密密码、代理凭据。

主要响应字段：

```json
{
  "accounts": [
    {
      "id": "acc_xxx",
      "name": "账号名",
      "real_email": "user@example.com",
      "status": "active",
      "alias_total": 100,
      "alias_active": 100,
      "has_cookies": true,
      "has_app_password": false,
      "has_protocol_login": true,
      "mail_mode": "local_domain",
      "mail_ready": true,
      "mail_status_text": "自建邮箱收信正常",
      "needs_app_password": false,
      "smtp_ready": true,
      "local_store_ready": true
    }
  ],
  "count": 1
}
```

### POST `/api/accounts/add`

通过 Cookie 添加账号。

请求：

```json
{
  "name": "主号",
  "cookie_input": "Cookie Header String 或 Cookie JSON",
  "host": "icloud.com"
}
```

`host` 可选：`icloud.com` / `icloud.com.cn`；无效时自动从 Cookie 内容判断。

响应：`ok`, `id`, `name`, `real_email`, `alias_total`, `alias_active`, `status`, `error`。

### POST `/api/accounts/add_by_protocol`

同步协议登录并添加账号。可能因 2FA 需要改用异步接口。

请求：

```json
{
  "apple_id": "user@example.com",
  "password": "Apple 密码",
  "region": "icloud.com",
  "name": "主号",
  "two_factor_code": "123456",
  "sms_phone_hint": "+1******1234"
}
```

响应：`ok`, `account`, `two_factor_required`, `error` 等。接口不会回显密码。

### POST `/api/accounts/add_by_protocol_start`

启动异步协议登录任务，适合 2FA/SMS 自动转发场景。

请求字段同 `/api/accounts/add_by_protocol`。

响应 HTTP `202`：

```json
{
  "ok": true,
  "job_id": "job_xxx",
  "status": "running|waiting_2fa|completed|failed",
  "message": "..."
}
```

### GET `/api/accounts/protocol_login/<job_id>`

查询异步协议登录状态。

响应：`ok`, `job_id`, `status`, `message`, `account`, `error`, `created_at`, `updated_at`。

### POST `/api/accounts/protocol_login/<job_id>/code`

提交 2FA 验证码。

请求：

```json
{"code":"123456"}
```

响应：`ok`, `status`, `message`。

### POST `/api/accounts/<account_id>/refresh_login`

使用已保存的加密协议登录凭据刷新账号 Cookie。

响应：`ok`, `account`, `error`。

### POST `/api/accounts/<acc_id>/validate`

校验账号登录/HME 状态并刷新账号统计。

响应：`ok`, `account`, `error`。

### POST `/api/accounts/<acc_id>/remove`

删除账号，并清理该账号关联的本地数据：取件链接、latest email 缓存、导出历史、IMAP 缓存、邮件正文缓存。

响应：

```json
{
  "ok": true,
  "removed": true,
  "cleanup": {
    "pickup_links": 10,
    "latest_emails": 10,
    "export_history": 10
  }
}
```

### POST `/api/accounts/<acc_id>/app-password`

设置并测试 iCloud IMAP App 专用密码。自建域名收信模式下这是可选高级功能。

请求：

```json
{
  "icloud_email": "user@icloud.com",
  "app_password": "xxxx-xxxx-xxxx-xxxx"
}
```

仅在测试连接成功后保存；失败不会覆盖旧配置。响应：`ok`, `inbox_count`, `error`。

## 8. HME alias 创建与列表 API

### POST `/api/accounts/<acc_id>/create`

为单个账号创建 HME alias。

请求：

```json
{"count": 5, "label": "可选标签"}
```

约束：`count` 为 `1..750`。

响应：

```json
{
  "ok": true,
  "emails": ["alias@icloud.com"],
  "created": 1,
  "errors": 0,
  "error": null
}
```

### GET `/api/aliases`

从 Apple/HME 拉取全部账号的 alias 与状态，并写入本地 latest email 缓存。

响应：

```json
{
  "ok": true,
  "aliases": [
    {"email":"alias@icloud.com","account_id":"acc_xxx","label":"...","active":true}
  ],
  "count": 1,
  "accounts": {},
  "failures": {}
}
```

如果部分账号失败，`ok=false`，`failures` 包含失败账号详情，但成功账号的 alias 仍返回。

### GET `/api/emails`

读取本地 latest email 缓存，用于前端邮箱列表。会自动清理旧账号/无效/重复缓存行，避免出现无法生成取件链接的“生成失败”垃圾项。

查询参数：

- `limit`: 可选，返回最新 N 条。

响应字段：`emails`, `count`, `exported_count`, `unexported_count`。

每项字段：`email`, `account_id`, `created_at`, `pickup_url`, `exported`, `exported_at`。

## 9. 批量创建 API

### POST `/api/create-batch`

创建/追加批量 HME alias 任务。

请求：

```json
{
  "account_ids": ["acc_xxx"],
  "count_per_account": 10,
  "interval": 0,
  "label": "批次标签"
}
```

响应 HTTP `202`：`ok`, `job_id`, `job`。

如果目标账号已有任务运行，返回 `409`。

### GET `/api/create-batch/<job_id>`

查询批量任务。

响应：`ok`, `job`。

### GET `/api/create-batch-current`

查询当前任务；无任务时 `job` 为 `null`。

## 10. 自建域名邮箱 / 地址池 API

### GET `/api/local-mail/status`

返回自建 SMTP 收信状态、地址池数量和本地邮件统计。

响应：

```json
{
  "ok": true,
  "domains": ["yx66.email", "mail.yx66.email"],
  "primary_domain": "yx66.email",
  "count": 12,
  "recipients": [],
  "mailbox_count": 0,
  "discovered_count": 8,
  "mailbox_active": 0,
  "mailbox_exported": 0,
  "smtp_ready": true,
  "local_store_ready": true,
  "mail_ready": true,
  "mail_status_text": "自建邮箱收信正常",
  "mx_status_text": "MX -> mail.yx66.email"
}
```

`mail_ready` 必须同时满足域名已配置、SMTP 可连接、本地存储就绪。

### GET `/api/local-mail/messages`

查询本地 SMTP 收到的邮件列表。

查询参数：

- `recipient`: 可选；精确邮箱匹配时可查 `@yx66.email` 本地地址，也可查 `@icloud.com` HME alias 元数据。
- `limit`: 默认 `100`，最大 `500`。
- `offset`: 默认 `0`。

响应：`ok`, `messages`, `count`。

每封邮件包含：`id`, `from`, `mail_from`, `to`, `envelope_recipients`, `header_recipients`, `local_recipients`, `subject`, `date`, `received_at`, `hme_alias`, `hme_forward_to` 等。

### GET `/api/local-mail/messages/<msg_id>`

读取单封本地邮件详情与正文。

响应：`ok`, `message`；`message` 包含 `body_text`, `body_html`, `attachments`。

### POST `/api/local-mail/test`

写入一封本地测试邮件，用于验证存储与 UI。

请求：

```json
{
  "to": "test@yx66.email",
  "subject": "自建邮箱测试",
  "body": "测试正文"
}
```

`to` 必须属于 `LOCAL_MAIL_DOMAINS`。

### GET `/api/local-mail/mailboxes`

查询自建邮箱地址池。

查询参数：

- `include_discovered`: 默认 `false`。设为 `1/true` 时同时显示收信发现地址。
- `search`: 搜索邮箱、标签、批次、备注。
- `active`: `all|active|inactive`。
- `exported`: `all|exported|unexported`。
- `label`: 精确标签过滤。
- `batch_id`: 精确批次过滤。
- `limit`: 默认 `500`，最大 `2000`。
- `offset`: 默认 `0`。

响应：`ok`, `mailboxes`, `total`, `include_discovered`, `summary`, `overall_summary`。

地址字段：`email`, `domain`, `label`, `batch_id`, `created_at`, `active`, `exported_at`, `note`, `mail_count`, `latest_at`, `hme_aliases`, `discovered`。

### POST `/api/local-mail/mailboxes/generate`

生成并持久化自建邮箱地址池。

请求：

```json
{
  "domain": "yx66.email",
  "mode": "random|sequence|custom",
  "count": 10,
  "prefix": "signup",
  "start": 0,
  "width": 3,
  "label": "项目标签",
  "batch_id": "batch-001",
  "note": "备注",
  "custom": "one\ntwo\nthree@yx66.email"
}
```

规则：

- 单次最多 1000 个。
- 完整邮箱必须属于 `LOCAL_MAIL_DOMAINS`。
- `sequence` 支持 `start=0`。
- 自定义数量不能超过 `count`。

响应：`ok`, `mailboxes`, `count`, `created_count`, `duplicates`。

### POST `/api/local-mail/mailboxes/export`

导出地址池并可标记导出状态。

请求：

```json
{
  "emails": ["a@yx66.email", "b@yx66.email"],
  "format": "txt|csv",
  "mark_exported": true
}
```

说明：

- `emails` 为空时默认导出全部未导出的持久化地址。
- `mark_exported=false` 可恢复为未导出。
- discovered 地址不会被导出或标记，会出现在 `not_persisted`。
- 非本地域名或畸形邮箱会出现在 `invalid`。

响应：`ok`, `filename`, `content`, `count`, `mailboxes`, `changed`, `changed_count`, `not_persisted`, `invalid`。

### POST `/api/local-mail/mailboxes/<email>/toggle`

启用/停用持久化地址池项。

请求：

```json
{"active": false}
```

`active` 省略时切换当前状态。字符串 `"false"/"0"` 会正确解析为 false；非法布尔值返回 `400`。

响应：`ok`, `mailbox`。

### DELETE `/api/local-mail/mailboxes/<email>`

删除持久化地址池项。不会删除历史邮件。

响应：`ok`, `deleted`, `email`。

## 11. 收件箱 / 邮件读取 API

### GET `/api/accounts/<acc_id>/inbox`

读取账号收件箱摘要。

查询参数：`limit`, `force`。

如果账号走自建域名收信，响应含 `source: "local_domain"`，读取本地 SMTP/HME 存储；否则读取 iCloud IMAP。

### GET `/api/accounts/<acc_id>/inbox-stream`

SSE 流式读取账号收件箱。

事件格式：

```text
data: {"type":"start"}

data: {"type":"email","count":1,"email":{...}}

data: {"type":"done","count":1}
```

### GET `/api/accounts/<acc_id>/mail/<alias_email>`

查询指定 HME alias 的邮件。

查询参数：`limit`, `days`, `force`。

响应：`emails`, `count`, `alias`, `source`。

### GET `/api/accounts/<acc_id>/alias-mail`

按 alias 聚合查询账号邮件。

查询参数：`force`。

响应：`by_alias`, `total`, `cached`, `source`。

### GET `/api/accounts/<acc_id>/message/<msg_id>`

读取账号邮件正文。本地邮件 ID 以 `lm_` 开头时直接读取本地存储；否则走 IMAP。

响应：`ok`, `message`, `source`。

### GET `/api/mail`

按主邮箱地址查询邮件。

查询参数：

- `email`: 主 iCloud 邮箱/账号邮箱。
- `alias`: 可选，指定 alias。
- `limit`: 默认 `20`。
- `days`: 默认 `30`。

响应：指定 alias 时返回 `emails`, `count`, `alias`, `account`；未指定时返回 `by_alias`, `total`, `account`。

## 12. 取件链接 API

### GET `/api/pickup-links`

返回全部有效取件链接。不会返回裸 token 字段，只返回完整 URL。

响应：

```json
{
  "links": [
    {"account_id":"acc_xxx","email":"alias@icloud.com","url":"https://.../pickup/<opaque>","created_at":"..."}
  ],
  "count": 1
}
```

### POST `/api/pickup-links/<acc_id>/<alias_email>`

为指定 alias 创建或读取现有取件链接。

响应：`ok`, `url`, `email`, `account_id`, `created_at`。

### DELETE `/api/pickup-links/<acc_id>/<alias_email>`

撤销指定取件链接。

响应：`ok`, `revoked`。

### POST `/api/pickup-links/export`

导出未导出的取件链接，并标记导出历史。

请求：

```json
{"emails": ["alias@icloud.com"]}
```

响应：`ok`, `lines`, `count`, `skipped`。每行格式：`alias----pickup_url`。

### POST `/api/export-history/restore`

将指定 alias 恢复为未导出。

请求：

```json
{"emails": ["alias@icloud.com"]}
```

响应：`ok`, `restored`。

## 13. 公共取件页面/API

以下接口通过不可猜测 `/pickup/<token>` 访问，不需要管理员/API token。token 在 URL 内，调用方应保护链接。

### GET `/pickup/<token>`

返回取件 HTML 页面。

### GET `/pickup/<token>/messages`

读取该 alias 的邮件列表。

查询参数：`force=1` 可触发刷新。

响应：`emails`, `count`, `refreshing`, `error`, `warning`。

### GET `/pickup/<token>/message/<msg_id>`

读取指定邮件正文。

响应：

- `200`: `ready: true`, `message`
- `202`: `ready: false`, `refreshing: true|false`
- `404`: 邮件不存在或链接无效

## 14. SMS / 2FA API

### GET `/api/sms/ping`

SMS 服务探活。

响应：`ok`, `message`。

### POST `/api/sms/upload`

上传验证码，管理员/API token 认证。

请求：

```json
{"code":"123456","sender":"Apple","message":"...","device_id":"android-1"}
```

响应：`success`, `message`, `data`。

### GET `/api/sms/latest`

读取最近一条验证码记录，管理员/API token 认证。

### GET `/api/sms/recent`

读取最近验证码记录，管理员/API token 认证。

查询参数：`limit`。

### GET|POST `/api/sms/webhook`

Android 短信转发入口。可用独立 webhook token，不需要管理员 Cookie。

推荐认证：

```bash
X-SMS-Webhook-Token: <SMS_WEBHOOK_TOKEN>
```

或：

```bash
Authorization: Bearer <SMS_WEBHOOK_TOKEN>
```

兼容旧版 query：`?token=...`，可通过 `SMS_WEBHOOK_ALLOW_QUERY_TOKEN=0` 禁用。

请求字段兼容：`content`, `org_content`, `message`, `msg`, `text`, `body`, `sms`, `sms_body`, `raw`, `from`, `sender`, `device_id`, `simInfo` 等。

响应：`success`, `message`, `data`。日志会脱敏验证码和敏感字段。

## 15. 调度与日志 API

### POST `/api/scheduler/start`

启动自动创建调度器。

响应：`ok`, `already_running`。

### POST `/api/scheduler/stop`

停止自动创建调度器。

响应：`ok`。

### GET `/api/logs`

读取最近运行日志。

响应：`logs`。

### GET `/api/log-stream`

SSE 日志流。

事件格式：

```text
data: {"seq":1,"ts":"...","level":"info","msg":"..."}
```

## 16. 推荐接入流程

### 自建域名地址池

1. `GET /api/local-mail/status` 确认 `mail_ready=true`。
2. `POST /api/local-mail/mailboxes/generate` 批量生成 `@yx66.email`。
3. `GET /api/local-mail/mailboxes` 展示地址池。
4. `POST /api/local-mail/mailboxes/export` 导出并标记已导出。
5. `GET /api/local-mail/messages?recipient=<email>` 查看收件。

### Apple HME alias

1. `GET /api/accounts` 找到可用账号。
2. `POST /api/accounts/<acc_id>/create` 或 `POST /api/create-batch` 创建 HME alias。
3. `GET /api/emails` 获取 alias 与 pickup URL。
4. `POST /api/pickup-links/export` 导出取件链接。
5. `GET /api/accounts/<acc_id>/mail/<alias>` 查询 alias 邮件。

## 17. 常见错误码

- `400`: 参数错误、邮箱域名非法、格式非法。
- `401`: 未提供有效 API token。
- `404`: 账号、邮箱、邮件或取件链接不存在。
- `409`: 账号已有创建任务运行。
- `500`: 服务内部错误或上游异常。
