域名配置
在 Cloudflare 注册域名,或将 Spaceship 等第三方注册商购买的域名接入 Cloudflare,再完成网站、邮件和 R2 自定义域配置。
第一次部署 Saavo 时,可以先使用 Cloudflare 提供的 workers.dev 地址。等项目能够正常访问,再配置自己的域名会更稳妥:部署问题和域名问题可以分开排查,也不用在项目还没跑通时来回修改 DNS。
本页以 webpagetopdf.dev 为例,依次完成下面这些事情:
| 用途 | 示例 | 是否必须 |
|---|---|---|
| 网站主域名 | webpagetopdf.dev | 正式上线时建议配置 |
| 网站备用域名 | www.webpagetopdf.dev | 可选,通常跳转到主域名 |
| 接收用户邮件 | support@webpagetopdf.dev | 有客服或网站需要支持邮箱时配置 |
| 发送系统邮件 | send@mail.webpagetopdf.dev | 注册验证、找回密码等功能需要 |
| R2 文件域名 | files.webpagetopdf.dev | 需要直接公开 R2 文件时配置 |
这些地址不必一次全部开通。网站域名配置完成后就可以上线;邮件和 R2 按产品实际需要继续处理。
先了解注册商和 DNS 的区别
域名注册商负责域名的购买、续费和所有人信息,DNS 服务负责把域名指向网站、邮箱和存储服务。两者可以是同一家公司,也可以分开。
| 购买方式 | 域名在哪里续费 | DNS 在哪里管理 | 适合的情况 |
|---|---|---|---|
| 在 Cloudflare 购买 | Cloudflare | Cloudflare | 操作最少,准备长期使用 Cloudflare |
| 在 Spaceship 等第三方购买 | 原注册商 | 接入后由 Cloudflare 管理 | 其它注册商价格、后缀或付款方式更合适 |
在 Spaceship 修改域名服务器,只是把 DNS 管理权交给 Cloudflare,并没有把域名转移到 Cloudflare Registrar。域名到期后仍然在 Spaceship 续费,注册人信息和自动续费也继续在那里管理。
所有 Cloudflare 资源尽量放在同一个账户
域名 Zone、Saavo Worker 和 R2 Bucket 应放在同一个 Cloudflare 账户。一个 Cloudflare 用户可以加入多个账户,操作前先看清当前账户名称和 Account ID,避免域名接入了一个账户,项目却部署在另一个账户。
在 Cloudflare 购买域名
如果准备长期使用 Cloudflare,直接通过 Cloudflare Registrar 注册最省事。购买完成后,域名会自动使用 Cloudflare DNS,不需要再修改域名服务器。
购买前先准备好:
- 已经验证邮箱的 Cloudflare 账号;
- 可以长期使用的联系邮箱;
- 准确的注册人姓名、地址和电话;
- 可以完成付款并支持后续自动续费的付款方式。
注册人邮箱不要填写正在购买的域名邮箱,例如 admin@webpagetopdf.dev。此时这个邮箱还不能接收邮件,一旦注册局要求验证或者续费失败,很可能收不到通知。使用现有且长期可控的邮箱更可靠。
不要只看第一年的价格
Cloudflare 的搜索结果会同时显示首年价格和续费价格。促销只影响第一年,后续续费通常会恢复原价;标有 Premium 的域名还可能明显更贵。确认域名拼写、续费价格和注册年限后再付款,域名注册完成后通常不能退款。
搜索并选择域名
登录 Cloudflare Dashboard,切换到准备部署 Saavo 的账户,然后打开 Domain Registration → Register Domains。
搜索框既可以输入完整域名,例如 webpagetopdf.dev,也可以输入产品名称,让 Cloudflare 推荐不同后缀。找到准备购买的域名后,先核对拼写、首年价格和续费价格,再点击对应的购买入口。

搜索结果只能说明域名此刻看起来仍可注册。进入购买流程后,Cloudflare 还会向注册局进行一次最终检查;如果随后提示不可注册,返回搜索页重新选择即可。
填写注册信息
在 Complete your registration 页面选择注册年限,并确认自动续费设置。Cloudflare 默认开启自动续费,右侧会同时显示本次付款金额、到期日期和预计续费价格。
接着填写真实、完整的注册人信息。Cloudflare 当前只接受 ASCII 字符,姓名和地址不要填写中文,可以按实际信息使用拼音或英文。这里填写的邮箱必须能够长期使用,电话也要选择正确的国家或地区代码。

