如果你厌倦了付费企业邮箱或临时邮箱的不稳定,想拥有一个完全属于自己的私人邮局,那么这篇文章就是为你准备的。我将带你一步步在 Cloudflare 的免费额度上,搭建起功能完整的 OmniMail,并解决国内访问慢的难题。
引言:为什么选择 OmniMail?
OmniMail 是一个开源的、现代化的邮件管理面板,它利用 Cloudflare Workers、D1 数据库和 R2 存储,让你能以极低成本(甚至免费)运行自己的邮件服务。
OmniMail 的核心优势:
- 收发邮件:通过 Cloudflare Email Routing 免费收信,通过 Resend 或 SMTP 发信
- 多域名管理:支持在一个实例中管理多个域名邮箱
- 外部邮箱聚合:可接入 QQ、Outlook、Gmail、iCloud 等主流邮箱
- 二次验证(2FA):基于 TOTP 标准,支持 Google Authenticator 等 App
- 自动备份:D1 数据库 + R2 存储的自动备份机制
- 近乎免费:充分利用 Cloudflare 的免费额度(D1 5GB、R2 10GB 存储)
最关键的是,它可以部署在 Cloudflare Workers 上,享受免费额度,非常适合个人或小团队使用。
准备工作
在开始之前,你需要准备好以下资源:
- 一个 Cloudflare 账户(并托管至少一个域名)
- 一个 GitHub 账户(用于 Fork 项目)
- 一个 Resend 账户(用于发信,有免费额度)
- 本地环境:Node.js 18+、npm、Wrangler CLI
说明:Resend 的免费额度为每月 3000 封邮件,对于个人使用完全足够。如果已有 SMTP 服务器,也可以直接用 SMTP 发信。
第一步:部署 OmniMail
1. Fork 并克隆项目
首先访问 OmniMail 的 GitHub 仓库,点击 Fork 将项目复制到自己的账号下,然后部署到cf:
fork完毕后再cf
Workers & Pages -> “Create application”
在你连接github账户后,就可以选择你的仓库进行自动部署
3. 设置环境变量
在 Cloudflare Dashboard 中,进入你的 Worker → 设置 → 变量,在 Variables & Secrets 中添加以下变量:
| 变量名 | 类型 | 说明 | 获取方式 |
|---|---|---|---|
SETUP_TOKEN | Secret | 初始化令牌 | 自定义强密码(至少 8 位) |
SUPER_ADMIN_EMAIL | Text | 管理员邮箱 | 你的邮箱地址 |
CLOUDFLARE_ACCOUNT_ID | Text | Cloudflare 账户 ID | 在 Workers & Pages 页面右侧可找到 |
D1_DATABASE_ID | Text | D1 数据库 UUID | 进入 D1 数据库详情页复制 |

坑点:
SETUP_TOKEN必须设为 Secret 类型,否则初始化页面会提示“初始化令牌未检测到”。添加变量后,必须点击“保存并部署”,否则变量不会生效。
4. 执行数据库迁移
这是整个部署过程中最容易出错的环节,需要特别注意。
如果迁移报错,以下是常见错误及解决方案:
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
Couldn't find a D1 DB with the name | wrangler.jsonc 缺少 database_id | 在配置文件中补上 database_id |
no such table: settings | 数据库为空,迁移未执行 | 删除 D1 数据库重建,重新运行迁移 |
no such column: stored_bytes | 0012_mail_safety.sql 引用不存在的列 | 手动执行 ALTER TABLE messages ADD COLUMN stored_bytes INTEGER NOT NULL DEFAULT 0; |
no such table: draft_attachments | 该表未被创建 | 手动创建该表(参考迁移文件结构) |
incomplete input: SQLITE_ERROR | SQL 语法错误或不兼容 | 在 D1 Web 控制台中逐条执行 SQL,定位具体问题 |
如果迁移反复失败,最省事的办法是:
- 在 Cloudflare Dashboard → D1 SQL 数据库中,删除现有的
omnimail-db - 重新创建一个同名的 D1 数据库
- 需要注意要在Bindings 界面删除DB并重新添加新的D1
我最终就是通过“删除重建 D1”一次性成功完成了所有迁移。这是最简单粗暴但最有效的方法。
5. 部署 Worker
部署成功后,你会获得一个 *.workers.dev 的默认域名,例如 omnimail.你的用户名.workers.dev。
你可以进行访问 它但是如果你在中国大陆 它大概率失败 你可以使用 1.1.1.1 进行访问 本章的第七步:国内访问优化 章节讲述了如何进行国内访问
第二步:配置收信(Cloudflare Email Routing)
2.1 启用 Email Routing
- 进入 Cloudflare Dashboard → 你的域名 → 电子邮件 → 电子邮件路由。
- 点击 开始使用,它会自动添加 MX、SPF、DKIM 记录。
- 确认 DNS 记录状态显示为 “已锁定”。

