自建一个将邮件列表转换为 RSS 的服务
Matters 转载版本注:好久没有写文字了。最近刚好顺着不知道哪来的用 Next.js 重写博客系统的浪潮把个人博客站点重制了一下,又写了一篇给去年的总结文(不过太不正经了就不转载到这里)。虽说 Likecoin 的发展和 Matters 的壮大让人倍感欣慰,但感觉马特市还是太少生活气息。倒不是说内容质量或者数量不行——Matters 有很多写得很好的区块链技术文章、思辨文章、虚构故事或科幻故事,或是专业性和技术类文章等等。不过,也请各位作者记得,总是严肃着、紧绷着,生活会显得压抑而无趣哦。
再注:Matters 的编辑器连二级列表都不支持让我惊到了。
不图折腾的用户也可以直接去用 Kill the Newsletter! 搭建的服务。
最近用着 Miniflux 做 RSS 拉取/阅读器很愉快,于是希望将一些邮件列表转换为 RSS。如果收件箱里总是一堆订阅邮件的话,来自个人的通信邮件很容易淹没在其中,因此萌生了让它们成为 RSS 的想法。
现成的项目的话有 leafac 的 Kill the Newsletter!。这是一个用 JavaScript 写的单文件项目,也有搭建公共服务供不想 self-host 的用户使用。不过这个项目有几个不够我用的地方:
- 大部分的提交似乎都没有 commit message,对一个 repo 而言看起来不是很好的预兆。
- 不能自定义邮件别名。考虑到它的主要用例是公共(而非个人专用)服务,这个特点其实也容易理解:只要知道了邮件别名,就可以访问相应邮件地址收到的邮件。利用这个特性,知道邮件别名的其它用户可以控制相应邮件地址的订阅,甚至获取付费人的支付信息。
刚好最近 Pop 也写了个类似的东西。不同于 Kill the Newsletter!,这个项目的主要用例是给个人使用,所以对邮件别名没有特别的限制,只要收件人的域名对上,就会收录到 RSS 中,同时也提供网页端渲染的列表与显示。前段时间加上了 Basic Auth,所以也可以防止其它人随意访问。大多数 RSS 客户端应该也是支持 Basic Auth 的,所以对 RSS 客户端没有影响。
我则是基于这个项目进行了一些修改,添加了针对单个收件地址收取的邮件生成 RSS 的功能。
不过这都不是正题。本篇文章的主题是,在拿到一个可以接收明文 SMTP 协议的端口之后,如何把它优雅(?)地暴露到公网上。
配置 nginx 处理 SMTP
nginx 有一些处理邮件的模块。如果编译命令中使用了 --with-mail
,编译出来的 nginx 就会包含这些模块(可以通过 nginx -V
查看)。这些模块可以处理一些 IMAP/SMTP/POP3 协议上基本的认证流程,然后将请求交由相应的后端处理,也可以配置 SSL 和 STARTTLS。
Kill the Newsletter! 后端用的是 nodemailer
的 SMTP server,那个 server 可以配置 SSL/STARTTLS(虽说不知道相应的配置有没有暴露出来);但是 Pop 这个 mail-list-rss
利用了自己写的基础 Rust SMTP server 实现,其中不自带对 SSL/STARTTLS 的支持。因此我们需要使用像是 nginx 之类的服务来处理这个。
基本配置可以参考 nginx 文档中的例子:
mail { server_name mail.example.com; auth_http 127.0.0.1:8825; smtp_auth none; proxy_pass_error_message on; xclient off; starttls on; ssl_certificate /path/to/cert.cer; ssl_certificate_key /path/to/key.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ssl_session_cache shared:MozSSL:10m; ssl_session_timeout 10m; server { listen 25; protocol smtp; } }
mail
是 nginx.conf
配置的一级区块,所以不能放在 sites-enabled
。这里另外提及几点:
mail-list-rss
用到的实现中不支持XCLIENT
指令,记得把它关掉。server_name
和证书需要匹配。这个域名不一定要是邮箱接收邮件的域名,而应该是MX
记录结果中指向的域名。
考虑一封发给hi@example.com
的邮件,而example.com
的MX
记录指向smtp-01.example.com
,那么server_name
应该是smtp-01.example.com
,而 SSL 证书也应该是这个域名(而非example.com
)的证书。
- 读者可能会发现这里完全没有关于后端服务器的配置,这个我们马上讲。
关于 auth_http
上面没有提及怎么配置后端服务器,因为 nginx 需要另外的方法来动态指定后端,那就是 auth_http
。nginx 会给 auth_http
指定的服务发送关于此次请求的信息,包括用户名、密码、访问的协议、用户 IP 等,而服务返回的响应将会告诉 nginx 是将它引导到某个端点,还是拒绝此次访问。具体可以参见 ngx_mail_auth_http_module
的文档。这里由于我们的服务配置比较简单,并且 SMTP 服务也只用于接收而不是发送邮件,就不需要各种复杂的身份验证了,直接返回后端 SMTP 端点就好:
HTTP/1.0 200 OK Auth-Status: OK Auth-Server: smtp.mail-list-rss.local Auth-Port: 10000
于是写了个简单的 HTTP 服务器处理这个。 于是就让 nginx 来处理这个吧:
server { listen 127.0.0.1:8825; location / { add_header "Auth-Status" "OK"; add_header "Auth-Server" "smtp.mail-list-rss.local"; add_header "Auth-Port" "10000"; return 200; } }
最后...
记得 nginx -t
检查配置以及 nginx -s reload
重新加载配置。
本文为 Blog 上原文稍作修改后的版本。所有修改均以 Blog 原文为准。由于 IPFS 的不可变性,Matters 的副本无法更新。欲查看原文,请参见 Re:Linked。
本文以 CC BY-NC-ND 4.0 协议发布。
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