填写完成后,点击右侧的 Continue to pay for… 进入订单确认页。
核对订单并付款
在 Register domain 页面再次核对域名、注册年限、应付金额和付款方式。阅读域名注册协议、服务条款和隐私政策,确认无误后勾选页面要求的选项,再点击 Complete purchase。

不要因为浏览器已经记住付款方式就直接提交。域名拼写错误、选错后缀或者没有看清续费价格,通常不能在购买后通过退款解决。
等待注册完成
Cloudflare 通常会在几十秒内完成注册。页面显示 Your domain is on its way,并在域名前出现成功标记后,说明域名已经注册到当前账户。

点击域名右侧的 Manage,可以直接进入管理页面;以后也可以从 Domain Registration → Manage Domains 找到它。
检查域名状态
在域名管理页面确认状态为 Active,并检查到期时间、续费价格和 Auto renew 是否符合预期。

如果 Cloudflare 或注册局发来注册人邮箱验证邮件,要及时完成验证。注册人邮箱未验证或验证失效时,域名可能被暂停解析。联系人信息和付款方式以后发生变化,也应及时更新。
Cloudflare Registrar 当前的购买流程、字段限制和域名服务器要求,以官方的注册新域名说明为准。
注册在 Cloudflare 的域名必须继续使用 Cloudflare DNS
这项限制目前仍然存在。只要域名仍由 Cloudflare Registrar 管理,就不能把权威域名服务器改成其它 DNS 服务商。网站和邮箱仍然可以使用第三方服务,只需在 Cloudflare 中配置相应的 A、CNAME、MX 或 TXT 记录;需要时也可以把某个子域名单独委派出去。
如果必须把整个域名改用其它 DNS 服务,需要先把域名转移到其他注册商,并留意新注册、刚转入或修改注册人信息后可能存在的转移锁定期。Business 和 Enterprise 计划提供的 Custom Nameservers 只是自定义 Cloudflare 域名服务器的名称,并不等于改用了第三方 DNS。
在 Spaceship 购买并接入 Cloudflare
如果域名是在 Spaceship 购买的,注册和续费仍由 Spaceship 管理,只把 DNS 交给 Cloudflare 即可。整个过程不需要再次购买域名,也不需要把域名转移到 Cloudflare Registrar。
下面采用 Cloudflare 的 Full setup(完整接入)方式:先把域名添加到 Cloudflare,再到 Spaceship 将域名服务器改成 Cloudflare 分配的地址。接入完成后,DNS 记录统一在 Cloudflare 管理,域名续费仍然在 Spaceship 处理。
在 Spaceship 购买域名
打开 Spaceship 域名搜索,输入准备注册的完整域名。加入购物车前,重点核对域名拼写、注册价格、续费价格、注册年限和可能产生的 ICANN 费用,不要只看第一年的促销价。
填写真实的联系人信息并完成付款后,回到 Domain List,确认域名已经出现在账户中并且可以管理。结算时推荐的主机、Spacemail 和其它附加服务都不是接入 Cloudflare 的必要条件,暂时用不到可以不购买。
选择连接已有域名
Cloudflare 会列出三种操作:连接已有域名、把域名转移到 Cloudflare,以及购买新域名。域名已经在 Spaceship 注册,因此选择 Connect a domain。

不要选择 Transfer a domain。连接域名只是把 DNS 交给 Cloudflare,转移域名则会更换注册商,两者不是一回事。
输入根域名
在 Domain name 中填写根域名,例如 webpagetopdf.dev,不要填写 www.webpagetopdf.dev,也不要带 https://、端口或路径。

页面下方还会显示 AI 爬虫策略和 DNS 记录导入方式。这些选项不会影响域名能否接入 Cloudflare,第一次配置可以先保留默认值,之后再根据网站需要单独调整。确认域名无误后,点击 Continue。
检查 Cloudflare 扫描到的 DNS 记录
选择计划后会进入 Review your DNS records 页面。Cloudflare 会尝试从原来的 DNS 服务中扫描记录,但扫描结果不一定完整,不能把它当作原记录的完整备份。

