↓ 跳过正文
  1. Posts/

在 Cloudflare 上白嫖一个自建邮箱服务:cloud-mail 全流程部署指南

·2936 字·6 分钟· loading · loading · ·
HJP
作者
HJP
一个正在不断学习与成长的人。
目录

本文只讲方法:如何用开源项目 maillab/cloud-mail 在 Cloudflare 免费额度内部署一个完全属于你自己的域名邮箱。文中所有密钥、域名、ID、账号均为占位符 <...>,请替换成你自己的真实值;不含任何可用凭据。

想拥有一个 @自己的域名 的邮箱?痛点通常是:

  • 个人域名只用来建站,白白浪费;
  • 第三方企业邮箱要么收费、要么有数量限制;
  • 想要「收信 + 发信 + 附件 + 网页端」全套,但不想维护服务器。

这篇文章记录了一套基于 Cloudflare 全家桶的自建邮箱方案,最终效果:

  1. xxx@你的域名 任意收件(Email Routing 通配);
  2. 网页端发信(CF Email Sending + Resend 双通道自动兜底);
  3. 附件存 R2,可绑自定义域名直连;
  4. 注册即用,无需注册码/人机验证,适合小圈子共享。

整体架构
#

Email Routing(*@你的域名 → Worker)
        ↓
cloud-mail Worker(Hono 框架)
  ├─ D1        → 账号/邮件/设置
  ├─ KV        → 会话/缓存
  ├─ R2        → 附件存储(绑自定义域名直连)
  ├─ send_email→ CF Email Sending(发信通道 1)
  ├─ AI        → 验证码识别(可选)
  └─ Vue3 前端  → 网页邮件客户端(随 Worker 构建上传)

核心思想:收信走 Cloudflare Email Routing,发信走 CF Email Service / Resend,数据与附件落在 D1 + R2——整套跑在 Cloudflare 免费额度内,不需要任何 VPS。

需要的 Cloudflare 资源
#

资源作用
Worker跑 cloud-mail 服务本体(handlers: fetch / email / scheduled)
D1 数据库存账号、邮件、系统设置
KV会话、缓存
R2 存储桶附件(绑定 r2.<你的域名> 自定义域名)
Email Routing收件:*@<你的域名> → Worker
send_email发件(CF Email Service,Beta)
AI验证码识别(可选)

提示:所有资源都可以在 wrangler.toml 里声明后通过 wrangler deploy 自动绑定。R2 首次使用需要在 CF 控制台手动开通(免费计划点一下即可)。

第一步:克隆项目并配置
#

git clone https://github.com/maillab/cloud-mail
cd cloud-mail/mail-worker
# 按你的域名/资源名改 wrangler.toml:D1/KV/R2/send_email 绑定 + [vars]
npx wrangler deploy --config wrangler.toml
  • 前端代码在 mail-vue/,wrangler [build] 会自动 pnpm install && pnpm build 后随 Worker 一起上传;
  • 服务本体在 mail-worker/,改动后重新 wrangler deploy 即可。

第二步:初始化数据库与管理员
#

Worker 部署后:

  1. 访问 https://mail.<你的域名>/api/init/<jwt_secret> 初始化 D1(建表);
  2. 后台登录管理员账号 admin@<你的域名>(初始密码部署时生成,登录后尽快修改);
  3. 打开系统设置,确认开关:收信 receive=1、发信 send=1、注册 register=0。

第三步:配置收件(Email Routing)
#

CF 的 catch-all(type=all)规则不支持 worker 动作,要用 *@域名 的 literal matcher 实现通配:

curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/email/routing/rules" \
  -H "Authorization: Bearer <OAUTH_TOKEN>" -H "Content-Type: application/json" \
  -d '{"matchers":[{"type":"literal","field":"to","value":"*@<你的域名>"}],"actions":[{"type":"worker","value":["<worker名>"]}],"enabled":true,"name":"all-to-worker"}'
  • worker 动作的 value 填 Worker 脚本名(不是自定义域名);
  • 启用 Email Routing 后,MX / SPF / DKIM 记录会自动创建(dns.google 可实测验证);
  • 验证:向任意 xxx@<你的域名> 发信 → worker email handler 接收 → 入库 → 登录网页端查看。

