2910 字
15 分钟
自建邮局 OmniMail 保姆级教程

如果你厌倦了付费企业邮箱或临时邮箱的不稳定,想拥有一个完全属于自己的私人邮局,那么这篇文章就是为你准备的。我将带你一步步在 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:

mibgb65-cloud
/
OmniMail
Waiting for api.github.com...
00K
0K
0K
Waiting...

fork完毕后再cf

Workers & Pages -> “Create application”

在你连接github账户后,就可以选择你的仓库进行自动部署

3. 设置环境变量#

在 Cloudflare Dashboard 中,进入你的 Worker → 设置 → 变量,在 Variables & Secrets 中添加以下变量:

变量名类型说明获取方式
SETUP_TOKENSecret初始化令牌自定义强密码(至少 8 位)
SUPER_ADMIN_EMAILText管理员邮箱你的邮箱地址
CLOUDFLARE_ACCOUNT_IDTextCloudflare 账户 ID在 Workers & Pages 页面右侧可找到
D1_DATABASE_IDTextD1 数据库 UUID进入 D1 数据库详情页复制

alt text

坑点:SETUP_TOKEN 必须设为 Secret 类型,否则初始化页面会提示“初始化令牌未检测到”。添加变量后,必须点击“保存并部署”,否则变量不会生效。

4. 执行数据库迁移#

这是整个部署过程中最容易出错的环节,需要特别注意。

如果迁移报错,以下是常见错误及解决方案:

报错信息原因解决方案
Couldn't find a D1 DB with the namewrangler.jsonc 缺少 database_id在配置文件中补上 database_id
no such table: settings数据库为空,迁移未执行删除 D1 数据库重建,重新运行迁移
no such column: stored_bytes0012_mail_safety.sql 引用不存在的列手动执行 ALTER TABLE messages ADD COLUMN stored_bytes INTEGER NOT NULL DEFAULT 0;
no such table: draft_attachments该表未被创建手动创建该表(参考迁移文件结构)
incomplete input: SQLITE_ERRORSQL 语法错误或不兼容在 D1 Web 控制台中逐条执行 SQL,定位具体问题

如果迁移反复失败,最省事的办法是:

  1. 在 Cloudflare Dashboard → D1 SQL 数据库中,删除现有的 omnimail-db
  2. 重新创建一个同名的 D1 数据库
  3. 需要注意要在Bindings 界面删除DB并重新添加新的D1

我最终就是通过“删除重建 D1”一次性成功完成了所有迁移。这是最简单粗暴但最有效的方法。

5. 部署 Worker#

部署成功后,你会获得一个 *.workers.dev 的默认域名,例如 omnimail.你的用户名.workers.dev。

你可以进行访问 它但是如果你在中国大陆 它大概率失败 你可以使用 1.1.1.1 进行访问 本章的第七步:国内访问优化 章节讲述了如何进行国内访问

第二步:配置收信(Cloudflare Email Routing)#

2.1 启用 Email Routing#

  1. 进入 Cloudflare Dashboard → 你的域名 → 电子邮件 → 电子邮件路由。
  2. 点击 开始使用,它会自动添加 MX、SPF、DKIM 记录。
  3. 确认 DNS 记录状态显示为 “已锁定”。

ss

2.2 配置 Catch-all 规则#

这是关键步骤,确保所有发送到你的域名的邮件都能被 Worker 处理。

  1. 在 Email Routing 页面,找到 Catch-all 规则,点击 编辑。
  2. Action 选择 “发送到 Worker”。
  3. 在下拉菜单中选择你的 Worker(omnimail)。
  4. 保存。