如果这是刚购买、还没有使用过的域名,页面中通常只有 Spaceship 自动添加的停放页记录,这些记录可以删除。如果域名已经有网站、邮箱或其它服务,不要全部删除,应先把原 DNS 中的 A、AAAA、CNAME、MX、TXT 等有效记录逐项核对并补齐。
确认记录后,点击 Continue to activation。以后还可以在 Cloudflare 的 DNS → Records 中继续添加或修改记录。
保存 Cloudflare 分配的域名服务器地址
Cloudflare 会显示需要替换的旧地址,以及分配给当前域名的两条 Cloudflare 域名服务器地址。先不要关闭这个页面,下一步需要把这两条地址填入 Spaceship。

每个域名分配到的地址可能不同。请复制自己页面中显示的内容,不要直接照抄本教程截图里的 guss.ns.cloudflare.com 和 june.ns.cloudflare.com。
如果域名原来开启了 DNSSEC,先在原 DNS 服务中关闭,并删除旧的 DS 记录。等 Cloudflare 确认域名接入成功后,再通过 Cloudflare 重新开启 DNSSEC。
改用 Cloudflare 域名服务器
在打开的面板中选择 Custom nameservers,删除 Spaceship 原来的地址:
launch1.spaceship.net
launch2.spaceship.net然后填入 Cloudflare 为当前域名分配的两条地址。以本页截图中的域名为例:
guss.ns.cloudflare.com
june.ns.cloudflare.com上面只是示例,实际操作必须以你自己的 Cloudflare 页面为准。核对两条地址,确认没有遗漏、没有多余空格,也没有混入原来的 Spaceship 地址,然后保存设置。
如果 Spaceship 提示现有产品连接和 DNS 记录将停止生效,先确认需要保留的记录已经添加到 Cloudflare,再确认切换。Spaceship 中的原记录不会继续对外解析。
通知 Cloudflare 并等待接入完成
回到刚才的 Cloudflare 引导页面,点击底部的 I updated my nameservers。Cloudflare 会开始检查域名服务器,域名状态会先显示 Pending Nameserver Update,确认成功后变成 Active。
域名服务器更新通常不会立刻完成。Cloudflare 提示最长可能需要 24 小时,Spaceship 提示全球 DNS 完整生效可能需要 48 小时。等待期间不要反复切回 Spaceship 的域名服务器,否则只会让状态更难判断。
域名变成 Active 后,DNS 记录就改在 Cloudflare 中管理。如果前面关闭了 DNSSEC,此时再按照 Cloudflare 提供的 DS 信息重新开启。
如果超过 24 小时仍然停留在 Pending Nameserver Update,检查 Spaceship 是否保存成功、两条地址是否完整、是否仍然混有 Spaceship 的域名服务器,以及注册局是否还保留旧的 DS 记录。详细排查方法见 Cloudflare 的 Pending Nameserver Update 和完整接入流程。
改 Nameserver 不是转移域名
接入完成后,DNS 记录在 Cloudflare 管理,域名续费仍在 Spaceship 管理。不要因为 Cloudflare 已经显示 Active,就关闭 Spaceship 的自动续费或删除注册人信息。
规划域名的用途
开始添加记录之前,先决定每个名称负责什么。一个简单产品可以这样安排:
| 名称 | 用途 | 由谁配置 |
|---|---|---|
webpagetopdf.dev | 网站唯一正式入口 | Saavo domain:set |
www.webpagetopdf.dev | 跳转到正式入口 | Cloudflare Redirect Rules |
support@webpagetopdf.dev | 接收用户来信 | Cloudflare Email Routing |
mail.webpagetopdf.dev | 通过 Resend 发送系统邮件 | Resend + Cloudflare DNS |
files.webpagetopdf.dev | 公开 R2 文件 | R2 Custom Domain |
support@webpagetopdf.dev 是邮箱地址,不是要创建的网页子域名。mail 和 files 则是实际的 DNS 子域名,不要把同一个子域名同时交给 Resend 和 R2。
绑定网站域名
先完成一次 npm run deploy:init,确认 workers.dev 地址能够正常打开。Saavo 的域名命令要求远程 Worker 和 .env.production 已经存在,不适合在首次部署之前运行。
在项目根目录执行:
npm run domain:set -- https://webpagetopdf.dev这条命令会完成四件事:
- 在
wrangler.jsonc中写入 Worker Custom Domain; - 把
.env.production中的VITE_SITE_URL改成正式地址; - 重新检查、构建和部署项目;
- 访问新域名进行健康检查。
Cloudflare 会为 Worker 创建所需的 DNS 记录并签发证书,不要提前给同一个 Hostname 手动创建 CNAME。该名称已经存在 CNAME 时,Custom Domain 会创建失败,应先确认旧记录是否还在使用,再决定是否删除。
命令执行成功后,再处理这些与正式域名有关的配置:
- 在 Turnstile Widget 的 Hostname Management 中加入
webpagetopdf.dev,并把真实密钥写入.env.production; - 如果启用了 GitHub 或 Google 登录,到对应平台更新 OAuth Callback URL;
- 如果启用了 Stripe,到 Stripe 更新 Webhook 地址;
- 检查站点名称、Canonical URL、Open Graph 和 Sitemap 是否已经使用正式域名。
domain:set 会在终端打印 OAuth Callback 和 Stripe Webhook 的新地址,但不会替你修改这些第三方平台,也不会更新 Resend 中的域名设置和 R2 自定义域。
处理 www 地址
建议只保留一个正式入口,例如统一使用 https://webpagetopdf.dev。Worker Custom Domain 精确匹配 Hostname,绑定根域名不会自动接管 www.webpagetopdf.dev。
如果希望用户输入 www 也能访问,可以在 Cloudflare 创建一条从 www.webpagetopdf.dev 到 https://webpagetopdf.dev 的 Redirect Rule,并保留原路径和查询参数。作为跳转来源的 www 还需要一条已代理的 DNS 记录。Cloudflare 官方的 Custom Domains 文档给出了无源站场景使用的占位地址。

