我曾在这个博客上开通过电子报,但很长一段时间都没发过邮件。这篇文章讲述了我最终如何重新启动电子报,以及我在此过程中学到了什么。
Tinyletter 的岁月

来源:互联网档案馆
多年来,我的设置很简单,就是在网站上放一个指向Tinyletter 的小型邮件订阅服务表单。Tinyletter 是一款专注于作家的邮件订阅服务。我喜欢它的简洁性。我从不用考虑邮件送达率、退信率、屏蔽列表、SPF、DKIM、DMARC 等等。我写完内容,点击发送,人们就能收到。

它之前一直运行正常。然后Tinyletter就崩溃了。
一点历史背景:Tinyletter 由Philip Kaplan于 2010 年创建,据说是在 2010 年 10 月 31 日星期日当天编写的。
一年后,它被 Mailchimp 收购,并悄然成为那些想要创建个人新闻简报而无需考虑销售漏斗、细分或 A/B 测试的作者们的实际首选平台。
随后在2023年末,Mailchimp(现已并入Intuit)宣布关闭该服务。官方说法是,他们的“业务重点发生了变化”,并且“将专注于开发服务于营销人员和帮助小型企业发展的工具”。作家从来都不是他们的核心客户。

来源: EmailOctopus
在 Tinyletter 于 2024 年 2 月 29 日停止服务之前,我做了订阅者列表的最终备份,但我当时并不知道该如何处理它。
拒绝
这时,我对使用第三方服务的想法产生了抵触情绪。同样的事情可能会再次发生。
我仍然考虑了所有选项,但都放弃了:
- 太贵了!大多数服务按联系次数收费,而且假定你是在运营一个商业销售漏斗,而不是给个人写信。
- 太注重营销了!模板、拖放式编辑器、A/B 测试、互动评分、追踪像素。所有术语都用错了。我不想做营销活动;我只想发邮件!
- 对黑客不友好。没有 Markdown,没有命令行界面,也没有我真正想用的 API。所有操作都在一个为市场团队设计的网页控制面板中完成。
- 非开源软件。如果 Tinyletter 下一个项目关闭,我希望能够继续使用,而无需再次迁移。
- 默认开启追踪!打开追踪、点击追踪,每个页脚都包含像素追踪。我不想知道谁打开了什么。我只想写点东西,你读(或者不读),就完事了。
迁移到 Fly.io
一直有人问我电子报什么时候恢复,所以我用fly.io拼凑了一个简易版。它包含一个小型 Rust API、一个存储订阅者信息的 CSV 文件,以及一个通过网站订阅的功能。我的想法是先解决发送问题,现在至少提供一个注册途径。
然后,那份清单就一直放在那里。
事实证明,冷邮件列表本身就是个问题。当你最终向一个很久没收到你邮件的名单发送邮件时,邮件服务商会起疑心,你的邮件可能会被标记为垃圾邮件。突然之间,你自己的邮件列表就可能变成你的绊脚石。
寻找发送服务
这绝对是最难的部分。我研究了Resend 、 Postmark 、 SendGrid 、 Mailgun 、 Amazon SES等等。它们要么对小型邮件订阅来说太贵,要么 API 体验很差,要么不符合 GDPR 规定,要么就是太复杂。
我几乎要放弃了,直到我发现了Plunk 。它是开源的,价格会根据你的邮件列表规模而变化,而且 API 用起来很顺手。它帮我搞定了那些我不想操心的邮件送达率优化工作(比如SES 集成、退信处理、屏蔽列表、托管退订页面等等)。我现在是付费用户了。我跟他们没有任何利益关系,只是一个真心喜欢它的用户。
我甚至还给他们捐了一小笔钱,他们十分钟就合并了。这让我感觉自己真的成为了社区的一份子。
第一期正式的电子报发送给了一千多位很久没收到我消息的联系人。我原本担心会收到大量退订,但结果很顺利。退订率在1%左右,只有极少数人取消订阅,而且没有出现任何送达问题。哇!

来源: Plunk
这里感觉就像家一样!
我意识到我可以把问题写成纯 Markdown 文件,放在一个文件夹里,进行版本控制,再用一个简单的命令行工具处理其他所有事情。这样我感觉很自在。只有我、一杯热巧克力、我的编辑器、终端和 Git。我和写作之间再也没有网页控制面板的阻隔了。
所有内容都存放在同一个代码仓库中:
newsletter/ ├── issues/ # one .md per edition (1.md, 2.md, ...) ├── send/ # the CLI I run locally └── subscribe/ # tiny HTTP service behind the website signup form
该命令行界面 (CLI) 名为send 。以下是它的功能:
$ send help Usage: send < COMMAN D > Commands: new Create a new issue file and open $ EDITOR list List local issues lint Check links in an issue (or all issues ) test Send a test email to myself publish Publish the issue to all subscribed contacts status Show contact-list and deliverability report prune Delete unsubscribed contacts
send publish 2会显示预览、收件人数量以及y/N提示,然后再实际执行任何操作。 send status会显示每个营销活动的送达率,跳出率单元格会根据 SES 阈值进行颜色编码,此外还会显示每日跳出率和退订率,以便我能及早发现问题。
网站上的注册表单会向运行在我服务器上的小型subscribe服务发送 POST 请求。该服务会验证电子邮件地址并将其转发给 Plunk。无需 JavaScript。Plunk 会发送一封交易确认邮件(用于双重验证)。
我推送代码到 Git, Nixpacks检测到 Rust crate,构建它,新版本就上线了。运行中的服务完全不占用 CPU 或内存。
一个小插曲
我忘了From:地址必须是真实存在的邮箱才能正常回复邮件。第一期邮件发到了[email protected]这个邮箱地址,但这个邮箱并不存在。一位热心的读者(嘿,凯文!)回复邮件打招呼,结果邮件被退回了,他把退信通知转发给了我。我修复了这个问题,现在这个别名已经存在,回复邮件也能正常使用了。
一份清单,而非两份
趁此机会,我还把之前的 endler.dev 和corrode.dev 的邮件列表合并成了一个。这两个邮件列表都是我写的,同时运行两个实在没必要。同一个人在敲键盘,受众群体也基本重合,维护成本却翻了一倍。以后就只有一个邮件列表了。如果您觉得这些合并不适合您,随时可以取消订阅,以后就不会再收到我的邮件了。我不会介意的。
我会告诉你
如果你一直想自己动手,那就去做吧。自托管真的比以前容易多了。现在几乎所有功能都有很棒的开源服务。总的来说,自己动手构建一些小东西是真正理解它们并掌控关键部分的最佳方法之一。这本身就是一个值得单独写一篇博文的话题,如果你想让我写,请告诉我。
如果你想看看这个(有点简陋的)代码库,可以给我发邮件,我会把链接发给你。其实它没什么特别的,但如果你好奇它是怎么工作的,我很乐意分享。或者你可以等等,等我把它整理好并正式开源之后再看,不过这可能还需要几年时间。
最棒的是,您现在可以通过填写下面的表格并订阅新闻简报来测试我的设置!