bigcode
|
c4b5e65159
|
v2.6.0: 接入不再自动建 catch-all 邮箱(手动添加);删除账号/域名时清理 Cloudflare 侧资源(关闭 Email Routing + 删除 Email Worker,尽力而为+告警)
|
2026-10-01 02:19:30 +08:00 |
|
bigcode
|
830ca85ebd
|
v2.5.1: 邮件详情抽屉去掉 邮箱/Message-ID;添加账号窗口去切换控件,OAuth 按钮 + API Token 表单平铺同窗
|
2026-10-01 01:11:06 +08:00 |
|
bigcode
|
8b255ef2e0
|
v2.5.0:操作日志 + 邮件保留 + 账号弹窗精简 + 复制按钮推广
- 操作日志:operation_logs 表(0004 迁移)记录 账号/域名/邮箱/Webhook 全部写操作,
含操作账号(Console 登录名,系统动作为 system);/logs 日志页(类型筛选+搜索+分页);
上限 10000 条,Cron housekeeping 超限删最旧
- 邮件保留:emails.retained;POST /api/emails/retain(单条/批量);
TTL 清理与 Webhook 投递过期判定均跳过已保留;/inboxs 操作列图钉按钮 + 批量保留
- 添加账号弹窗:OAuth 与 API Token 同窗按钮组切换,去掉说明文字与账户 ID 字段
(账户 ID 以 Token 实际所属账户为准);账号列表去掉 Email Worker 列
- 复制按钮推广:CopyText 组件;/domains 域名列、/inboxs 发件人与收件人(原「邮箱」改名)列
- 测试:104 bun tests(+10 日志/保留)、ui-smoke 35 项(+logs 页/新弹窗/复制/保留)
|
2026-10-01 00:25:38 +08:00 |
|
bigcode
|
8c5ed7fc8b
|
v2.4.1 回读校验收紧到 status:SPF 冲突(misconfigured)不再谎报已配置
实测 adx9.com 全链路时发现的新缺口:/enable 成功后 enabled=true,但 zone 的
Email Routing status 可能仍是 misconfigured(SPF 指向旧邮件服务)——
照 v2.4.0 的校验(enabled===true)照样会把域名标成「已配置」,而邮件根本不会投递,
与 MX 假成功是同一类问题。
- cfapi: 回读校验增加 status 判定:
- ready / unlocked(过渡态,实测邮件照常投递)视为成功
- misconfigured* 判失败,并把状态对象里的 errors 翻译成中文
(spf.foreign = 现有 SPF 指向其它邮件服务;spf.missing = 给出应替换的 SPF 内容)
- cf-mock: 读回的状态随 emailRoutingStatusAfterEnable 可配置
- oauth.test 新增 2 例:misconfigured 判失败(不标 active)、unlocked 视为成功
线上排查记录(2026-09-30,已手工修复):
adx9.com 删除自建 MX(10 mx.adx9.com)→ POST /email/routing/enable 成功但
status=misconfigured/locked(errors: spf.foreign/spf.missing)→ PATCH
/email/routing/dns(unlock)→ 替换 SPF TXT 为 v=spf1 include:_spf.mx.cloudflare.net
~all → Graph API 发测试邮件 → Console 收到(msg_7eb6afeba6179293),全链路打通。
|
2026-09-30 22:18:13 +08:00 |
|
bigcode
|
ecce90dfab
|
v2.4.0 修 Email Routing 假成功 + 加 API Token 接入与邮箱/域名页交互改进
问题 6(收不到邮件、Dashboard 邮件路由里看不到域名)的根因:
上一版把「开启 Email Routing」改成了 PUT /zones/{id}/email/routing,
但实测该接口(以及 PATCH)是**纯回显** —— 返回 success:true 但 enabled 纹丝不动,
域名在 Cloudflare 侧仍是 unconfigured、连 MX 记录都没有。Console 却照它的返回值
把域名标成「已配置 Email Workers」,于是「显示配好了却收不到邮件」。
实测只有 POST /zones/{id}/email/routing/enable 真的开启(线上对 adx9.com 与
galaxyemail.com 逐一验证)。
后端
- cfapi: 改用 /enable,并在开启后回读 GET 校验 enabled===true,不满足即判失败;
新增 CFApiError(带 Cloudflare 错误码)与 getEmailRoutingSettings
- cfapi: 错误码 2008(Non-Cloudflare MX records exist)翻译成中文并点名冲突的 MX 记录
- provision: Email Worker 统一命名 wmailhub-email(原先按账号 id 拼名),
部署走 PUT,同名即覆盖更新
- db: 新增 decryptAccountToken —— 按账号取 token,不再取「最近一条连接」,
并跳过已过期的 OAuth token;oauth_connections.account_id 真正写入
- resources: 新增 POST /api/accounts/token(API Token 方式添加账号):
先校验 token 与账户 ID,确认可用才建账号并自动接入
前端
- 账号:「添加账号」改为模态窗口,OAuth / API Token 两个 tab,各自带说明
- 域名: 删除「Email Worker」列;「设置 Email Workers / 重新配置」先弹确认框
(说明会改 MX 与路由),执行期间按钮 loading 且互相禁用;error 状态改成可读的 Alert + 重试
- 邮箱: 删除「状态」列(已由「启用」开关承担);地址列加复制按钮(带弹跳+变绿动画);
「添加邮箱」窗口的域名只列已装 Email Workers 的、支持搜索、默认选中最近使用的域名;
地址框可一键从 namedb 取随机用户名;勾选 catch-all 后地址框禁用
- 收件箱: 域名筛选只显示已装 Email Workers 的域名
测试
- cf-mock 复刻「PUT/PATCH 回 success 但不改 enabled」与 2008,锁住本次修复
- oauth.test 新增 4 例:2008 冲突、回读校验、API Token 接入、Token/账户 ID 校验失败
- ui-smoke 覆盖新增的添加账号/添加邮箱/确认框等交互(28/28 通过)
文档: docs/02 补「三种开启接口只有 /enable 有效」的实测表、2008 处理、
两种接入方式与按账号取 token 的说明
|
2026-09-30 18:20:44 +08:00 |
|
bigcode
|
e7db6762fd
|
fix(email): 开启 Email Routing 改用 PUT,并补上 zone-settings.write 权限
POST /zones/{id}/email/routing 不是有效路由,Cloudflare 返回
10405 Method not allowed for this authentication scheme。正确接口是
PUT /zones/{id}/email/routing(Apply Email Routing settings);
POST .../email/routing/enable 能用但官方已标 Deprecated。
该接口的 Accepted Permission 是 Zone Settings Write,而不是 Email Routing 权限族
—— 权限名和接口所属资源组对不上,Email Routing 四个权限全勾也不够。
- CF_OAUTH_SCOPES_DEFAULT / 探测候选集加 zone-settings.write;设置页文案同步
- cfapi 的 API 错误带上 Cloudflare 错误码(如 10405),便于区分路径错与权限错
- cf-mock 对非 PUT 的 /email/routing 返回 10405,旧写法会被打回
- 88/88 测试
|
2026-09-30 17:26:29 +08:00 |
|
bigcode
|
42c488050b
|
fix(oauth): token 兑换改用 HTTP Basic(client_secret_basic),修 401
Cloudflare OAuth 客户端默认 token_endpoint_auth_method = client_secret_basic,
只接受 Authorization: Basic 头。之前把 client_id/secret 放在 POST body
(client_secret_post),token 端点直接 401 invalid_client,描述里点名
"method 'client_secret_post' was requested" —— 表现为 Cloudflare 授权成功、
回调却报 token exchange failed: 401。
- exchangeToken 改 Basic 认证,凭据按 RFC 6749 §2.3.1 先 form-urlencoded 再 base64
- 失败时带回 Cloudflare 原始 error/error_description;invalid_client 额外提示
「secret 只在创建时显示一次,轮换后旧值失效」
- cf-mock 复刻「只认 Basic」的行为,没有 Basic 头就返回 401(旧代码会被打回)
- 断言 token body 不含 client_id/client_secret,Basic 头解出正确凭据
- 88/88 测试
|
2026-09-30 17:16:14 +08:00 |
|
bigcode
|
2ce8a24707
|
fix(deploy): /api/* 与 /internal/* 显式 run_worker_first,修 OAuth 回调被 SPA 资源层截胡
compatibility_date >= 2025-04-01 隐式开启 assets_navigation_prefers_asset_serving:
浏览器【导航请求】不进入 Worker,直接由 SPA 资源层返回 index.html。
/api/oauth/cloudflare/callback 是浏览器跨站重定向的落点(导航请求),于是被截胡 ——
前端在无匹配路由的路径上 hydrate,渲染 React Router 的 404 页面;后端 state 完全没被消费,
表现为「Cloudflare 授权成功,回调却毫无反应」。
用 run_worker_first 路径数组(而非 true),静态资源仍走 asset-first 快路径。
- 新增 tests/deploy_config.test.ts 锁住这条部署配置(此类问题只在生产出现)
- 线上复验:导航请求打回调现在返回 Worker 的 400,不再是 200 index.html;/accounts 仍返回 SPA
|
2026-09-30 17:10:57 +08:00 |
|
bigcode
|
5b887908e2
|
feat(oauth): 账号名改从 zone.account 取,去掉 account-settings.read 依赖
实测确认 GET /zones 每个 zone 自带 account {id,name},该接口只需 zone.read,
因此账号 id 与账号名都不必再调 GET /accounts(account-settings.read)。
顺带修掉 account_id 旧字段在当前响应里已为 null 导致的降级路径取不到账号 id。
- RealCFApi.discover 只列 /zones,移除 listAccounts 与 accountSource
- scope 候选集去掉 account-settings.read;设置页移除「含账号名权限」按钮
- 设置页 Scope 说明与 docs/02、README 同步(补 User Details Read 的区别说明)
- 85/85 测试通过(新增 zone 带 account / 不带 account 两种断言)
|
2026-09-30 17:03:59 +08:00 |
|
bigcode
|
7a1625d575
|
fix: v2.3.2 用探测确定真实 scope 词表,接入已实测可用
- 上一版默认 scope 名是猜的(account.read / email_routing.write),全部被拒。
正确词表是点号分隔的 <group>.<verb>,且:
- 账号是 account-settings.read(选择器里叫 Account Settings Read),不是 account.read
- Workers 脚本是 workers-scripts.write,不是 workers_scripts.write
- Email Routing 在选择器里是四个独立权限,改 catch-all 对应 email-routing-rule.write
- account:read 这种冒号写法是 wrangler 的第一方简写,第三方 client 一律被拒
- client 注册的 scope 是上限不是默认:没勾的权限即使账号有也不生效
- preflight 扩展 scope 探测:授权端点在同意页之前就校验并点名拒绝的 scope,
逐轮「请求剩余候选 -> 剔除被点名项」即可收敛出 App 已授权集合(未认证请求,
不登录/不产生授权),结果按 allowed/denied 返回并在设置页用绿/橙标签展示
- 缺少账号级读权限时不再失败:discover() 先试 /accounts,403 则改为列 token 可见的 /zones,
用 zone 自带的 account_id 反推账户(展示名用第一个域名)
- 默认 scope 收敛为接入必需的三项(zone.read / workers-scripts.write /
email-routing-rule.write),account-settings.read 改为可选:勾了才显示真实账号名
- 实测:线上 preflight 已 ok=true(Cloudflare 跳登录页),无需再改 App 即可「添加账号」
|
2026-09-30 16:26:43 +08:00 |
|
bigcode
|
1f4d45f719
|
fix: v2.3.1 Cloudflare OAuth scope 点号格式 + 授权失败可读提示 + 配置自检
- 根因:Cloudflare OAuth 的 scope 是点号分隔(account.read),冒号写法不被接受,
授权端点直接返回 error=invalid_scope。默认 scope 改为
account.read zone.read email_routing.write workers_scripts.write
- scope 可在设置页自定义(settings.cf_oauth_scopes),需与 App 登记值逐字一致
- 新增 GET /api/oauth/cloudflare/preflight + 设置页「检测授权配置」按钮:
只读探测授权端点(不跟随跳转),区分 登录同意页 / 弹回回调 / Cloudflare /oauth/error,
并把 invalid_scope、invalid_request 翻译成可执行的处置建议
- 回调端点处理 error 参数:不再拿空 code 去兑换 token,改为跳回账号页并弹窗说明原因
(此前会落到 SPA 404 空壳页)
- 账号页读取 ?oauth_error= 弹窗展示 Cloudflare 的原始描述
- docs/02 补 Cloudflare OAuth App 配置清单(Redirect URL / Client URI 域名校验 /
Promote to public / 点号 scope);83 个测试全通过
|
2026-09-30 16:08:27 +08:00 |
|
bigcode
|
3be6e483b4
|
feat: v2.3.0 设置内配置 Cloudflare OAuth 客户端 + 全列表批量删除
- 设置新增「Cloudflare 接入」tab:Client ID / Client Secret(Secret AES-GCM 加密入库,
只回显末 4 位),并展示可复制的授权回调地址;settings 优先、env 变量兜底,
保存后立即生效无需重新部署;DELETE /api/settings/cf-oauth 清除
- 四个资源列表(账号/域名/邮箱/收件箱)加复选框批量选择与批量删除
- 新增 POST /api/{accounts,domains,mailboxes,emails}/batch-delete:
账号软删+撤销凭据;域名/邮箱级联删除其下邮件;邮件连 R2 原文与附件一并清理
- 抽出 deleteEmailById / deleteEmailsByMailbox / revokeAccount 供单条与批量共用
- 点击复选框不再触发行点击(避免误开详情抽屉)
- 新增 tests/batch.test.ts(6 例)与 settings OAuth 凭据用例(2 例);ui-smoke 扩到 17 步
|
2026-09-30 15:53:18 +08:00 |
|
bigcode
|
e2c3c353cf
|
refactor: v2.2.0 移除本地 sim 模式,Cloudflare OAuth 只走真实授权
- 删除 SimCFApi / WMAILHUB_SIM_CF / isRealOAuth / POST /api/oauth/cloudflare/sim/approve
- 删除前端 OAuthSim 模拟授权页与 /oauth/sim/authorize 路由;账号页「添加账号」整页跳 Cloudflare
- 迁移 0005 删除 cf_sim_resources 表
- 未配置 CF_OAUTH_CLIENT_ID/SECRET 时 start/callback 一律 503(不再降级出假账号假资源)
- 修 OAuth 回调端点:跨站重定向不携带 SameSite=Strict 会话 cookie,改为由一次性 state 承担 CSRF 防护
- 测试改用 tests/cf-mock.ts 在 fetch 层拦截 Cloudflare API,断言真实 HTTP 调用(72/72 通过)
- 本地 dev 无账号时只拉起 Console 并提示人工授权,不再自动造账号
|
2026-09-30 15:33:58 +08:00 |
|
bigcode
|
c10495d7f8
|
fix: v2.1.1 列表操作列溢出与分页器对齐
- /mailboxes 地址列保持自适应(不设宽度吸收剩余空间),操作列 150→210 修复按钮被卡片右缘裁切
- /domains 操作列 200→260、/accounts 100→110,带图标按钮一行放下
- 分页器(总条数/页码/条数下拉)整体居中紧凑,条数下拉不再贴最右侧
|
2026-09-30 14:50:07 +08:00 |
|
bigcode
|
7370cce784
|
feat: v2.1.0 界面与凭据改进 —— 单一 API/MCP Key、邮件 Markdown 正文、/inboxs 域名筛选、暗色主题
- 单一 Key:API 与 MCP 共用一个 wmh_ Key,凭据迁移至 settings 表(0004 删除 api_credentials)
- Markdown:入库时 HTML→Markdown(mailhook 同思路),webhook payload 新增 markdown 字段
- /emails 路由改为 /inboxs 并支持域名筛选;设置按钮移入头像下拉
- 主题切换按钮(头像左侧,亮/暗持久化);设置模态仅 全局 Webhook/账号密码 两 tab 且高度限屏
- 列表操作列按钮加 SVG 图标;mailboxes 去 Webhook 列;最近邮件加收件人列
|
2026-09-30 13:27:28 +08:00 |
|
bigcode
|
fec96e49cc
|
feat: v2.0.0 邮件接收架构改造 —— 移除 Node,Email Worker 直连 Console(docs/11)
- 两阶段接收:POST /internal/email/authorize(accept/reject/temporary_error)+ POST /internal/email/ingest(raw MIME 直传)
- Worker-Console 协议:Authorization: WmailHub-Worker + timestamp/nonce/body-hash/HMAC,nonce 防重放,凭据撤销即时生效
- 数据模型:nodes/node_credentials -> cloudflare_accounts/worker_credentials(迁移 0003),emails/domains 归属 account_id
- 接入流程 Connect Cloudflare Account:OAuth 自动同步域名 + 部署账号级 Email Worker + 签发 Worker 凭据;rotate 自动重部署
- 动态邮箱:创建/删除/禁用下一封邮件立即生效;拒绝码 DOMAIN_*/MAILBOX_*;超时/5xx 不伪装成邮箱不存在
- 删除 node/ 目录、旧 /api/internal/nodes 协议、ingress/enrollment 概念;dev.ts 简化为 console + email worker 双进程
- 前端:账号页 Email Worker/凭据管理,设置窗口移除默认 Ingress,仪表盘/文案同步;版本 2.0.0
- 测试 62 项全过(新增 authorize 决策矩阵 + Worker 两阶段临时错误语义);本机虚拟 E2E 12 场景全通
- docs 00-10 同步改写;README 更新
|
2026-09-30 13:10:26 +08:00 |
|
bigcode
|
421cfb2f04
|
feat: v1.1.0 账号化重构 + 三级 Webhook + 设置中心 + Vite 工具链
- 账号化:节点更名账号,/nodes -> /accounts;添加账号直达 Cloudflare OAuth,自动创建账号并同步账号下全部域名(catch-all 邮箱随同步创建)
- 域名:移除手工添加;点击域名『设置 Email Workers』= 部署账号级 Email Worker + Email Routing + catch-all;支持按账号筛选
- Webhook 三级模型:邮箱 -> 域名 -> 全局,收信取第一个命中者;支持自定义请求头与 key(默认 Authorization: Bearer <key>,兼做 X-WmailHub-Signature 签名);独立 webhooks 实体与 /webhooks、/keys 页面删除,Key 管理收进设置模态窗口
- 设置中心:全局 Webhook / 默认 Node Ingress 地址 / 修改密码 / API & MCP Keys(生成、撤销、删除)
- UI:Header 标题副标题紧凑化(修复溢出),LOGO 加版本号 tag(v1.1.0 取自 package.json),各列表页搜索框
- 工具链:前端构建 Bun.build -> Vite(vite 8 + @vitejs/plugin-react)
- 后端:/api/settings、POST /api/domains/:id/setup、0002 迁移(投递行固化三级目标配置);MCP 去 list_webhooks(5 工具);迁移执行器加 _migrations 记录
- 测试:44/44(新增 settings 套件、webhook 三级优先级/SSRF/签名);UI 冒烟 11/11
|
2026-09-30 11:37:38 +08:00 |
|
BigCode
|
d4c1334143
|
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 生成
|
2026-09-30 03:34:37 +08:00 |
|