不要让根域名和 www 同时返回完整页面。两个入口长期并存会增加 Cookie、OAuth 回调和搜索引擎规范地址不一致的可能性。
配置邮件接收
config/base.ts 中的 supportEmail 只是告诉 Saavo 在页面上显示哪个客服邮箱,并把哪个地址设为系统邮件的 Reply-To。填写 support@webpagetopdf.dev 不会自动创建邮箱,必须另外配置接收方式。
先根据实际用途选择方案:
| 需要解决的问题 | 合适的方案 | 建议 |
|---|---|---|
只想收到用户发给 support@... 的邮件 | Cloudflare Email Routing 转发到现有邮箱 | 最简单,适合大多数 Saavo 项目 |
| 需要独立收件箱、搜索、附件和多人管理 | 专业邮箱服务,或单独部署开源网页邮箱 | 不要只依靠邮件转发 |
| 需要大量临时地址、验证码收件箱或邮件 API | 基于 Workers 的临时邮箱项目 | 适合开发工具,不适合作为正式客服邮箱 |
将客服邮件转发到现有邮箱
Cloudflare Email Routing 不会提供新的收件箱。它收到发给 support@webpagetopdf.dev 的邮件后,会把邮件转发到你已经在使用的 Gmail、Outlook 或其它邮箱。
为域名启用 Email Routing
登录 Cloudflare Dashboard,打开 Compute → Email Service → Email Routing,点击 Onboard Domain,然后选择 webpagetopdf.dev。
Cloudflare 会为根域名添加接收邮件所需的 MX、SPF 和 DKIM 记录。确认页面中的域名无误后完成接入。DNS 记录通常几分钟内生效,少数情况下可能需要更长时间。
添加并验证实际接收邮件的邮箱
打开 Destination Addresses,在页面下方填写你平时真正使用的邮箱,然后点击 Add address。