坑点:如果后续收信失败,检查 Worker 的 触发器 中是否配置了路由 email.bg4jts.cn/*。注意这里用的是 路由 而不是 自定义域,因为我们后面要用优选 IP,自定义域会强制走 CDN 代理,导致优选 IP 失效。

第三步:配置发信(Resend)#

3.1 注册并验证域名#

  1. 注册 Resend,在 Domains 中添加你的域名 bg4jts.cn。
  2. Resend 会提供几条 DNS 记录(DKIM、SPF 等),在 Cloudflare DNS 中添加对应的 TXT 记录。
  3. 等待验证通过(状态变为 “已验证”)。

[截图建议:Resend 域名验证成功页面,显示 “Domain verified”]

3.2 获取并配置 API Key#

  1. 在 Resend 控制台 → API Keys 中创建新的 API Key,复制保存。
  2. 在 Worker 中添加 Secret:变量名 RESEND_DOMAIN_CONFIGS,值为 JSON 格式:
    {"bg4jts.cn": {"apiKey": "re_你的API密钥"}}
  3. 保存并重新部署 Worker。

说明:如果不需要追踪邮件打开/点击状态,可以不配置 Webhook。如果需要,在 Resend 的 Webhooks 中添加端点 https://你的域名/api/webhooks/resend,并在 Worker 中添加 RESEND_WEBHOOK_SECRET。

第四步:连接外部邮箱#

QQ 邮箱#

前置准备:

  1. 在 QQ 邮箱网页版的 设置 → 账户 中开启 IMAP/SMTP 服务。
  2. 按提示发送短信验证,获取 16 位授权码(不是 QQ 密码)。

配置步骤:

  1. 在 Worker 中添加 Secret:QQ_MAIL_CREDENTIALS_KEY(至少 32 位随机字符串)。
  2. 重新部署 Worker。
  3. 在 OmniMail 左侧边栏点击 添加账户 → 选择 QQ 邮箱。
  4. 填写邮箱地址和 16 位授权码。

坑点:QQ 邮箱的密码字段需要填的是 授权码 而不是 QQ 密码。如果填错了会报认证失败。

Outlook / Microsoft 邮箱#

前置准备:

  1. 在 Azure AD 中注册应用,获取 Client ID 和 Refresh Token。
  2. 应用注册时,受支持的帐户类型 要选 “任何组织目录中的帐户和个人 Microsoft 帐户”。

配置步骤:

  1. 在 Worker 中添加 Secret:MICROSOFT_CREDENTIALS_KEY(至少 32 位随机字符串)。
  2. 重新部署 Worker。
  3. 在 OmniMail 中添加 Microsoft 账户,填写:
    • 邮箱地址
    • Refresh Token
    • Client ID
    • Authority:consumers(个人账户)

坑点:如果 Azure 应用注册时只选了“仅组织目录中的帐户”,会报错 AADSTS50020。解决方法是在应用的 清单 中,将 signInAudience 改为 AzureADandPersonalMicrosoftAccount。

第五步:开启二次验证(2FA)#

  1. 在 Worker 中添加 Secret:TOTP_ENCRYPTION_KEY(至少 32 位随机字符串)。
  2. 保存并重新部署 Worker。
  3. 登录 OmniMail 后台,进入 管理员二次验证 页面。
  4. 用 Google Authenticator 等 App 扫描二维码,输入动态验证码激活。

alt text

CAUTION

激活后页面会显示 8 组恢复码,务必截图保存。关闭页面后不会再次显示,丢失恢复码将无法恢复账户访问。

第六步:配置自动备份#

  1. 获取 CLOUDFLARE_ACCOUNT_ID 和 D1_DATABASE_ID(与之前相同)。
  2. 创建 D1 REST API Token:
    • Cloudflare 右上角头像 → 我的个人资料 → API 令牌。
    • 点击 创建令牌,选择 自定义令牌。
    • 权限选择 D1 → 编辑,账户选择你的 Cloudflare 账户。
    • 创建后复制保存令牌(只显示一次)。
  3. 在 Worker 中添加 Secret:D1_REST_API_TOKEN。
  4. 保存并重新部署 Worker。
  5. 在 OmniMail 后台的 系统设置 → 备份、保留与配额 中配置备份策略。

alt text

第七步:国内访问优化(优选 IP)#

由于 *.workers.dev 域名在国内常被屏蔽,我们需要为自定义域名配置国内访问优化。核心思路是:将自定义域名的 DNS 解析指向国内访问最快的 Cloudflare IP,同时保留 Worker 路由来处理邮件逻辑。

7.1 测试优选 IP#

  1. 下载 CloudflareSpeedTest(建议从 Releases 页面下载)。
  2. 解压后运行 CloudflareST.exe(Windows),它会自动测试并输出延迟最低的 IP。
  3. 记录测试结果中延迟最低、丢包率为 0% 的 IP 地址。

7.2 修改 DNS 记录#

  1. 在 Cloudflare DNS 中,找到你的邮件子域名(如 我的就是email.bg4jts.cn)。
  2. 将记录类型从 CNAME 改为 A 记录。
  3. 记录值填入测出的最优 IP。
  4. 代理状态必须关闭(灰色云朵,仅 DNS),不能开启橙色云。

坑点:如果开启代理(橙色云),请求会强制走 Cloudflare CDN,优选 IP 就失效了。

7.3 配置 Worker 路由#

  1. 进入 omnimail Worker → 设置 → 触发器。
  2. 在 路由 部分,添加或确认存在:email.bg4jts.cn/* 指向 omnimail。
  3. 不要在自定义域中添加 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 existOmniMail 中未创建对应的邮箱账户在 OmniMail 后台 用户管理 中创建邮箱账户
收信失败555 5.7.1 Mailbox unavailableCatch-all 规则未正确指向 Worker,或 Worker 路由缺失检查 Email Routing Catch-all 规则和 Worker 路由配置
国内访问超时无法访问或 ERR_CONNECTION_TIMED_OUT默认 Workers 域名被屏蔽,CDN 路由绕路使用优选 IP + A 记录 + Worker 路由
Outlook 连接失败AADSTS50020Azure 应用不支持个人 Microsoft 账户修改应用清单 signInAudience 为 AzureADandPersonalMicrosoftAccount
QQ 邮箱连接失败认证失败使用了 QQ 密码而非 16 位授权码在 QQ 邮箱设置中生成授权码,填入 OmniMail
部署后 Worker 名称混乱多个 Worker 出现,部署名称不一致CLI 部署与 Dashboard 部署使用不同名称统一使用 wrangler deploy,或在 wrangler.jsonc 中明确指定 name

最终验证#

完成所有配置后,建议按以下顺序验证:

  1. 收信测试:从 QQ/Gmail 发送邮件到 test@你的域名,检查 OmniMail 收件箱。
  2. 发信测试:在 OmniMail 中撰写邮件发送到自己的 QQ 邮箱。
  3. 外部邮箱测试:在 OmniMail 中添加 QQ/Outlook 邮箱,验证能否接收和发送。
  4. 2FA 测试:登出后重新登录,验证是否需要输入动态验证码。
  5. 优选 IP 测试:关闭代理工具,直接访问 https://email.你的域名,确认国内可访问。

alt text

结语#

经过以上步骤,你应该已经拥有一个功能完整、国内可流畅访问的私人邮局了。它不仅可以收发邮件,还能聚合多个外部邮箱,支持 2FA 和自动备份,安全性也足够。

享受你的私人邮局吧! 🚀


如果这篇文章帮到了你,欢迎在评论区留言分享你的搭建体验,或者提出改进建议!

自建邮局 OmniMail 保姆级教程
https://bg4jts.cn/posts/omnimail-tutorial/
作者
BG4JTS
发布于
2026-09-06
许可协议
CC BY-NC-SA 4.0