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
+24
View File
@@ -0,0 +1,24 @@
From: Alice Sender <alice@example.org>
To: hello@example.test
Cc: bob@example.net
Subject: WmailHub 端到端测试邮件
Message-ID: <test-001@example.org>
Date: Wed, 30 Sep 2026 03:20:00 +0000
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY-XYZ"
--BOUNDARY-XYZ
Content-Type: text/plain; charset=utf-8
Hello WmailHub! This is a plain text body.
--BOUNDARY-XYZ
Content-Type: text/html; charset=utf-8
<html><body><h1>Hello WmailHub</h1><p>This is <b>HTML</b> body.</p></body></html>
--BOUNDARY-XYZ
Content-Type: text/plain; charset=utf-8; name="notes.txt"
Content-Disposition: attachment; filename="notes.txt"
Content-Transfer-Encoding: base64
VGhpcyBpcyBhbiBhdHRhY2htZW50IGZpbGUu
--BOUNDARY-XYZ--
+41
View File
@@ -0,0 +1,41 @@
/**
* 本地 Webhook 接收器(联调用):
* bun tests/fixtures/webhook-receiver.ts [port]
* 验证 X-WmailHub-Signature = HMAC-SHA256(secret, `${timestamp}.${body}`),打印收到的 payload。
*/
const port = Number(process.argv[2] ?? 18790);
/** # 成员变量: 与创建 webhook 时一致的 secret(由环境变量传入) **/
const SECRET = process.env.WEBHOOK_SECRET ?? "";
Bun.serve({
port,
async fetch(req) {
if (req.method !== "POST") return new Response("ok");
const body = await req.text();
const ts = req.headers.get("X-WmailHub-Timestamp") ?? "";
const sig = req.headers.get("X-WmailHub-Signature") ?? "";
const delivery = req.headers.get("X-WmailHub-Delivery") ?? "";
const key = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(SECRET),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"],
);
const expected = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${ts}.${body}`));
const expectedHex = [...new Uint8Array(expected)].map((b) => b.toString(16).padStart(2, "0")).join("");
const valid = expectedHex === sig;
console.log(
JSON.stringify({
t: new Date().toISOString(),
msg: "webhook received",
delivery,
signature_valid: valid,
payload: JSON.parse(body),
}),
);
return Response.json({ received: true });
},
});
console.log(`webhook receiver on :${port}`);