TL;DR — paulkuo.tw 要做电子报时,我一开始只想知道:该自己架,还是直接用 Substack?跟 Claude 讨论一轮后,最后采用的是「半自建」:订阅名单和流程留在自己手上,寄信则交给 Resend。最近,我又在原来的架构上加了开信追踪。这次经验让我发现,半自建的好处不只是在当下省事,也让之后想加功能时,不必等平台替你决定。

「如果网站要有电子报,建议自建,还是用市场上现成的服务,例如 Substack?」

这是我问 Claude 的原话。当时 paulkuo.tw 已经有一套固定运作的网站后台,因此再加一份订阅名单,技术上并不困难,成本也很低。但「技术上不难」跟「该不该做、该怎么做」是两件事。我想先把架构想清楚,再决定要不要动手。

Substack 很方便,但不符合这次的条件

Substack 的优势很明确:它有自己的推荐网络,对刚开始经营电子报的人来说,可能更容易找到第一批读者。不过,若开始收费,它会抽取 10% 的订阅营收,另外还有金流费用;版面和读者互动,也会逐渐留在 Substack 的 app 与 Notes 系统里。

对很多人来说,这些交换可能很划算。但对 paulkuo.tw 而言,我更在意的是读者名单能不能留在自己手上,以及未来能不能自由调整网站和寄送流程。

如果网站、内容和域名都自己管理,唯独把订阅关系放在另一个平台上,整套架构就会留下明显的依赖。除非我很需要 Substack 带来的初期流量,否则这笔交换对我并不划算。

但跳过 Substack,不代表就该全部自己来。

半自建是什么意思?

全自建真正麻烦的,不只是把寄信代码写出来,而是如何让信稳定送进收件箱。寄件域名要验证(例如 SPF、DKIM、DMARC)、退信和垃圾信投诉要处理,寄送记录一旦不好,整批信都有可能被丢进垃圾桶。这些已经是专门的服务商长期处理的问题,自己从头搭,未必比较省事。

想成物流会比较清楚。全用现成服务像进驻百货专柜,什么都帮你打理好,但客人名单是百货的。全自建像自己盖一栋楼,连水电管线都自己拉,最自由也最累。半自建则是自己管客人名单和营运,但货要怎么送到客人手上,交给黑猫宅急便,不自己养车队。

半自建架构切分图:左侧自己握有订阅名单、表单与寄送判断逻辑,右侧外包 SPF/DKIM/DMARC 域名验证与退信投诉监控给 Resend。

具体切法:自己握订阅名单、订阅表单、和「有新文章就寄」的判断逻辑;外包出去的是把信真的送进对方信箱这件事。架构定调之后,问题缩小成一个:外包的寄送这一层,该找谁。

四个候选服务,我怎么一路删到剩 Resend

电子报寄送服务决策流程图:Substack 因抽成与名单去留问题淘汰,全自建因送达维护负担淘汰,半自建架构定调后比较四个候选服务,Cloudflare Email Service、Buttondown、AWS SES 依序淘汰,最终选定 Resend。

比较过程中列出四个候选者,各自的优缺点都摊开比较,不是拍脑袋选一个:

候选者优点缺点 / 顾虑结果
Cloudflare Email Service全 CF 生态原生、Workers 直接整合、每月含 3,000 封起2026 年才公测,目前只支持交易通知信,例如注册确认、订单通知,还不支持一次寄给大量订阅者的电子报一度是首选,查证后排除
AWS SES业界最便宜,这种量几乎免费寄送名单、退信和垃圾信投诉都要自己处理,后续维护工作最多保留到最后一轮比较
Buttondown最轻、markdown 友善,连名单管理都帮你做,免费层 100 订阅超过免费层约 9 美元一个月起,它连名单管理都包办了,虽然方便,但和我想把名单留在自己手上的方向不同半自建定调后淘汰
Resend现成 broadcast、退订 API,帮你扛退信和投诉管理,现成功能较完整,需要自己补的部分最少,免费层每月 3,000 封、每天 100 封早期印象是「订阅数一大就变贵」最终胜出

