现代电子邮件可通过借用现有组件来构建
摘要
这篇文章提出了一个名为HMTP的现代电子邮件协议,基于HTTP构建,用WebFinger、ActivityPub和HPKE等现有技术替代SMTP组件,以修复设计缺陷。
暂无内容
查看缓存全文
缓存时间: 2026/07/27 13:44
# 现代邮件可用借来的部件构建 | Andros Fenollosa 来源:https://en.andros.dev/blog/d7ed8b07/modern-email-can-be-built-from-borrowed-parts/ 让我们在 HTTP 之上设计邮件的继任者,修复 SMTP 四十年来拖累的诸多设计缺陷。一点一点来。目标不是取代现有邮件系统(千万不要!),而是学习、娱乐并发现当前技术,用以替换每一个元素:发送、接收、网关、密钥等。该系统永远不会与 Gmail 或任何传统邮件提供商通信:它只与自己通信。我们唯一保留的是地址格式 `user@domain`。其他一切都要重新发明。由于这是一个基于 HTTP 的邮件系统,协议的好名字是 HMTP:超文本邮件传输协议(SMTP 中代表 *Simple* 的 S 让位给了 HTTP 的 H)。现在准备技术栈:HTTP、TLS、WebFinger、ActivityPub、Webmention、Ed25519、HPKE、sigchains 等。
## 所需组件清单
本设计不发明任何单一技术:一切均已存在。
| 问题 | 现有技术 | 谁在用 |
|------|---------|--------|
| 传输与状态码 | HTTP | 整个互联网 |
| 传输加密 | TLS + Let's Encrypt | 整个互联网 |
| 用户发现 | WebFinger (RFC 7033) | Mastodon 与联邦宇宙 |
| 消息投递 | POST 到 inbox | ActivityPub |
| 发送方源头验证 | Webmention 与 DKIM 模式 | IndieWeb,所有邮件 |
| 签名 | Ed25519 | SSH、Signal |
| 内容加密 | HPKE (RFC 9180) | MLS、TLS ECH |
| 支持密钥轮换的身份 | Sigchains | ATProto (Bluesky)、Keybase |
| 阅读与同步 | JMAP (RFC 8620) | Fastmail |
| 推送通知 | SSE / WebPush | 每个浏览器 |
| 首次联系同意 | 消息请求 | Signal、Instagram |
| 带哈希引用的附件 | 内容寻址 | Git、IPFS、Matrix |
我们所用的每一块都经过了标准化、部署和百万级实战检验;唯一的新东西是组装方式。
选择 HTTP 不仅仅出于实用主义。它能从一开始就解决任何新协议迟早要构建的几个问题:
- **TLS、虚拟主机和 SNI**:免费获得。
- **状态码**:邮件协议所需的状态码目录已存在于 HTTP 中。`202 Accepted`(排队投递)、`429 Too Many Requests` + `Retry-After`(速率控制)、`404`/`410`(邮箱不存在/已消失)、`3xx`(邮箱已迁移)、`413`(太大)。甚至付费反垃圾邮件自1997年起就有保留状态码:`402 Payment Required`。
- **现有基础设施**:代理、负载均衡器、Nginx、各种语言的库。该协议不再是新服务器,而是变成基于 HTTP 的*约定*,如 Webmention 或 Micropub。
让我们进入下一层:如何发现用户、验证其身份、投递消息、签名和加密,全都在 HTTP 之上进行?
## 1. 发现与委派(更好的 MX)
委派通过静态文档解决:
```
GET https://example.com/.well-known/hmtp/ana
```
```json
{
"inbox": "https://mail.migadu.example/hmtp/inbox/ana",
"keys": { ... },
"devices": [ ... ]
}
```
`inbox` 可以位于另一台主机上:这**就是** MX 记录,但无需修改 DNS。GitHub Pages 上的静态博客可以通过提供 JSON 文件将其邮件委派给提供商。它还允许 MX 从未做到的事情:*按用户*委派(一个域名的每个邮箱可由不同提供商托管)。我们甚至不需要发明这条路:WebFinger (RFC 7033) 做到了这一点,而 Mastodon 已经证明它可以规模化。
## 2. 支持密钥轮换的身份
身份不能*是*一个密钥(密钥会丢失、过期);它必须是密钥可以*背书*的东西。一个包含两个锚点的方案:
- **加密延续性**:发现文档发布当前密钥和一个轮换链,其中每个新密钥由前一个密钥签名。任何在密钥 N 认识你的人都可以验证密钥 N+1,无需信任任何人。这就是 sigchain,ATProto 用 DID 做的那种,或者 Keybase 以前的做法。
- **域名控制作为后备方案**:如果你丢失了密钥但没有签名的轮换(比如笔记本电脑被盗),域名声明一个新密钥,无需链条,但附带一个强制公告期(比如30天),在此期间认识你的服务器会显示警告“身份由域名重新锚定,而非签名”。
然而,域名锚定的身份有其致命弱点:域名不是拥有的,而是租用的。如果你停止付费,域名过期并被他人注册,新所有者会在你的 `/.well-known` 中发布他们的密钥,从那时起他们就能接收你的邮件并冒充你签名。没有人能区分合法继承人和抢注者。这是 ATProto 试图通过用 DID 将身份与域名分离来解决的问题,代价是需要另一套基础设施。我们知道这是一个真实问题,且有已知解决方案。现在继续。
## 3. 带队列的投递(存储转发)
投递是通过 POST 到收件人的 inbox:
```
POST /hmtp/inbox/ana HTTP/1.1
Host: mail.migadu.example
Content-Type: application/hmtp+json
```
关键不在于请求本身,而在于*谁*发出请求。你的客户端不会直接投递到收件人,而是投递到**你自己的服务器**(一个经过身份验证的 POST 到你的 outbox),然后由你的服务器进行排队、带指数退避的重试以及遵循 `Retry-After`。这承认了 SMTP 的 MUA/MSA/MTA 分离是正确的。邮件系统的一个低调天才之处在于:如果目标服务器宕机,你的服务器会重试多天,而你完全不用操心。
但让我们增加一个 SMTP 从未有过的改进。每条消息都携带一个 ID,即其内容的哈希值,因此重试是幂等的。接收服务器根据 ID 去重,而经典的“由于 ACK 失败导致的重复邮件”问题就此消除。
以下是投递完整周期,第一次尝试时目标节点宕机的情况:
```mermaid
sequenceDiagram
autonumber
participant Ana as Ana 的客户端
participant SA as Ana 的服务器
participant SB as Bob 的服务器
Ana->>SA: POST /outbox (签名消息)
SA-->>Ana: 202 已排队
SA->>SB: GET /.well-known/hmtp/bob
SB-->>SA: Bob 的 inbox 和密钥
SA->>SB: POST /hmtp/inbox/bob (信封 + 密封的正文)
Note over SB: 宕机:无响应
Note over SA: 排队:带指数退避重试
SA->>SB: POST /hmtp/inbox/bob (重试,相同 id)
SB->>SA: GET /.well-known/hmtp/ana
SA-->>SB: Ana 的签名密钥
Note over SB: 签名已验证,按 id 去重
SB-->>SA: 201 已投递
```
注意,图中包含了整个协议:两个对 `/.well-known` 的 GET 是发现和验证,POST 是投递,队列位于它应在的位置——发送方的服务器上。
## 4. 使用已有密钥进行签名和加密
消息是一个签名对象,而不是松散文本:
```json
{
"id": "sha256:9f2c...",
"from": "[email protected]",
"to": ["[email protected]"],
"date": "2026-07-26T10:00:00Z",
"in_reply_to": "sha256:11ab...",
"subject": "Re: that idea",
"body": {
"type": "text/markdown",
"content": ""
},
"signature": "..."
}
```
这为我们带来了很多好处:
- **静态真实性**:存储的邮件携带其加密证明。转发会保留原始签名。即使通过转发链,伪造发件人也不可能。
- **无需 DKIM 的发件人验证**:接收服务器 GET `from` 域名的 `/.well-known`,并检查密钥是否签名。这与 Webmention 验证相同。证明来源于源头获取。
- **端到端加密**:发现文档发布加密密钥(X25519);正文使用 HPKE 密封。信封(from、to、id、date)保持可见以便路由和过滤;内容仅收件人可见。
- **线程**:通过内容哈希的 `in_reply_to` 和 `references`。无需启发式算法即可重建对话。
- **附件**:在消息外部。附件是 `{hash, url, size}`,指向发件人的服务器;收件人按需下载,其服务器可以镜像附件。不再有 base64 撑爆邮箱。
## 5. 分层反垃圾邮件
与任何系统一样,这是一个复杂问题,需要多层防御。使用 HMTP,我们可以从三个层面开始:
1. **身份成本**:以 `[email protected]` 身份签名需要在 `example.com` 提供密钥文档。身份锚定于域名,而域名需要花钱。这是自签名身份所没有的 Sybil 成本。然而,一个域名可以给你无限子域名和邮箱,所以成本减缓的是*独立*身份的大规模创建,而非地址数量。我们在根层级工作。
2. **首次联系同意**:未知发件人不会进入邮箱;他们会进入“请求”文件夹,第一条消息可见(类似 Signal 的消息请求)。你接受后,线程永久开放。陌生人可以*敲你的门*,这是邮件的基本属性,但他们不能塞满你的客厅。
3. **可选的陌生人邮资**:服务器可以用 `402` 响应首次联系。每个邮箱可配置;冷垃圾邮件的成本不再为零。
## 6. 阅读也得到规范
电子邮件将发送(SMTP)和阅读(IMAP/POP)标准化为两个独立的世界。我们不需要发明任何东西:通过 JSON/HTTP 阅读、同步和搜索邮箱已经由 IETF 解决并标准化。它叫做 JMAP。HMTP 将定义投递;阅读是 JMAP 加上一种新对象类型。通过 SSE 或 WebPush 推送到客户端。整个周期(发送、投递、阅读、同步)保持在 HTTP 上。
## 结论
电子邮件的每一个问题都有已部署且运转中的解决方案:Mastodon 中的发现、ActivityPub 中的投递、IndieWeb 中的验证、Bluesky 中的可轮换身份、Fastmail 中的阅读、Signal 中的同意。电子邮件的升级已经存在,但没人将其组装起来。我们用优雅、现代的解决方案解决许多问题:
- **信誉与社交许可**(SPF、DKIM、DMARC、反向 PTR、黑名单、IP 预热数月):被每条消息的加密验证取代——一次签名,一次对发件人 `/.well-known` 的 GET。一个可验证的属性不需要信誉。
- **发件人伪造**:从根本上不可能。接收方根据 `from` 域名上发布的密钥检查签名,且签名随消息一起传输(即使转发)。
- **邮件委派**(MX 记录):`/.well-known` 中的一个静态文档,支持按用户委派,无需修改 DNS。
- **内容隐私**(没人去配置的 PGP):默认端到端加密;接收服务器存储一个它无法阅读的正文。
- **垃圾邮件**(事后统计过滤器):首次联系同意(陌生人敲门,不走入邮箱)、锚定于域名的昂贵身份、以及可选的 `402` 邮资。
- **重试带来的重复**:消息 id 是内容的哈希,因此重试是幂等的,接收方从根本上实现去重。
- **靠启发式算法重建线程**:`in_reply_to` 指向父消息的哈希;对话是一个可验证的图。
- **轻量邮箱**:附件按引用(哈希 + URL),按需下载。
- **简单、熟悉的基础设施**:一切通过标准 HTTPS 传输,后面是相同的 Nginx 和相同的证书,它们已经服务于你的网站。
- **密钥轮换**(DKIM 的操作噩梦):一条命令。由于没人固定你的密钥,新密钥立即受信任,被盗的密钥也快速失效。
空谈无益,因此我用 Python 实现了一个工作原型:github.com/tanrax/hmtp (https://github.com/tanrax/hmtp)。全部在一个文件里。该原型覆盖了完整传输:签名投递、源头验证、端到端加密、首次联系同意、去重、线程、带指数退避的队列以及一键密钥轮换。它有意省略了外围部分:签名轮换链(接收方每次投递时实时获取你的密钥,而非固定它,因此链只在节点缓存密钥时才发挥作用)、`402` 邮资、按引用附件和 JMAP 阅读。README 里有快速入门(两分钟内发送你的第一条消息,发给自己)、在你的机器上两个节点交换加密邮件的演示,以及完整的生产指南,从 DNS 到 systemd。请记住,这是一个设计实验,密码学未经审计;不要用于任何重要秘密依赖的场景。不过,它可以成为你所想到的任何生态系统的轻量级通信系统。
希望你喜欢这段旅程。如果你发送了你的第一条 HMTP 消息,我很乐意听到。
相似文章
电子邮件加密
本文追溯了电子邮件从其去中心化、基于信任的起源到现代安全问题的历史,解释了SMTP和MIME等协议是如何作为技术限制的变通方案而出现的,但这使电子邮件容易受到窃听和篡改。
本可以是X.400倍更好的电子邮件
一篇回顾文章指出,基于OSI的X.400电子邮件标准提供了比SMTP更丰富的功能——加密、日程安排、已读回执、多语言文本——却因为SMTP更易于实现而败下阵来。
OpenSMTPD 是未来的邮件服务器
Peter N. M. Hansteen 描述了他转向 OpenSMTPD 的过程,因为 OpenBSD 7.9 放弃了 exim,他认为 OpenSMTPD 是 21 世纪的邮件服务器。
电子邮件的未来
Fastmail探讨了AI驱动的邮件过滤和助手如何使邮件认证标准(SPF、DKIM、DMARC)成为防止伪造和网络钓鱼的关键基础设施。
Show HN: Posthorn,无需邮件服务器的自托管邮件系统
Posthorn 是一个自托管的出站邮件网关,通过统一接口整合多个应用的邮件发送,支持 HTTP 和 SMTP 接收,并支持多种提供商传输。