我用 Cloudflare 搭了一个 FlashInbox 临时邮箱

张开发
2026/4/14 22:46:29 15 分钟阅读

分享文章

我用 Cloudflare 搭了一个 FlashInbox 临时邮箱
本文转载自个人博客若内容存在缺失或后续有更新可通过下方链接跳转至原博客页面查阅完整内容我用 Cloudflare 搭了一个 FlashInbox 临时邮箱 - 萑澈的寒舍https://hs.cnies.org/archives/build-flashinbox我一直觉得临时邮箱这种东西能自己掌握还是自己掌握比较踏实。公共服务不是不能用而是你用的时候总要多留个心眼域名不是你的地址不是你的哪天规则变了、站点没了或者数据清了你也没什么办法。刚好FlashInbox这套项目走的又是我比较喜欢的路线前端Next.js部署在 Cloudflare Workers收信靠 Cloudflare Email Routing数据放进D1。不需要自己折腾一整套传统邮件服务成本和复杂度都低不少。项目仓库在这里https://github.com/CtelSpecu/FlashInbox演示地址https://flashinbox.hxcn.top我这次就是把它从仓库拉下来按自己的域名和 Cloudflare 环境跑了一遍。装完之后手里会有一套自己的临时邮箱服务能匿名创建地址能收邮件能认领邮箱拿 Key也能靠username key把邮箱找回来。默认 Key 有效期是 15 天拿来收验证码、接通知、做注册测试都挺顺手。最后大概会变成这样网页在mail.example.com上打开临时邮箱地址是bluepanda23example.com这种形式邮件能正常收进来后台还能自己管域名、规则和隔离队列。FlashInbox 是什么先把边界说清楚免得装到一半才发现想要的根本不是这个。FlashInbox更像一个收件站不是常规邮箱服务。它现在能做的事情主要有这些支持匿名创建临时邮箱支持接收入站邮件不存附件支持认领邮箱并生成一次性明文 Key支持用username key恢复访问提供一个管理后台你如果想要的是“自己域名下的临时邮箱”那这个方向没问题如果想要的是“自己做一个 Gmail”那就是另一回事了。准备工作先准备这些东西一个 Cloudflare 账号并且已经开通Workers、D1、Email Routing、Turnstile一个已经接入 Cloudflare DNS 的域名例如example.com本地环境里已经装好bun本地可以使用wrangler这里先记住一件事Web 访问域名可以是mail.example.com真正收信的域名可以是example.com。这两个域名最好分开因为 Cloudflare Email Routing 的 catch-all 规则吃的是主域不是mail.example.com这种 Web 子域。架构先看明白这套东西不是一个 Worker 从头跑到尾而是三部分一起干活flashinbox这是主应用负责网页、API、用户收件箱、管理后台。它读的是wrangler.toml。flashinbox-email这是入站邮件 Worker负责接住 Email Routing 转过来的邮件解析后写进 D1。它读的是wrangler.email.toml。flashinbox-scheduled这是定时任务 Worker负责清理、统计之类的后台工作。它读的是wrangler.scheduled.toml。这三个 Worker 必须指向同一个 D1。很多“页面能打开但收不到信”的问题最后查下来都不是代码坏了而是这里没配对。第 1 步克隆仓库并安装依赖先把仓库拉下来git clone https://github.com/CtelSpecu/FlashInbox.git cd FlashInboxbun install项目里已经带了wrangler后面直接用bunx wrangler也行。想先确认本地环境没问题可以顺手看一眼package.json里的几个命令bun run build:worker bun run dev bun test第 2 步创建 D1先登录wrangler login再创建生产数据库wrangler d1 create flashinbox-db执行完以后Cloudflare 会返回一个database_id。把它分别填到wrangler.toml、wrangler.email.toml和wrangler.scheduled.toml里。这三份配置里的database_id必须一致。只改主应用那一份不够网页是能开后台也可能能进但邮件根本不会进到你以为的那个库里。第 3 步执行数据库迁移接着把表建好wrangler d1 execute flashinbox-db --remote --filemigrations/0001_init.sql wrangler d1 execute flashinbox-db --remote --filemigrations/0002_mailboxes_banned.sql两条都跑不要省。0001_init.sql是基础表结构0002_mailboxes_banned.sql跟后台禁用邮箱的状态有关少跑一条后面多半要踩坑。如果迁移时碰到BEGIN TRANSACTION、COMMIT之类的报错说明迁移文件不符合 D1 的要求。当前仓库里的迁移文件已经处理过照着跑通常没事。第 4 步配置域名wrangler.toml里有两个地方必须看生产环境路由例如[env.production] name flashinbox routes [ { pattern mail.example.com, custom_domain true } ]默认邮箱域名例如[env.production.vars] DEFAULT_DOMAIN example.com这两个值不是一回事。mail.example.com是用户打开网页的地址example.com才是真正生成临时邮箱地址时用的收信域名。很多人第一次配的时候脑子里只有一个“域名”结果 Web 域名和收信域名搅在一起后面查问题会非常累。第 5 步创建 TurnstileFlashInbox的认领流程用到了 Turnstile所以这里先建一个站点绑定主应用域名比如mail.example.com。建好之后把TURNSTILE_SITE_KEY和TURNSTILE_SECRET_KEY记下来后面填进主应用配置里。第 6 步配置 Secrets接下来配主应用的 Secretswrangler secret put ADMIN_TOKEN --env production wrangler secret put KEY_PEPPER --env production wrangler secret put SESSION_SECRET --env production wrangler secret put TURNSTILE_SECRET_KEY --env production wrangler secret put TURNSTILE_SITE_KEY --env production这里最重要的是ADMIN_TOKEN、KEY_PEPPER和SESSION_SECRET。前者是后台登录口令后两个分别用于 Key 哈希和会话签名。尤其是KEY_PEPPER这个值别随便改它跟 Key 哈希和恢复流程绑得很死。你改一次旧 Key 基本就都失效了。第 7 步部署主应用主应用这一层走的是Next.js OpenNext Cloudflare Workers。先构建bun run build:worker再部署wrangler deploy --env production跑到这里站点本身应该已经能打开了比如https://mail.example.com如果这时候网页都打不开就别急着去查邮件链路先把主应用的构建、路由和自定义域名检查完。第 8 步部署两个 Worker主应用只是前台收邮件和做清理的活还得靠另外两个 Worker。先部署 Email Workerwrangler deploy --config wrangler.email.toml再部署 Scheduled Workerwrangler deploy --config wrangler.scheduled.toml这一步特别容易漏而且一漏就很容易把人带偏。页面能开创建邮箱也不报错乍一看像是已经部署好了甚至会让人误以为后面只剩发邮件验证一下。等你真的往那个地址发一封测试邮件才会发现收件箱安静得像没通电。页面能开不代表收信链路已经通了。第 9 步初始化domains这里也是高频坑。FlashInbox的 Email Worker 不会见信就收它会先查 D1 里的domains表看这个域名是不是存在、是不是enabled。表里没有或者状态不对邮件就进不来。这个表有两种初始化办法。方案 A后台添加部署完成后访问https://mail.example.com/admin用ADMIN_TOKEN登录在 Domains 页面里把example.com加进去并设置为enabled。方案 B写入 D1wrangler d1 execute flashinbox-db --remote --command INSERT INTO domains (name, status, note, created_at, updated_at) VALUES (example.com, enabled, prod, strftime(%s,now)*1000, strftime(%s,now)*1000);如果你后面打算让多个域名一起收信比如example.com和example.net那每个域名都得写进去别指望一个默认值把所有事情包圆。第 10 步配置 Email Routing下面开始配真正的收信链路。在 Cloudflare Dashboard 里打开你的域名进入 Email Routing把下面几项配上启用 Email Routing创建一条 Catch-all 规则Action 选择Send to a WorkerWorker 选择flashinbox-email逻辑很简单别人发到anythingexample.com的邮件Cloudflare 先接住再转给你的 Email Worker。这里最容易混的是两件事Catch-all 针对的是主收信域名也就是说通常是example.com不是mail.example.com。如果 Catch-all 没指向 Worker那邮件就可能直接被丢掉而且不一定给你多清楚的提示。很多时候你只能在 Activity log 里看到一个Dropped。第 11 步验证收信配置做完之后最好马上测一遍。先打开你的站点创建一个临时邮箱。假设系统给你分配了bluepanda23example.com然后拿另一个外部邮箱往这个地址发一封测试邮件。重点看三件事前端能不能看到收件箱内容管理后台里的域名状态是不是正常以及 Cloudflare Email Routing 的 Activity log 里这封邮件有没有被正确投递。如果前端没看到邮件就按这个顺序排domains表里有没有example.com这个域名状态是不是enabledEmail Routing 的 Catch-all 是否真的指向了flashinbox-email三个 Worker 是否都已经部署三份 Wrangler 配置是不是都绑到了同一个 D1如果还不行可以直接看 Email Worker 日志wrangler tail flashinbox-email如果日志里出现Domain not found、Domain is disabled这种提示就别猜了直接回去查配置。几个常见坑1. 主站能开不等于邮箱已经能收信这是最容易让人误判的一点。网页能开只代表主应用部署好了真正决定能不能收信的是 Email Routing、Email Worker 和domains表有没有一起对上。2. 三个 Worker 必须共用同一个 D1别把它们当成三个独立项目。对FlashInbox来说这就是同一套系统的三个入口。3.DEFAULT_DOMAIN不是网页访问域名它代表的是默认收信域名不是网页访问域名。这个值写错前端生成出来的邮箱地址就会跟你的预期不一致。4. 附件不会保存这不是 bug而是项目本身就没打算存附件。收验证码、通知、注册链接都没问题但别拿它当文件邮箱用。5. Cloudflare Email Routing 有平台限制大于25 MiB的邮件别指望它稳稳接住。这个上限不是FlashInbox自己定的是 Cloudflare Email Routing 本身的限制。适合哪些场景这篇方案更适合下面这些场景你想用自己的域名收临时邮件你不想继续依赖公共临时邮箱你不想自己维护完整邮件服务器你希望网页、收信、存储和后台都留在 Cloudflare 体系里如果你的需求差不多就是这些那FlashInbox值得花点时间装一下。它当然不是正式办公邮箱的替代品也不适合做复杂邮件协作。但如果你只是想把“临时邮箱”这件事握回自己手里用自己的域名来收用自己的后台来管那这套东西已经够用了。

更多文章