值得一提:Cloudflare Email Service 一度是最顺手的选择,全 CF 生态、Workers 原生,看起来天作之合。但写实作计划前先去查了官方文档,才发现它现阶段只收交易通知信,电子报这种一次寄给整个名单的寄送方式不在支持范围内。这也成了我这次跟 Claude 讨论时很有意思的一个转折。表面上最合适的选项,查过官方文档后反而第一个被排除。对我来说,Claude 在这里不只是帮忙列选项,更重要的是陪我把每个假设逐一查清楚,再重新调整方向。

最后一题:省寄信费,还是省维护时间?

最后只剩 Resend 和 AWS SES。两者的差别其实很直接:SES 的寄信费用更低,但许多电子报需要的功能都要自己补;Resend 费用稍高一些,不过群发、退订、退信与投诉处理已经准备得比较完整。

以个人网站目前的订阅量来看,两边的实际费用差异不大,真正有差的是我还要投入多少时间维护。最后我选择把时间留给写文章,因此用了 Resend。

定案之后还有两个追加决策,是半自建精神真正落地的地方。

第一个是订阅名单要放在哪里。一开始,我原本想直接使用 Resend 的名单管理功能,后来还是决定把数据留在自己的 Cloudflare D1,让 Resend 只负责寄信。这样即使未来更换寄送服务,订阅数据也不需要跟着搬家。

第二个决定和寄件地址有关。比较理想的做法,是另外使用一个子域名寄送电子报,把网站本身和电子报的寄送记录分开。不过,这需要升级付费方案。考量目前的规模,我最后先沿用已验证的主域名,使用 [email protected] 寄信。这不是最标准的架构,但在目前的成本和使用量之间,对我来说已经足够。

系统在 2026 年 6 月底上线。我从订阅、收确认信、点击确认到最后退订,完整走过一次流程。确认信有正常进入收件箱,数据库状态也会跟着更新,自动化测试全部通过。上线后,我的代码平台账号曾意外被停权,但网站和电子报仍正常运作。这也意外验证了:部署流程没有绑在单一平台上。这段经历值得另外写一篇,这里暂时略过。

寄出去之后,我开始想知道有没有人打开

系统稳定运作一段时间后,回头问了一个问题:这些订阅者到底有没有在看?一般电子报平台通常已经提供开信率,但在这套半自建架构里,我得自己决定要不要追踪、怎么保存,以及最后要把数据放在哪里看。好处是,名单和寄送记录都在自己手上,未来想怎么使用,不需要受限于平台现有的界面。

答案一开始是查不到。Resend 本身有开信、点击追踪的能力,但默认没开,开了之后也不会主动把事件反馈给你。

做法并不复杂。先开启 Resend 的追踪功能,再建立一个接收通知的网址。之后只要有人开信、点击链接,或信件发生退信、投诉,Resend 就会把事件送回我的系统。这种由服务主动通知另一个系统的方式,通常称为 webhook。

为了避免有人假冒 Resend 传数据,系统还会验证每次通知附带的数字签名。最后,我新增两张数据表:一张记录信寄给了谁,另一张记录信件后续发生的事件。整个机制不需要额外装包,浏览器和服务器都内建的加密函数库就能验证签名。

开信率查询机制流程图:Resend 触发开信事件,经 webhook POST 送出,Svix 签名验证通过后写回 Cloudflare D1 的两张新表,累积后即可查得开信率。

目前这个追踪管道已经上线,安全验证也测试完成。没有合法签名的请求,系统会直接拒绝。因为是刚接上的追踪,还没有累积到一次完整的开信事件,开信率目前诚实显示「尚无数据」,而不是造假的 0%。这个数据还没进来、但管道已经接好的诚实状态,本身就是半自建架构的具体证明:想加什么功能,随时可以加,不用等别人开放。

接下来,我还可以把这些数据放进自己的后台,也可以接到其他分析工具,甚至只在需要时通过 API 查询。目前我还没有急着决定,先让数据累积一段时间再说。

这套电子报系统上线后,我才慢慢看见下一个问题。先是寄得出去,接着是能不能退订,后来又想知道读者有没有打开。功能不是一开始就全部规划好的,而是在实际使用之后,一点一点长出来。

对我来说,这大概就是半自建最实际的好处:现在不用把所有事情都做完,但以后想往前走时,手上还留有调整的空间。