2.2 配置 Catch-all 规则
这是关键步骤,确保所有发送到你的域名的邮件都能被 Worker 处理。
- 在 Email Routing 页面,找到 Catch-all 规则,点击 编辑。
- Action 选择 “发送到 Worker”。
- 在下拉菜单中选择你的 Worker(
omnimail)。 - 保存。
坑点:如果后续收信失败,检查 Worker 的 触发器 中是否配置了路由
email.bg4jts.cn/*。注意这里用的是 路由 而不是 自定义域,因为我们后面要用优选 IP,自定义域会强制走 CDN 代理,导致优选 IP 失效。
第三步:配置发信(Resend)
3.1 注册并验证域名
- 注册 Resend,在 Domains 中添加你的域名
bg4jts.cn。 - Resend 会提供几条 DNS 记录(DKIM、SPF 等),在 Cloudflare DNS 中添加对应的 TXT 记录。
- 等待验证通过(状态变为 “已验证”)。
[截图建议:Resend 域名验证成功页面,显示 “Domain verified”]
3.2 获取并配置 API Key
- 在 Resend 控制台 → API Keys 中创建新的 API Key,复制保存。
- 在 Worker 中添加 Secret:变量名
RESEND_DOMAIN_CONFIGS,值为 JSON 格式:{"bg4jts.cn": {"apiKey": "re_你的API密钥"}} - 保存并重新部署 Worker。
说明:如果不需要追踪邮件打开/点击状态,可以不配置 Webhook。如果需要,在 Resend 的 Webhooks 中添加端点
https://你的域名/api/webhooks/resend,并在 Worker 中添加RESEND_WEBHOOK_SECRET。
第四步:连接外部邮箱
QQ 邮箱
前置准备:
- 在 QQ 邮箱网页版的 设置 → 账户 中开启 IMAP/SMTP 服务。
- 按提示发送短信验证,获取 16 位授权码(不是 QQ 密码)。
配置步骤:
- 在 Worker 中添加 Secret:
QQ_MAIL_CREDENTIALS_KEY(至少 32 位随机字符串)。 - 重新部署 Worker。
- 在 OmniMail 左侧边栏点击 添加账户 → 选择 QQ 邮箱。
- 填写邮箱地址和 16 位授权码。
坑点:QQ 邮箱的密码字段需要填的是 授权码 而不是 QQ 密码。如果填错了会报认证失败。
Outlook / Microsoft 邮箱
前置准备:
- 在 Azure AD 中注册应用,获取 Client ID 和 Refresh Token。
- 应用注册时,受支持的帐户类型 要选 “任何组织目录中的帐户和个人 Microsoft 帐户”。
配置步骤:
- 在 Worker 中添加 Secret:
MICROSOFT_CREDENTIALS_KEY(至少 32 位随机字符串)。 - 重新部署 Worker。
- 在 OmniMail 中添加 Microsoft 账户,填写:
- 邮箱地址
- Refresh Token
- Client ID
- Authority:
consumers(个人账户)
坑点:如果 Azure 应用注册时只选了“仅组织目录中的帐户”,会报错
AADSTS50020。解决方法是在应用的 清单 中,将signInAudience改为AzureADandPersonalMicrosoftAccount。
第五步:开启二次验证(2FA)
- 在 Worker 中添加 Secret:
TOTP_ENCRYPTION_KEY(至少 32 位随机字符串)。 - 保存并重新部署 Worker。
- 登录 OmniMail 后台,进入 管理员二次验证 页面。
- 用 Google Authenticator 等 App 扫描二维码,输入动态验证码激活。

CAUTION激活后页面会显示 8 组恢复码,务必截图保存。关闭页面后不会再次显示,丢失恢复码将无法恢复账户访问。
第六步:配置自动备份
- 获取
CLOUDFLARE_ACCOUNT_ID和D1_DATABASE_ID(与之前相同)。 - 创建 D1 REST API Token:
- Cloudflare 右上角头像 → 我的个人资料 → API 令牌。
- 点击 创建令牌,选择 自定义令牌。
- 权限选择 D1 → 编辑,账户选择你的 Cloudflare 账户。
- 创建后复制保存令牌(只显示一次)。
- 在 Worker 中添加 Secret:
D1_REST_API_TOKEN。 - 保存并重新部署 Worker。
- 在 OmniMail 后台的 系统设置 → 备份、保留与配额 中配置备份策略。

第七步:国内访问优化(优选 IP)
由于 *.workers.dev 域名在国内常被屏蔽,我们需要为自定义域名配置国内访问优化。核心思路是:将自定义域名的 DNS 解析指向国内访问最快的 Cloudflare IP,同时保留 Worker 路由来处理邮件逻辑。
7.1 测试优选 IP
- 下载 CloudflareSpeedTest(建议从 Releases 页面下载)。
- 解压后运行
CloudflareST.exe(Windows),它会自动测试并输出延迟最低的 IP。 - 记录测试结果中延迟最低、丢包率为 0% 的 IP 地址。
7.2 修改 DNS 记录
- 在 Cloudflare DNS 中,找到你的邮件子域名(如 我的就是
email.bg4jts.cn)。 - 将记录类型从 CNAME 改为 A 记录。
- 记录值填入测出的最优 IP。
- 代理状态必须关闭(灰色云朵,仅 DNS),不能开启橙色云。
坑点:如果开启代理(橙色云),请求会强制走 Cloudflare CDN,优选 IP 就失效了。
7.3 配置 Worker 路由
- 进入
omnimailWorker → 设置 → 触发器。 - 在 路由 部分,添加或确认存在:
email.bg4jts.cn/*指向omnimail。 - 不要在自定义域中添加
email.bg4jts.cn,否则会与路由冲突。
注意:路由格式是
email.bg4jts.cn/*(带/*),不是*email.bg4jts.cn/*。
踩坑总结(强烈建议阅读)
| 坑点 | 现象 | 原因 | 解决方案 |
|---|---|---|---|
| SETUP_TOKEN 检测不到 | 初始化页面提示“初始化令牌未检测到” | 变量未添加到生产环境,或添加后未重新部署 | 检查变量作用域,确保是 Secret 类型,添加后点击“保存并部署” |
| 数据库迁移失败 | no such table: settings | 迁移文件未完整执行 | 删除 D1 数据库重建,重新运行迁移(最有效) |
| 手动迁移列缺失 | no such column: stored_bytes | 迁移 0012 中的 UPDATE 语句引用了尚未创建的列 | 在 D1 控制台手动执行 ALTER TABLE messages ADD COLUMN stored_bytes INTEGER NOT NULL DEFAULT 0; |
| 手动迁移表缺失 | no such table: draft_attachments | 创建该表的迁移文件未被正确执行 | 在 D1 控制台手动创建该表(参考迁移文件结构) |
| 收信失败 | 550 5.1.1 Address does not exist | OmniMail 中未创建对应的邮箱账户 | 在 OmniMail 后台 用户管理 中创建邮箱账户 |
| 收信失败 | 555 5.7.1 Mailbox unavailable | Catch-all 规则未正确指向 Worker,或 Worker 路由缺失 | 检查 Email Routing Catch-all 规则和 Worker 路由配置 |
| 国内访问超时 | 无法访问或 ERR_CONNECTION_TIMED_OUT | 默认 Workers 域名被屏蔽,CDN 路由绕路 | 使用优选 IP + A 记录 + Worker 路由 |
| Outlook 连接失败 | AADSTS50020 | Azure 应用不支持个人 Microsoft 账户 | 修改应用清单 signInAudience 为 AzureADandPersonalMicrosoftAccount |
| QQ 邮箱连接失败 | 认证失败 | 使用了 QQ 密码而非 16 位授权码 | 在 QQ 邮箱设置中生成授权码,填入 OmniMail |
| 部署后 Worker 名称混乱 | 多个 Worker 出现,部署名称不一致 | CLI 部署与 Dashboard 部署使用不同名称 | 统一使用 wrangler deploy,或在 wrangler.jsonc 中明确指定 name |
最终验证
完成所有配置后,建议按以下顺序验证:
- 收信测试:从 QQ/Gmail 发送邮件到
test@你的域名,检查 OmniMail 收件箱。 - 发信测试:在 OmniMail 中撰写邮件发送到自己的 QQ 邮箱。
- 外部邮箱测试:在 OmniMail 中添加 QQ/Outlook 邮箱,验证能否接收和发送。
- 2FA 测试:登出后重新登录,验证是否需要输入动态验证码。
- 优选 IP 测试:关闭代理工具,直接访问
https://email.你的域名,确认国内可访问。

结语
经过以上步骤,你应该已经拥有一个功能完整、国内可流畅访问的私人邮局了。它不仅可以收发邮件,还能聚合多个外部邮箱,支持 2FA 和自动备份,安全性也足够。
享受你的私人邮局吧! 🚀
如果这篇文章帮到了你,欢迎在评论区留言分享你的搭建体验,或者提出改进建议!