Cloudflare 会向这个地址发送验证邮件,打开邮件并点击验证链接。Destination Address 属于整个 Cloudflare 账户,同一个已经验证的地址可以被多个域名重复使用。完成验证之前,指向它的转发规则不会生效。
创建 support 转发规则
回到 Email Routing,选择 webpagetopdf.dev,打开 Routing Rules,点击 Create routing rule。
按下面的方式填写:
| 设置项 | 填写内容 |
|---|---|
| Email pattern | support |
| Action | Send to an email |
| Destination | 刚才验证的实际邮箱 |
保存后,发给 support@webpagetopdf.dev 的邮件就会被转发到这个邮箱。除非确实需要接收任意地址的来信,否则不建议一开始就开启 Catch-all;公开域名的全域收件很容易带来大量垃圾邮件。
测试转发并修改 Saavo 配置
使用另一个邮箱向 support@webpagetopdf.dev 发送测试邮件。不要用 Destination Address 给自己发信,有些邮件服务会合并、隐藏或丢弃这种邮件,容易误以为转发失败。
确认能够收到邮件后,再修改 Saavo 配置:
supportEmail: 'support@webpagetopdf.dev',Cloudflare 官方的邮件路由操作说明会随控制台界面更新。如果页面入口与本文略有不同,以 Email Service → Email Routing 下的 Domain、Destination Addresses 和 Routing Rules 为准。
转发邮件不等于拥有完整邮箱
直接在个人邮箱中回复转发过来的邮件,收件人通常会看到你的个人邮箱地址。需要始终以 support@webpagetopdf.dev 收发邮件,或者需要“已发送”、草稿、搜索、团队协作等功能时,应使用完整的邮箱服务或自行部署网页邮箱。
不要让两项服务同时接管根域名的邮件
如果根域名已经在使用 Google Workspace、Microsoft 365、Spacemail 等邮箱服务,不要再启用 Cloudflare Email Routing 覆盖原有 MX 记录。先确定由哪项服务负责接收邮件,再使用它提供的 DNS 记录;重复添加两套 MX 记录不能实现稳定的双重接收。
使用 Worker 建立自己的收件箱
Email Routing 的转发目标除了现有邮箱,也可以是一个 Worker。
Worker 收到邮件后,可以解析正文和附件,将数据保存到 D1、Durable Objects 或 R2,再通过网页或 API 提供收件箱功能。

