前两天给一个小工具站补注册登录。
这件事一开始看着很简单:用户填邮箱和密码,系统发一封验证邮件,点一下就完了。
真做下来才发现,最花时间的不是邮件模板,而是中间这一串:域名、DNS、发信平台、Worker Secret、认证配置、手机和电脑跨设备验证。
任何一环只配一半,表面上都会绿。用户一用,就露馅。
我这次就是这么卡过来的。下面把整个过程记下来。你也是 Cloudflare 部署的工具站,照着走一遍,应该能少踩不少坑。
说明:文中统一用 app.example.com 代表网站,用 mail.example.com 代表发信子域名。截图已把真实域名替换掉,API Key 从不出现在文章、截图或 Git 里。

先说一个最容易误会的地方
我一开始把“用户注册”“收到邮件”“验证成功”当成了一件事。
其实不是。它至少是四件事:
- 用户在你的网站提交邮箱和密码;
- 你的服务端拿着发信 Key 调 Resend;
- Resend 用你验证过的域名把邮件投出去;
- 用户点链接,认证系统把这个用户的 email_verified 更新为真。
邮件到了,不代表第 4 步完成。域名显示 Verified,也不代表注册接口真的拿到了 API Key。
这两个地方,后面都让我踩了坑。

01 我为什么没直接用主域名发邮件
主站我用 app.example.com,发信用 mail.example.com,发件人写成:
Product Name <noreply@mail.example.com>不是为了显得专业,就是为了把发信信誉隔开。
以后注册验证、重置密码、付款通知都从这个子域名发。哪天邮件量大了、误触发投诉了,首先受影响的是邮件子域名,不是主站本身。Resend 官方也明确建议使用子域名来隔离不同类型的发送信誉。Resend 域名说明
这里顺带说一个小点:Resend 负责“发”,不负责给你开收件箱。noreply@ 本来就不需要收件箱;以后真要接用户咨询,再单独做 support@app.example.com,通过 Cloudflare Email Routing 转发到自己常用邮箱就够了。
02 先把域名这一步做对
注册并登录 Resend 后,进入:
Domains -> Add Domain填写 mail.example.com。地区怎么选?我这次按应用数据库和主要用户的区域来选。它影响的是服务数据所在区域,不决定邮件会不会投到某个国家。

你在这一步只需要确认三件事:
- Name 填的是邮件子域名,例如 mail.example.com,不是网站根域名;
- Region 选择离你的应用数据和主要用户较近的区域;
- 不知道高级选项怎么填时,保持默认即可。第一次接事务邮件,不需要先配置追踪域名。
高级选项里我只保留两件事:
- Custom Return-Path 用默认的 send;
- 不开 click tracking 和 open tracking。
注册验证邮件的目的只是把用户带回网站,不是做营销归因。少一个跟踪域名,少一段隐私解释,也少一套以后要维护的东西。
然后会看到两种 DNS 接入方式:
- Auto configure:授权 Resend 连接 Cloudflare,它自动写入记录;
- Manual setup:自己复制 DNS 记录到 Cloudflare。
如果账号本来就在 Cloudflare,想省事可以选 Auto configure。但授权页一定要看一眼:应当只涉及目标域名的 DNS 修改。如果它要求范围明显超出 DNS 管理,就回到 Manual setup。
手动配置时,不要自己猜 SPF、DKIM 的值,逐条复制 Resend 页面给出的内容。通常会有:
- DKIM:证明邮件确实由被授权的服务签名;
- SPF:声明哪些服务器有权代表这个子域名发信;
- MX:处理回退路径;
- DMARC:建议先用 v=DMARC1; p=none; 做监测,稳定后再决定要不要提高策略。
Cloudflare 里的 DKIM CNAME 必须保持 DNS only,不要开橙云代理。TXT、MX 记录不涉及代理。全部加完回到 Resend,状态变为 Verified 才算这一段结束。

看到这张页面后,按这个顺序做:
- 如果选择 Auto configure,确认 Cloudflare 授权后等待 Resend 自动写入;
- 如果选择 Manual setup,在 Cloudflare 打开目标域名的 DNS -> Records -> Add record;
- 每添加一条就回到 Resend 对照 Type、Name、Content 和 Priority;
- 回到 Resend 点验证或等待自动验证。出现 Verified 后再继续创建 API Key。
不要启用 Enable Receiving,除非你确实要在 Resend 收信。注册验证只需要发信。
03 API Key 别随手创建,也别随手放
不要把 Resend 入门页自动生成的演示 Key 当生产 Key。
在 Resend 左侧进入:
API Keys -> Create API Key我给生产项目创建的规则是:
Name: product-production-worker
Permission: Sending access事务邮件只需要发信权限,不需要 Full access。Key 只会显示一次,复制后立刻进入下一步;不要发到聊天里,不要写进 .env.example,更不要提交 Git。

