Bahtya/agently-mail
GitHub: Bahtya/agently-mail
通过 Cloudflare Workers 部署的腾讯 Agently Mail 逆向 REST API 封装,为 AI Agent 和自动化场景提供开箱即用的邮件收发能力。
Stars: 0 | Forks: 0
# agently-mail — Cloudflare Workers 上的 agent.qq.com
[](https://workers.cloudflare.com/)
[](https://www.typescriptlang.org/)
[](./LICENSE)
[](https://agently-mail.bahtyar153.workers.dev/me)
**线上 Worker:** | **API 文档:** [`API.md`](./API.md) | **状态:** 逆向工程并已于 2026-07-07 验证线上生效
直接通过 Cloudflare Worker 驱动腾讯的 **Agently Mail** (`@agent.qq.com`):
接收(列表 / 阅读 / 搜索)+ 发送(两阶段)。基于
`@tencent-qqmail/agently-cli` v1.0.7 进行逆向工程,并于 2026-07-07 针对
真实的 `api.agent.qq.com` / `auth.agent.qq.com` 完成了线上验证。
**结论:可行且已验证。** 服务器仅在
`/v1/*` 上强制要求 `Authorization: Bearer`。没有 TLS 指纹识别,没有请求签名,没有 WebSocket,也没有二进制证明。
下方完整的 `curl` 调用已在 Termux 设备上成功运行 —— Worker 的
`fetch()` 也是同理。
## 已验证的协议(线上实测,非猜测)
| 调用 | 结构 |
|---|---|
| **Device-flow init** | `POST https://auth.agent.qq.com/oauth/device?func=1` body `{cli_agentname,cli_agentua,cli_hostname,cli_ua,cli_version}` → `{poll_url, browser_url, input_code, expires_in:600}` |
| **Device-flow poll** | `GET ` (`…?func=2&device_code=…`) → 扫码前为 `authorization_pending`,扫码后为 `{status:"authorized", app_id, access_token, refresh_token, expires_in:3600}` |
| **Refresh** | `POST https://auth.agent.qq.com/oauth/token` form-encoded `grant_type=refresh_token&refresh_token=…&client_id=cli_002e8cd1e54a3889&clientversion=1.0.7` → `{access_token, refresh_token, expires_in}`。**无 app_secret。** 会轮换 refresh_token。 |
| **Data** | `GET/POST https://api.agent.qq.com/v1/...` 仅需添加 header `Authorization: Bearer `。 |
| **Send (2-phase)** | `POST /v1/aliases/{aid}/messages/send` (无 token) → `{error:{code:"CONFIRMATION_REQUIRED", details:{confirmation_token:"ctk_…", operation_summary}}}`。再次 POST **相同的 body + `confirmation_token`** → `{queued:true}`。 |
`client_id` = `cli_002e8cd1e54a3889` — **公开**,内嵌于 CLI 二进制文件中,所有人通用。
**不存在/不需要 app_secret**(与二进制文件中残留的 struct 标签相反)。
## 获取 agent.qq.com 的 token(三种方法)
device flow 的核心是人扫微信二维码,**只需做一次**。目标:拿到 `access_token` + `refresh_token`
两个值(都不长期固定:access 约 1 小时过期、refresh 每次刷新轮换;Worker 部署后会自动维护,你不用管)。
### 方法 A:`agently-cli` 二进制(普通 macOS / Linux / Windows)
```
npm i -g @tencent-qqmail/agently-cli
agently-cli auth login # 打开链接 → 微信扫码授权
agently-cli +me # 确认登录成功
```
登录后 token 存进系统 keychain。要拿**明文**喂给 Worker,从 keychain 取;或更省事——直接用方法 B。
### 方法 B:原始 device-flow `curl`(任何机器,含 Termux)— 推荐
```
# 1) 发起 device flow,记下返回里的 device_code
curl -s -X POST 'https://auth.agent.qq.com/oauth/device?func=1' \
-H 'content-type: application/json' \
-d '{"cli_agentname":"Claude Code","cli_agentua":"claude","cli_hostname":"localhost","cli_ua":"agently-cli/1.0.7","cli_version":"1.0.7"}'
# 返回: {"poll_url":"...?func=2&device_code=dc_xxx","browser_url":"...","input_code":"ic_xxx","expires_in":600}
# → 打开 browser_url,微信扫码授权(device_code 600 秒内有效)
# 2) 轮询拿 token
curl -s 'https://auth.agent.qq.com/oauth/device?func=2&device_code=dc_xxx'
# 未授权: {"status":"pending",...}
# 已授权: {"status":"authorized","app_id":"cli_002e8cd1e54a3889","access_token":"...","refresh_token":"...","expires_in":3600}
```
记下 `access_token` 和 `refresh_token`。(`app_id` 即公开常量 client_id,无需特别记。)
### 方法 C:已有 token 直接注入(`AGENTLY_ACCESS_TOKEN`)
若已从别处拿到 access_token(如 CLI keychain 导出),用 `agently-cli` 时设
`AGENTLY_ACCESS_TOKEN=` 可跳过登录。但此法**只有 access_token、无 refresh_token**,
Worker 无法长期刷新,仅适合临时验证。
## 部署到 Cloudflare
```
wrangler kv:namespace create TOKEN_STORE # 把返回的 id 填进 wrangler.jsonc
wrangler deploy
```
### 写入 token 到 KV(⚠️ Termux 上的坑)
`wrangler kv key put` 在 Termux/Android 上会 spawn workerd 子进程而失败(`Error: spawn …/workerd`)。
**改用 Cloudflare REST API** 直接写 KV(账号信息见 `wrangler whoami` / `wrangler kv namespace list`):
```
ACCT= # wrangler whoami
NS= # wrangler kv namespace list
TOK="$CLOUDFLARE_API_TOKEN" # wrangler 登录后此环境变量已设
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCT/storage/kv/namespaces/$NS/values/access_token?expiration_ttl=3600" \
-H "Authorization: Bearer $TOK" -H "Content-Type: text/plain" --data-binary ""
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCT/storage/kv/namespaces/$NS/values/refresh_token" \
-H "Authorization: Bearer $TOK" -H "Content-Type: text/plain" --data-binary ""
```
### 设 Worker 自身鉴权密钥(API_TOKEN)+ 重置
```
python3 -c "import secrets;print(secrets.token_hex(32))" > .api_token # 256-bit 共享密钥
wrangler secret put API_TOKEN < .api_token
wrangler deploy
# 丢了就重新生成、put、deploy;调用方用新 token(见 API.md)。
```
## 使用
```
GET /me
POST /list {"limit":10,"dir":"inbox"}
POST /read {"id":"msg_…"}
POST /search {"q":"report","search_in":"SEARCH_IN_SUBJECT"}
POST /send {"to":["a@b.com"],"subject":"Hi","body":"hi"} → phase 1 (token+summary)
POST /send/confirm {"msg":{…same…},"confirmation_token":"ctk_…"} → phase 2 (queued)
```
Cron `*/2 * * * *` 会轮询收件箱并记录新的 `message_id`(可接入 Queue/webhook
以推送到你的 agent)。
## 唯一的真实风险 — 已验证通过
**Cloudflare 出口 IP 信誉 vs 腾讯大陆 WAF**(服务器会设 `mmlas-verifyresult` 风控头)。
**已于 2026-07-07 实测:从 Cloudflare 边缘 `curl /me` 返回正常 `{"data":{...}}`,
未触发 403/429/timeout** —— CF 默认出口能直连 `api.agent.qq.com`。
若日后腾讯收紧风控导致 403/429/超时,解法:Cloudflare **Dedicated Egress IPs**
或经 CN 友好 VPS 中转。验证命令:`curl -H "Authorization: Bearer $API_TOKEN" /me`。
标签:RESTful API, TypeScript, 云函数, 云资产清单, 安全插件, 提示词优化, 程序员工具, 网络调试, 自动化, 自动化攻击, 逆向工程, 邮件API