第四步:配置发件(CF Email Sending + Resend 兜底)
#

原版项目默认发件走 Resend。为了能发任意地址、又不依赖第三方,可做成双通道:

  1. CF Email Sending(send_email 绑定):部署时自动添加,wrangler.toml 里 [[send_email]] 配置;
  2. Resend 兜底:在系统设置里配 resendTokens.<你的域名> = Resend API Key(域名需在 Resend 控制台 Verified,并添加 DKIM TXT 记录)。

发送逻辑(email-service.js):

发站外邮件 → 优先 CF Email Sending
           └→ 抛错(如收件人未验证 E_RECIPIENT_NOT_ALLOWED)→ 自动改用 Resend
  • 免费额度:Resend 3000 封/月、100 封/天、1 个发件域名;
  • 判断走了哪个渠道:看已发送列表的 resendEmailId 字段——CF 格式 <xxx@域名>,Resend 格式是 UUID;
  • 若发现邮件进垃圾箱,可把 SPF 合并为 v=spf1 include:_spf.mx.cloudflare.net include:resend.dev ~all(DKIM 通常已足够,Gmail 实测可收)。

第五步:附件存 R2(绑自定义域名直连)
#

系统设置 storageType=R2,并绑 r2.<你的域名> 自定义域名到 bucket:

  • 附件直连 URL:https://r2.<你的域名>/attachments/<key>(更快);
  • Worker 的 /attachments/ 路由保留作兜底;
  • ⚠️ 已知坑:上游 bug——/attachments/ 路由永远从 KV 读取,R2 模式下附件上传后无法下载(PR #325)。修复:按 storageType 分发,R2 从 env.r2 读取(含 Content-Type/Disposition/Cache-Control 头),KV 回退原逻辑。

注册配置(小圈子共享)
#

设置值说明
register0注册开启
registerVerify1人机验证关闭(未配 Turnstile 时的选择)
regKey1注册码关闭
loginDomain0登录/注册自动带 @<你的域名> 后缀

注册时只填用户名即可,公开注册适合小圈子;如果对外开放,建议打开注册码或人机验证。

已知坑(部署前必读)
#

  1. orm_log:不能传字符串 "true"/"false",drizzle 会当 logger 对象调用报 this.logger.logQuery is not a function;要传空字符串或做布尔判断;
  2. 鉴权头:前端请求直接放 JWT,没有 Bearer 前缀,测试 API 时注意;
  3. R2 需 dashboard 开通:免费计划首次使用 R2 需在 CF 控制台手动点开通;
  4. Email Routing 通配:catch-all 不支持 worker 动作,必须用 *@domain literal 规则,worker 动作 value = 脚本名;
  5. 邮件列表接口崩溃:/api/email/list 与 /api/email/latest 在未传 accountId 时崩溃(Cannot read properties of undefined),修复:accountId 无效时兜底 allReceive=0、查询结果空时 ?? 0、latest 增加 Number 转换。

运维要点
#

  • 更新:cd mail-worker && CLOUDFLARE_API_TOKEN=<token> npx wrangler deploy --config wrangler.toml;
  • 重建库:https://mail.<你的域名>/api/init/<jwt_secret>;
  • Resend token 过期:登录 resend.com → API Keys 重建 → 更新系统设置即可(API Key 一般长期有效);
  • wrangler OAuth 登录态可能过期:长期 API 管理建议用 API Token,而不是 OAuth。

小结
#

Cloudflare 的免费额度足够支撑一个个人/小圈子的完整邮箱服务:

  • 收件:Email Routing 通配到 Worker,零成本;
  • 发件:CF Email Sending + Resend 兜底,发任意地址;
  • 数据:D1 存邮件、R2 存附件、KV 存会话;
  • 前端:Vue3 网页客户端,随 Worker 构建自动上传。

整套不需要 VPS、不需要维护服务器,唯一要注意的就是公开部署前先脱敏:管理员密码、JWT Secret、API Token、账号 ID 这些一律只放服务端环境变量,网页端和文档里不要出现真实凭据。

文中所有 <...>(域名、Token、ID、账号、密钥)均为占位符,请替换成你自己的真实值后再部署。

相关文章