这类项目通常采用下面的结构:
外部邮件服务器
↓
Cloudflare Email Routing
↓
Email Worker
├─ D1 / Durable Objects:邮件、会话和邮箱信息
├─ R2:附件
└─ 网页界面或 API:阅读、搜索和管理邮件它们并不是运行在 Worker 中的传统 SMTP、IMAP 邮件服务器。收件入口仍由 Cloudflare 提供;向任意外部地址发送邮件,则需要下面的一种发送渠道:
- Cloudflare Email Sending:可以直接通过
send_emailBinding 发送,但向任意地址发送需要 Workers Paid 计划; - Resend:配置简单,也和 Saavo 当前的默认邮件发送方式一致;
- 其它 SMTP 或邮件 API:是否支持取决于具体开源项目。
自行保存邮件不一定比转发更可靠。Worker 超时、解析失败、D1 或 R2 配置错误同样可能导致收件失败;还要自己处理登录保护、附件安全、垃圾邮件、备份和数据保留。只有确实需要独立收件箱或邮件 API 时,才值得承担这部分维护工作。
可以实际部署的开源项目
下面只列出代码公开、许可证明确、近期仍在维护,并且确实以 Cloudflare Workers 为核心的项目。关注度是 2026 年 8 月查看 GitHub 时的近似值,只用于判断社区规模,不代表项目已经适合保存重要邮件。
| 项目 | 关注度 | 实际用途 | 需要注意 |
|---|---|---|---|
| cloudflare/agentic-inbox | 约 7k Stars | Cloudflare 官方的完整网页邮箱示例,支持收发、搜索、会话、附件和 AI 草拟回复 | 使用 Email Routing、Durable Objects、R2、Workers AI 和 Email Sending;生产环境必须配置 Cloudflare Access,所有通过同一 Access 策略的用户都能访问全部邮箱 |
| dreamhunter2333/cloudflare_temp_email | 约 11.5k Stars | 功能较完整的临时邮箱,支持多域名、附件、转发、API、管理后台和多种发送方式 | 定位仍然是临时邮箱;SMTP、IMAP 代理需要额外运行 Python 服务,并不是所有功能都只依赖 Cloudflare |
| oiov/vmail | 约 1.5k Stars | 较轻量的临时邮箱,支持多域名、D1 存储、REST API 和邮件发送 | 适合验证码收件箱或开发工具;发送需要另外选择 Cloudflare Email、Resend 或 MailChannels |
| G4brym/email-explorer | 约 150 Stars | 面向日常使用的自托管网页邮箱,支持用户、邮箱管理、收发、搜索和附件 | 社区规模较小;需要自己维护认证、数据备份、资源用量和版本升级 |
Saavo 项目应该怎么选?
普通产品只需要接收客服来信时,使用 Email Routing 转发就够了,系统邮件继续通过 Resend 发送。确实需要一个独立网页邮箱时,可以把 Agentic Inbox 或 Email Explorer 作为单独项目部署,不要直接塞进 Saavo 的主 Worker。临时邮箱项目更适合开发工具、验证码测试或邮件 API 产品,不适合存放正式客服往来。
选择邮件发送服务
接收邮件和发送邮件是两套配置。Email Routing 处理别人发给 support@webpagetopdf.dev 的邮件;邮件发送服务则由 Saavo 主动发送注册验证、密码重置和账户安全通知。
Saavo 当前支持 Resend 和 Cloudflare Email Sending,两种方式共用同一套业务代码,但部署条件不同:
| 发送方式 | 项目配置 | 部署前需要准备 | 更适合谁 |
|---|---|---|---|
| Resend | emailProvider.type: 'resend' | 验证发送域名,创建 RESEND_API_KEY | Saavo 默认方案;希望配置简单、使用独立邮件平台 |
| Cloudflare Email | emailProvider.type: 'cloudflare' | 开通 Workers Paid,将发送域名加入 Email Sending,并配置 EMAIL Binding | 已经使用 Workers Paid,希望把邮件也放在 Cloudflare 管理 |
Cloudflare Email Sending 目前仍是 Beta
Email Routing 可以在 Workers Free 和 Paid 计划中使用,但通过 Email Sending 向任意用户发送邮件需要 Workers Paid。服务配额和价格可能继续调整,决定使用前应查看 Cloudflare 的最新价格和当前账户页面显示的额度。
使用 Resend
Resend 是模板的默认选择。如果没有明确理由改用 Cloudflare,保留下面的配置即可:
emailProvider: {
type: 'resend',
},建议使用独立子域名,例如 mail.webpagetopdf.dev,发件人可以写成 send@mail.webpagetopdf.dev。首次部署时,deploy:init 会要求填写 RESEND_API_KEY。域名验证、API Key 和 Saavo 配置的完整操作见配置 Resend。
使用 Cloudflare Email Sending
Cloudflare Email Sending 不需要 RESEND_API_KEY,但必须先开通 Workers Paid,并把准备使用的发送域名加入 Email Service。下面以截图中的 email.webpagetopdf.dev 为例。
打开 Email Sending
登录 Cloudflare Dashboard,进入 Compute → Email Service → Email Sending。

页面右侧会显示当前周期的用量和发送额度。点击右上角的 Onboard Domain,开始添加发送域名。
选择发送域名
Zone 选择 webpagetopdf.dev。建议再使用一个专门发送邮件的子域名,例如 email.webpagetopdf.dev;如果不填写 Subdomain,则使用根域名发送。

后面的发件人地址必须属于这里添加的域名。截图中使用的是 email.webpagetopdf.dev,Saavo 的发件人就可以设置为 send@email.webpagetopdf.dev,不能继续使用属于其它发送域的地址。
确认后点击 Continue。
核对并添加 DNS 记录
Cloudflare 会列出准备添加的 MX 和 TXT 记录,分别用于退信处理、SPF、DKIM 和 DMARC。它们通常位于 cf-bounce、_domainkey 和 _dmarc 等专用名称下。

