本文只讲方法:如何用开源项目 maillab/cloud-mail 在 Cloudflare 免费额度内部署一个完全属于你自己的域名邮箱。文中所有密钥、域名、ID、账号均为占位符
<...>,请替换成你自己的真实值;不含任何可用凭据。
想拥有一个 @自己的域名 的邮箱?痛点通常是:
- 个人域名只用来建站,白白浪费;
- 第三方企业邮箱要么收费、要么有数量限制;
- 想要「收信 + 发信 + 附件 + 网页端」全套,但不想维护服务器。
这篇文章记录了一套基于 Cloudflare 全家桶的自建邮箱方案,最终效果:
xxx@你的域名任意收件(Email Routing 通配);- 网页端发信(CF Email Sending + Resend 双通道自动兜底);
- 附件存 R2,可绑自定义域名直连;
- 注册即用,无需注册码/人机验证,适合小圈子共享。
整体架构#
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 部署后:
- 访问
https://mail.<你的域名>/api/init/<jwt_secret>初始化 D1(建表); - 后台登录管理员账号
admin@<你的域名>(初始密码部署时生成,登录后尽快修改); - 打开系统设置,确认开关:收信
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。为了能发任意地址、又不依赖第三方,可做成双通道:
- CF Email Sending(send_email 绑定):部署时自动添加,
wrangler.toml里[[send_email]]配置; - 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 回退原逻辑。
注册配置(小圈子共享)#
| 设置 | 值 | 说明 |
|---|---|---|
| register | 0 | 注册开启 |
| registerVerify | 1 | 人机验证关闭(未配 Turnstile 时的选择) |
| regKey | 1 | 注册码关闭 |
| loginDomain | 0 | 登录/注册自动带 @<你的域名> 后缀 |
注册时只填用户名即可,公开注册适合小圈子;如果对外开放,建议打开注册码或人机验证。
已知坑(部署前必读)#
- orm_log:不能传字符串
"true"/"false",drizzle 会当 logger 对象调用报this.logger.logQuery is not a function;要传空字符串或做布尔判断; - 鉴权头:前端请求直接放 JWT,没有
Bearer前缀,测试 API 时注意; - R2 需 dashboard 开通:免费计划首次使用 R2 需在 CF 控制台手动点开通;
- Email Routing 通配:catch-all 不支持 worker 动作,必须用
*@domainliteral 规则,worker 动作 value = 脚本名; - 邮件列表接口崩溃:
/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、账号、密钥)均为占位符,请替换成你自己的真实值后再部署。







