feat: WmailHub v1.0.0 —— Cloudflare Email Workers 邮件接收与转发平台(本地可用版本)

- Console:React 19 + antd 6.6.5 前端(登录 admin/admin)+ Hono 管理 API
  (Nodes/Domains/Mailboxes/Emails/Webhooks/Keys/OAuth/Admin)
- Node:Bun 转发节点(HMAC 签名、有限重试、心跳、结构化日志、优雅退出)
- Email Worker:Cloudflare email handler + 本地联调入口
- shared:HMAC 协议(docs/04)、wmh_ Key(32 位)、AES-GCM 加密、SSRF 防护
- 邮件管线:postal-mime 解析、附件、catch-all、限额、malformed 降级、TTL 1 天
- Webhook:签名投递、指数退避重试、SSRF 校验、投递日志
- API v1 + MCP(JSON-RPC,六工具,凭据 kind 隔离)
- Cloudflare OAuth:真实 + 本地 sim 模式,自动安装管线(幂等,无需手工命令)
- 测试:bun test 41 例(协议安全/管线/TTL/Webhook/SSRF/MCP/OAuth/鉴权)+ Playwright UI 冒烟
- LOGO/favicon 由 codex CLI 生成
This commit is contained in:
BigCode
2026-09-30 03:34:37 +08:00
commit d4c1334143
87 changed files with 9268 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
# WmailHub 开发设计总览
## 1. 项目定位
WmailHub 是一个基于 Cloudflare Email Workers 的轻量邮件接收与转发平台。
核心原则:
- Cloudflare 负责邮件基础设施。
- Console 是控制平面,包含前端与管理 Node。
- Node 是邮件数据转发平面,无前端、无业务判断。
- Console 通过 Cloudflare OAuth 自动完成 Node、Domain、Mailbox、Email Worker 的配置。
- Node 只能处理被授权 Cloudflare Account 下的域名邮箱。
- Node 与 Console 的通信必须使用 HTTPS + 应用层签名。
- 邮件默认短期保存,例如 1 天,过期自动删除。
- 邮件进入 Console 后才能进入 Webhook、API、MCP 等业务能力。
## 2. 总体架构
```text
Internet
|
v
Cloudflare Email Routing
|
v
Cloudflare Email Worker
|
v
Node
| HTTPS + Request Signature
v
Console Management Node
|
+--> Database
+--> Webhook
+--> API
+--> MCP
+--> Frontend
```
## 3. Console
Console = Frontend + Management Node。
负责:Cloudflare OAuth、Cloudflare Account、Node、Domain、Mailbox、Email、Webhook、API、MCP、Node 安装与配置、数据存储、TTL 清理调度。
用户不执行 Node 安装命令。点击 Add Node 后进入 Cloudflare OAuth,授权后由 Cloudflare API 自动完成安装和配置。
## 4. Node
Node 是纯后端组件,只做:接收 Cloudflare Email Worker 的邮件、将邮件安全转发到 Console。
Node 不做 Domain 判断、Mailbox 判断、邮件业务路由、Webhook、MCP、API、用户权限、邮件长期存储。
Node 收到什么就转发什么。
## 5. 权限边界
一个 Node 与一个 Cloudflare Account 建立绑定。Node A 只能处理 Account A 下配置的 Email Worker,不允许处理其他 Account。
Domain 与 Mailbox 的具体业务信息由 Console 管理,Node 不需要理解这些业务字段。
## 6. 核心邮件流程
```text
Email
|
v
Cloudflare Email Routing
|
v
Email Worker
|
v
Node
|
v
Console
|
+--> Store
+--> Webhook
+--> API
+--> MCP
```
## 7. 生命周期
默认邮件 TTL 为 1 天。数据库记录 expires_at,Cron 定期删除过期记录及对应 R2 对象。
## 8. 第一版明确不做
- 自建 SMTP Server
- IMAP / POP3
- 发件服务器
- 完整邮箱客户端
- 复杂邮件规则引擎
- AI 邮件分析
- 多租户复杂组织系统
- Node 端业务路由
+47
View File
@@ -0,0 +1,47 @@
# WmailHub 系统架构
## Console
Console = Frontend + Management Node,是系统控制中心。
负责 Cloudflare OAuth、Node、Domain、Mailbox、Email、Webhook、API、MCP 以及数据存储。
## Node
Node 是纯后端、无前端的邮件转发节点。
唯一核心流程:Cloudflare Email Worker -> Node -> Console。
Node 不负责 Domain、Mailbox、Webhook、MCP、API、用户权限或业务路由。
## Cloudflare Worker
Email Worker 是邮件入口,只负责接收 Cloudflare Email Event 并安全转发给 Node。
## 控制平面
```text
Cloudflare Account
+-- Node
+-- Domain
+-- Mailbox
+-- Email Worker
```
这些资源关系由 Console 管理。
## 数据平面
```text
Email Worker -> Node -> Console
```
Node 不参与业务决策。
## Node Scope
第一版一个 Node 绑定一个 Cloudflare Account。Node A 不允许处理 Account B 的资源。
## 扩展
未来可以有多个 Node,例如 Node JP、Node US、Node EU。每个 Node 默认仍绑定一个 Cloudflare Account。
+11
View File
@@ -0,0 +1,11 @@
# Cloudflare OAuth 与自动安装
Console 的 Add Node 入口必须打开 Cloudflare OAuth 授权页面。用户授权后,Console 通过 Cloudflare API 自动完成 Node、Email Worker、Domain、Mailbox 的配置。
用户不执行 shell 安装命令,也不手工创建 API Token。
流程:Console -> Add Node -> Cloudflare OAuth -> 授权回调 -> 获取 Account/Zone -> 创建 Node Identity -> 创建 Node Credential -> 创建或更新 Email Worker -> 配置 Email Routing -> 创建 Domain/Mailbox -> Node Ready。
Cloudflare credential 与 Node credential 必须分离。Cloudflare credential 加密存储,不进入前端和日志。
安装过程必须幂等,重复执行不能创建重复资源。OAuth state、授权回调和 Account ownership 必须验证。
+44
View File
@@ -0,0 +1,44 @@
# Node 设计
Node 是无前端、纯后端的邮件转发节点。
核心流程:
```text
Email Worker -> Node -> Console
```
## Node 职责
- 接收 Email Worker 请求
- 验证 Worker 请求
- 获取邮件
- 安全转发到 Console
- 有限重试临时网络错误
- 心跳
- 上报版本和状态
## Node 不负责
- Domain 路由
- Mailbox 路由
- Webhook
- MCP
- API
- 用户权限
- 邮件业务存储
- 邮件规则
Node 收到什么就转发什么。
## Node Scope
Node 只能服务创建它的 Cloudflare Account。不得通过普通业务请求把 Node 任意绑定到其他 Account。
## 配置
Node 至少需要 node_id、cloudflare_account_id、console_endpoint、credential。
credential secret 必须安全保存。
Node 可以有限重试 Console 网络错误,但不承担长期邮件队列职责。
+49
View File
@@ -0,0 +1,49 @@
# Node 与 Console 通信协议
Node -> Console 必须使用 HTTPS + HMAC 请求签名 + timestamp + nonce + body hash。
## Credential
```text
node_id
credential_id
credential_secret
cloudflare_account_id
```
Console 保存 secret 的安全摘要;Node 保存实际 secret。
## 签名
```text
body_hash = SHA256(raw_body)
canonical = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + body_hash
signature = HMAC-SHA256(secret, canonical)
```
请求头:
```text
Authorization: WmailHub-Node <node_id>
X-WmailHub-Timestamp: <unix_seconds>
X-WmailHub-Nonce: <random>
X-WmailHub-Body-SHA256: <hex>
X-WmailHub-Signature: <hex>
X-WmailHub-Protocol: 1
```
Console 拒绝 timestamp 超窗、重复 nonce、错误 signature、错误 body hash、已撤销 credential。默认 timestamp window 建议 5 分钟。
## API
```text
POST /api/internal/nodes/{node_id}/emails
POST /api/internal/nodes/{node_id}/heartbeat
GET /api/internal/nodes/{node_id}/config
```
邮件请求推荐 `Content-Type: message/rfc822`,body 直接使用 raw MIME。
Console 可以立即撤销 credential。Node 收到 401/403 后不得无限重试。
协议必须版本化。
+57
View File
@@ -0,0 +1,57 @@
# 数据模型
核心实体:CloudflareAccount、Node、Domain、Mailbox、Email、EmailAttachment、Webhook、WebhookDelivery、OAuthConnection。
## nodes
```text
id, name, cloudflare_account_id, credential_id, status, version, last_seen_at, created_at, updated_at
```
## domains
```text
id, cloudflare_account_id, node_id, name, status, worker_id, created_at, updated_at
```
## mailboxes
```text
id, domain_id, address, status, retention_seconds, created_at, updated_at
```
## emails
```text
id, node_id, mailbox_id nullable, message_id, from_address, to_addresses,
cc_addresses, subject, text_body, html_body, raw_storage_key, size,
received_at, expires_at, created_at
```
Node 可以不知道 mailbox_id。Console 收到邮件后,根据邮件内容和自身配置关联。
## email_attachments
```text
id, email_id, filename, content_type, size, storage_key, content_id
```
## webhooks
```text
id, name, endpoint, secret, enabled, created_at, updated_at
```
## webhook_deliveries
```text
id, webhook_id, email_id, status, attempt_count, next_retry_at, last_error, delivered_at, created_at
```
## oauth_connections
```text
id, provider, account_id, encrypted_access_token, refresh_token, expires_at, created_at, updated_at
```
OAuth token 必须加密存储。所有 Email 必须有 expires_at,默认 retention 为 86400 秒。
+42
View File
@@ -0,0 +1,42 @@
# Email 生命周期与 TTL
## 接收
```text
Cloudflare -> Email Worker -> Node -> Console
```
Console 验证 Node 身份和请求完整性,然后解析 MIME、提取 header、text/html 和附件,保存元数据,raw MIME/大附件写入 R2,计算 expires_at,并创建 Webhook Delivery。
## TTL
默认保留 1 天:
```text
received_at = 2026-09-30T10:00:00Z
expires_at = 2026-10-01T10:00:00Z
```
Retention 可按 Mailbox 配置。
## Cron
使用 Cloudflare Cron Trigger,建议每 15 分钟执行一次清理。实际频率根据当前 Cloudflare 限制调整。
```text
Cron -> 查询 expires_at <= now -> 删除 R2 -> 删除附件 -> 删除 Email
```
删除必须幂等。
## Webhook
邮件保存成功后再执行 Webhook。Webhook 失败不能导致邮件重新进入 Node。
## 异常
R2 删除失败时保留数据库记录并记录 cleanup error,下一次 Cron 重试。数据库已删除但 R2 删除失败时,需要 orphan cleanup。
## 数据最小化
邮件、附件、raw MIME、Webhook Delivery 和临时日志都应有生命周期,不做无限期保存。
+45
View File
@@ -0,0 +1,45 @@
# Webhook、API 与 MCP
Webhook、API、MCP 全部属于 Console,Node 不实现这些能力。
## Webhook
邮件保存成功后创建 delivery。Payload:
```json
{
"event": "email.received",
"id": "msg_xxx",
"mailbox": "hello@example.com",
"from": "user@example.org",
"to": ["hello@example.com"],
"subject": "Hello",
"text": "Hello World",
"received_at": "2026-09-30T10:00:00Z"
}
```
Webhook 必须签名,建议提供 X-WmailHub-Event、X-WmailHub-Delivery、X-WmailHub-Timestamp、X-WmailHub-Signature。
2xx 为成功;5xx 和 timeout 重试;4xx 按策略处理。使用指数退避和最大尝试次数。
## API
```text
/api/v1/nodes
/api/v1/domains
/api/v1/mailboxes
/api/v1/emails
/api/v1/webhooks
/api/v1/mcp
```
API 属于 Console。
## MCP
MCP 允许 Agent 查询邮箱、获取邮件、查询邮件状态、管理邮箱和 Webhook。Node 不暴露 MCP。
MCP/API 获取邮件时必须检查用户权限、邮件是否过期、mailbox scope 和 API credential scope。
Webhook endpoint 必须防 SSRF,至少阻止 localhost、private IPv4/IPv6、link-local、metadata endpoint 和 DNS rebinding。
+47
View File
@@ -0,0 +1,47 @@
# 安全设计
## 安全边界
```text
Cloudflare Email Worker
|
| authenticated request
v
Node
|
| TLS + HMAC
v
Console
```
## Cloudflare OAuth
OAuth Token 加密存储,不进入前端和日志,也不作为 Node credential。
## Node Credential
由 Console 自动生成。用户不手工配置。支持撤销和重新 enrollment。
## 请求签名
所有 Node -> Console 请求必须签名,签名覆盖 method、path、timestamp、nonce、body hash,防止篡改和 replay。
## Worker -> Node
Worker 使用 Node 专用 ingress secret。Worker 不应拥有 Console credential。
## 最小权限
Cloudflare OAuth 只申请业务所需权限。
## 日志
禁止记录 Cloudflare OAuth token、Node secret、Webhook secret、Authorization header 和完整邮件正文。
## 附件限制
限制单文件大小、单邮件总大小、文件数量和 MIME header 大小,避免资源耗尽。
## 数据保留
默认 Email TTL 为 1 天,过期自动删除。
+42
View File
@@ -0,0 +1,42 @@
# Cloudflare 部署设计
## 服务
第一版目标使用 Cloudflare Workers、Email Workers / Email Routing、D1、R2、Cron Triggers、OAuth;Queues 在需要可靠异步投递时再加入,并以当前 Cloudflare 限制为准。
## Console
Console 本身部署在 Cloudflare Workers:
```text
Worker
+-- Frontend Assets
+-- Management API
+-- OAuth Callback
+-- Cron Handler
```
## Node
Node 是独立纯后端程序,无前端。可以部署在用户服务器、云服务器或其他可访问 Console 的环境,但 Cloudflare Email Worker 必须能访问 Node ingress。
## Email Worker
Email Worker 只接收 Email Event 并安全转发到 Node,不保存业务数据库。
## R2
用于 raw MIME 和 attachments:
```text
emails/{yyyy}/{mm}/{dd}/{email_id}/raw.eml
emails/{yyyy}/{mm}/{dd}/{email_id}/attachments/{attachment_id}
```
## D1
保存 nodes、domains、mailboxes、emails、webhooks、webhook deliveries、oauth connections。
## Cron
至少实现 cleanup job,建议每 15 分钟一次,具体以当前 Cloudflare 限制调整。
+61
View File
@@ -0,0 +1,61 @@
# ZCODE 实施计划
## Phase 1 项目骨架
```text
WmailHub/
console/
node/
worker/
docs/
```
Console、Node、Worker 必须边界清晰,共享协议独立。
## Phase 2 Console
实现 Console Web、Management API、数据库、认证、Node CRUD、Domain CRUD、Mailbox CRUD、Email CRUD。
## Phase 3 Cloudflare OAuth
实现 OAuth start、callback、state、token exchange、Account/Zone discovery、加密 token storage。
## Phase 4 自动 Node 安装
Add Node 后完成:OAuth、Node identity、Node credential、Email Worker、Worker -> Node、Email Routing、Domain、Mailbox、Node heartbeat。正常流程禁止要求用户复制安装命令。
## Phase 5 Node
实现 bootstrap、secure config、Email Worker ingress、Console egress、HMAC signing、heartbeat、有限 retry、graceful shutdown、structured logging。
Node 不实现业务路由。
## Phase 6 Email Pipeline
```text
Cloudflare -> Worker -> Node -> Console -> D1/R2
```
测试 plain text、HTML、MIME、attachment、多收件人、大正文和 malformed mail。
## Phase 7 Webhook
实现 CRUD、secret、signing、delivery、retry、timeout、失败状态和日志。
## Phase 8 TTL
实现 retention configuration、expires_at、Cron cleanup、R2 cleanup 和 orphan cleanup。默认 1 day。
## Phase 9 API / MCP
实现 Console API,并提供 list_mailboxes、list_emails、get_email、create_mailbox、delete_mailbox、list_webhooks 等 MCP 工具。权限必须基于 Console credential。
## Phase 10 安全测试
测试 OAuth CSRF、credential revoke、replay attack、伪造 Node 请求、body 篡改、过期 timestamp、Webhook SSRF、未授权 mailbox、未授权 Cloudflare Account、超大邮件和超大附件。
## Phase 11 验收
必须完成:Cloudflare OAuth -> 自动 Node 安装 -> Domain 配置 -> Mailbox 创建 -> 真实 Email -> Email Worker -> Node -> Console -> Database/Webhook/API/MCP -> TTL 自动删除。
如果正常流程要求用户手工登录服务器执行安装命令,则不符合设计目标。