不要照抄本教程截图里的记录值。确认页面没有提示需要删除仍在使用的冲突记录后,点击 Activate,让 Cloudflare 自动写入当前域名需要的内容。
等待发送域名生效
返回 Email Sending 列表,等待域名状态显示为 Enabled,DNS records 显示为 Configured。Cloudflare 表示使用其 DNS 时通常会在几分钟内完成,少数情况下可能需要更长时间。
域名尚未启用时不要急着部署生产环境,否则 Worker 即使存在 EMAIL Binding,也会因为发件域名未获允许而发送失败。
修改 Saavo 的邮件配置
将邮件提供方改成 Cloudflare:
emailProvider: {
type: 'cloudflare',
},再把发件人改成刚才启用的发送域名。supportEmail 是用户回复邮件时使用的地址,可以继续使用已经配置好接收能力的 support@webpagetopdf.dev。
fromEmailAddress: {
name: 'Webpage to PDF',
email: 'send@email.webpagetopdf.dev',
},
supportEmail: 'support@webpagetopdf.dev',配置 EMAIL Binding 并部署
如果还没有执行首次部署,直接运行 npm run deploy:init。部署脚本会读取 emailProvider.type 和发件人地址,在 wrangler.jsonc 中生成限制了发件人的 send_email Binding,不会再询问 RESEND_API_KEY。
如果项目已经完成首次部署,后来才从 Resend 切换到 Cloudflare,需要先检查 wrangler.jsonc。当前没有 EMAIL Binding 时,手工添加:
"send_email": [
{
"name": "EMAIL",
"allowed_sender_addresses": [
"send@email.webpagetopdf.dev"
]
}
],send_email 是 wrangler.jsonc 的顶层配置,不要写成通用的 bindings: [{ type: 'email' }]。allowed_sender_addresses 还必须与 config/base.ts 中的 fromEmailAddress.email 完全一致。
配置完成后运行:
npm run doctor
npm run deploy:update发送一封真实测试邮件
在生产环境触发一次注册验证或密码重置,确认外部邮箱可以收到邮件,并检查发件人、Reply-To 和邮件内容是否正确。如果没有收到,先查看垃圾邮件,再到 Cloudflare Email Sending 的日志和 Suppressions 中检查发送结果。
只看到域名 Enabled 不能说明 Saavo 已经配置正确;发件域名、fromEmailAddress、EMAIL Binding 和实际部署版本必须同时一致。
Cloudflare 当前支持通过 Workers Binding、REST API 和 SMTP 使用 Email Sending。Saavo 使用的是 Workers Binding,详细规则见 Cloudflare 的发送邮件和配置发送绑定说明。
为 R2 绑定文件域名
Saavo 的普通上传通过 Worker 的 MAIN_R2 Binding 访问 Bucket,不配置文件域名也能使用 /uploaded/... 读取文件。只有业务明确需要返回独立的公开文件地址时,才绑定 R2 Custom Domain。
下面以 files.webpagetopdf.dev 为例:
- 在 Cloudflare Dashboard 打开 Storage & databases → R2 object storage。
- 选择
deploy:init为当前项目创建的 Bucket。 - 打开 Settings,找到 Custom Domains。
- 点击 Add 或 Connect Domain,填写
files.webpagetopdf.dev。 - 检查 Cloudflare 准备添加的 DNS 记录,确认后连接。
- 等状态从 Initializing 变成 Active。
- 上传一个可以公开的测试文件,通过新域名访问它。
R2 Bucket 与域名 Zone 必须位于同一个 Cloudflare 账户。不要手动创建指向 r2.dev 的 CNAME;Cloudflare 明确不支持把生产域名这样接到 R2。完整限制见 R2 Public buckets。
确认域名可以访问对象后,再修改 Saavo 配置:
upload: {
// ...
storage: {
// ...
r2: {
publicBaseUrl: 'https://files.webpagetopdf.dev',
},
},
},然后运行:
npm run deploy:updatepublicBaseUrl 只影响永久保存且需要绝对地址的 R2 上传结果。默认返回相对地址的头像、工单图片和通知配图仍然使用 /uploaded/...;带有效期的文件也必须经过 Worker。应用不需要生成 R2 公开地址时保持 false。
这个配置不会关闭 Cloudflare 上已经启用的公开访问。若要让 Bucket 真正不再公开,还要在 R2 设置中关闭 r2.dev 地址并移除已绑定的自定义域。
绑定 R2 域名会公开对象
Custom Domain 适合公开图片、下载文件和其他允许匿名访问的内容。私有文件不要因为配置方便就放到公开域名下,应继续通过鉴权接口或短时签名链接访问。
域名购买完成并不等于配置结束。网站、邮件接收、邮件发送和文件访问分别验证通过后,这个域名才算真正接入了项目。