这里不要急着点 Done:先打开终端,把下一节的 Secret 命令准备好。复制 Key 后立刻粘贴进终端的隐藏输入框。这样 Key 从 Resend 到 Cloudflare 的路径最短,也不会落到笔记、聊天记录或截图里。
域名验证成功后,可以使用该域名下任意合法发件地址;Resend 的发件人不等于你真的开了一个收件箱。Resend 发件人说明
04 Key 到底放哪里
我的项目是 Cloudflare Worker,所以 Key 不进数据库明文,也不写进前端环境变量,而是写入 Worker Secret:
pnpm exec wrangler secret put RESEND_API_KEY终端提示输入时粘贴 re_... Key。再写入发件人:
pnpm exec wrangler secret put RESEND_SENDER_EMAIL输入:
Product Name <noreply@mail.example.com>Cloudflare Secret 的特点是:设置后可以被 Worker 使用,但不会再从控制台完整读出来。这个边界很适合 API Key、支付密钥、认证密钥这类东西。Cloudflare Secrets 文档
命令执行成功时,终端会明确显示 Success! Uploaded secret RESEND_API_KEY。如果没有这句话,不要假设 Secret 已经生效;重新执行命令,并检查当前目录是否就是部署该 Worker 的项目根目录。
05 真正让我卡住的,不在 Resend
这里是我这次实际踩到的坑。
项目里既有数据库配置,也有 Worker Secret。最开始认证路由只读了数据库配置,公开配置页却读了“数据库 + 环境变量”的合并配置。结果就是:页面告诉我“已开启邮箱验证”,但真正处理注册的服务端拿不到 Resend Key,于是把验证逻辑降级了。
正确思路是:认证处理器必须读取完整配置,尤其是发信 Key 这种只存在于 Worker Secret 的值。
以 Better Auth 为例,服务端需要同时保证:
emailAndPassword: {
requireEmailVerification: true,
autoSignIn: false,
},
emailVerification: {
sendOnSignUp: true,
sendOnSignIn: true,
autoSignInAfterVerification: true,
}这里我不再让浏览器自己“顺手发一封”。注册接口直接由服务端发,未验证用户登录时也由服务端补发。这样用户网络慢、页面还没加载完、有人直接调用 API,都不会绕过验证。
06 手机点了,电脑为什么没反应
这件事看起来小,但真测时很容易误判。
用户在电脑注册,邮件在手机上点开。链接成功后,手机浏览器会拿到会话 Cookie,电脑浏览器没有。此时电脑上的“继续”按钮如果只检查本机有没有会话,就会错误提示“还没验证”。
正确体验应该是:
- 同一台设备点邮件:验证后自动进入产品;
- 换设备点邮件:账号已经验证成功,电脑端继续按钮应去登录页,让用户正常登录;
- 绝不能把“不同设备没有 Cookie”当成“验证失败”。
这类问题用接口看不出来,必须真的拿手机和电脑各测一遍。
07 最后别只看控制台变绿
我最终用这张清单验收:
- [ ] Resend 域名状态是 Verified;
- [ ] API Key 是 Sending access,不在代码仓库;
- [ ] 注册一个新邮箱后,账户未验证时不能直接登录;
- [ ] 邮箱收到验证邮件,邮件链接能把 email_verified 改为真;
- [ ] 同设备和跨设备验证都走得通;
- [ ] 忘记密码邮件也能收到并完成重置;
- [ ] Resend Logs 里能看到 Delivered,而不是只看网站没有报错;
- [ ] DMARC 先处于监测模式,后面再根据实际投递调整。
这套东西刚开始看着只是“给网站接个邮件”。但它本质上是用户身份的第一道门。
我现在的感觉是,注册验证这种东西先别追求花哨。
先让它能测、能查、能在出错的时候知道是哪一段出了问题,比一上来搞一堆营销自动化重要得多。
可以直接照抄的执行顺序
如果你只想先把一版注册验证邮件跑通,按下面顺序完成,不要跳步:
- 在 Cloudflare 中托管你的域名;
- 在 Resend 添加 mail.example.com;
- 用 Auto configure 或 Manual setup 完成 DNS,并等到 Verified;
- 创建 Sending access API Key;
- 用 wrangler secret put 写入 RESEND_API_KEY 和 RESEND_SENDER_EMAIL;
- 确认服务端认证处理器实际读取 Worker Secret;
- 部署 Worker;
- 用一个新邮箱注册,在电脑和手机各完成一次验证测试;
- 到 Resend Logs 检查投递状态。
前 5 步是配置,后 4 步才是验收。两部分都完成,才叫“邮件验证接好了”。
官方资料:
- Resend 域名与 DNS 验证
- Resend DMARC 指南
- Cloudflare Worker Secrets