电子邮件架构分析
这篇文章是我对自建电子邮局(EMail)这一执念的一个句号,谨以此文,纪念过去我为这块领域投入的时间与精力。
我走了这么多弯路,是因为国内很难找到完整的资料,过去爬了许多的坑,后来 AI 出现了。
它们真的改变了知识体系,摸着石头过河的那段经历,全都是泡沫。而且 AI 太过于善解人意,毫无疑问它比我聪明。
存在即合理,电子邮件协议分层设计全都是有原因的。
引导
先上干货,如何快速部署一个收件服务,一个可以收邮件的东西很多时候就够了。
denghongcai/forsaken-mail: a self-hosted disposable mail service
这是一个 2015 年的基于 Node.js mailin 库实现的在线收件箱,稍加改造就可以让他保留附件、将邮件上传到数据库了。
开源邮局方案
在 github 上,有许多开源邮局方案,他们大多自称 full-featured solution 。
- postalserver/postal: 📮 A fully featured open source mail delivery platform for incoming & outgoing e-mail
- docker-mailserver/docker-mailserver: Production-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.
- Mailu/Mailu: Insular email distribution - mail server as Docker images
- iredmail/iRedMail: Full-featured, open source mail server solution for mainstream Linux/BSD distributions.
- zone-eu/wildduck: Opinionated email server
- Modoboa, Open Source email server
- Poste.io ~ complete mail server
- …
邮件架构和端口(误)
电子邮件是一整套解决方案,一个古典的分布式软件群
计算机科班的学生知道,SMTP 协议使用 25 端口来发送邮件,但是国内目前的教材大多没有继续深入电子邮件的方案。
我用自然语言来描述一下电子邮件的工作流程,大致三步:
- 用户打开邮件客户端,写邮件,提交
- 此时邮件客户端提交数据到服务端,服务端根据收件人地址,找到目标邮件服务器,转发数据到目标服务器的 25 端口
- 收件人在目标邮件的客户端查看邮件
从技术架构的角度上,我们展开讲讲:
从步骤 1 我们可以知道,就像市面上所有的电子邮件软件一样,用户需要有一个客户端,来构建邮件发送的请求,提交到 SMTP 服务器。
客户端和 SMTP 服务器中间大概率还有个中间层,来解决并发问题。
考虑到附件、图片之类的,我们可能还要根据 SMTP 协议的执行标准来做一些编码,或者用其他的方式(对象存储服务)
到了步骤 2 中,SMTP 服务器根据查询目标域名 DNS 的 MX 记录,找到 MX 记录指向的 IP 地址,向指定 IP 的 25 端口发起 SMTP 连接,提交邮件。
目前先这样,一笔带过吧。
邮件发不出去
如果你和我一样想要从底层开始写一个电子邮件系统,那么根据当前的业务场景,大概会这样拆解:
前后端分离:邮件前端 UI,邮件后端,呃,没了。
比如说我要发送邮件到 10000@qq.com,我直接查询 qq.com 的 MX 记录,然后对目标 IP 的 25 端口发起链接,直接网络编程。
设计完了以后发现不对劲,哎?查资料的时候,不是说还有什么 587,465 端口吗?还有什么 POP3 协议呢 ???
管他呢,先写个 demo 出来再说。
用现代软件高度框架化的设计思想去考量古典软件是需要商榷的。
遇到的第一个问题,是邮件发不出去了,通过 talnet 测试,发现根本连不通指定的邮件服务器。
这是因为绝大多数的 ISP 服务商,都默认禁止了指向 25 端口的出站(或者需要申请)。
当然了,你现在可能会开始寻找,不禁用 25 端口的 VPS 服务商,一方面来说,这的确可以解决问题,但是这不是主要的原因。
为什么呢?因为垃圾邮件。
随着标准的不断完善,SMTP 协议作为简单邮件传输协议,为了安全的解决邮件的收取和发送问题,25 端口如今仅被用于邮件服务器之间交换数据。
而用户作为客户端,是不建议(不允许)使用 25 端口的,根据 RFC 6409,应该使用 587 端口。
让我们引入电子邮件的关键点:IP 信誉
以点破面:IP 信誉
信誉问题,是电子邮件架构中的核心问题;了解了信誉问题,几乎就明白了现有的电子邮件架构的全部内容。
一切问题都将迎刃而解。
这段内容生成自 deepseek - r1
理论上,一个程序完全可以自己进行以下操作:
- 解析目标邮箱地址(如
user@example.com)的域名 (example.com)。 - 查询
example.com的 MX 记录,获取其邮件服务器的域名或 IP。 - 直接连接到该邮件服务器的 25 端口。
- 进行 SMTP 对话,将邮件提交给该目标邮件服务器。
那么,为什么现实中我们普遍使用中间 SMTP 服务器(通过 587 端口提交),而不是让每个应用程序直接去连接目标邮件服务器的 25 端口呢 ?
原因主要在于可靠性、安全性与合规性、运维复杂性以及现代反垃圾邮件机制。这种“越过步骤”的做法在实践中几乎无法成功,或者会带来巨大问题:
-
出站邮件端口 (25) 阻塞:
- 互联网服务商 (ISP) 的策略: 为了遏制垃圾邮件,几乎所有的居民区和普通商用互联网接入提供商都会在边界路由器或防火墙上默认阻止客户端的出站 25 端口连接。即使您的程序发送到 25 端口的数据包,也根本出不去您的本地网络。
- 云服务商策略: AWS, Azure, GCP 等主流云平台,默认情况下也阻止其虚拟机/容器的出站 25 端口连接。需要使用邮件投递服务 (如 Amazon SES, SendGrid) 或申请特殊解封(通常仅用于连接他们自己的邮件中继)。
- 移动网络: 移动网络同样普遍阻止出站 25 端口。
- 意义: 使用 587 端口的关键原因之一是它通常不会被ISP或网络策略阻止。ISP 信任你连接到自己的、经过身份验证的邮件服务器,而不是任意外部服务器。
-
身份与信誉 (Reputation):
-
源 IP 信誉:
邮件接收服务器(监听 25 端口的)会极度严格地检查发送方的 IP 地址信誉。普通的家庭宽带 IP、小型 VPS IP、新的云服务器 IP 通常:
- 不在已知邮件服务器 IP 范围。
- 没有良好的发信历史记录。
- 缺乏反向 DNS 记录(PTR 记录),或记录与发信域名不匹配。
- 可能被列入公开的垃圾邮件黑名单。
-
SPF/DKIM/DMARC: 为了让接收服务器信任您的邮件,需要正确配置 SPF(指定合法发信 IP)、DKIM(邮件内容签名)、DMARC(策略)记录。直接发信的服务器需要能通过接收方对这些记录的所有检查。
-
意义:
专业的 SMTP 服务器(如 Gmail SMTP, Office 365 SMTP, SendGrid, Mailgun)拥有:
- 固定的、高信誉的 IP 池,与知名的邮件服务关联。
- 完善的 SPF/DKIM/DMARC 配置。
- 专业的团队监控和维护发送信誉。
-
通过它们发送,您的邮件就继承了它们的信誉。直接发信,您的邮件几乎立即被标记为垃圾邮件或被拒绝。
-
-
可靠性与故障处理:
- 排队与重试: 专业的 SMTP 服务器具有强大的队列和重试机制。如果目标服务器临时不可用、繁忙或拒绝连接,中间服务器会将邮件暂存并在稍后多次尝试投递(可能持续数天)。
- 负载均衡与容灾: 它们通常有多个 MX 服务器和负载均衡器,保证高可用性。
- 退信处理: 能够接收、解析和处理来自目标服务器的错误信息(退信),并通知您。
- 意义: 您的程序直接发信,一旦遇到
EHLO被拒绝、连接超时、目标服务器临时故障、队列满等情况,邮件就立刻失败丢失了。您需要自己实现复杂、可靠的队列、重试、错误处理逻辑,运维成本极高。
-
安全性与认证:
- 端口 25 (MTA) 通常不需要发件人认证: 它主要用于服务器间传输。目标服务器只检查邮件是否符合协议、来源 IP 信誉、域名配置 (SPF/DKIM/DMARC)。
- 端口 587 (Submission) 强制要求认证: 它要求提交邮件的客户端(用户或程序)必须提供合法的用户名和密码(或 OAuth token 等) 来证明你是邮件服务的合法用户。这极大地减少了未授权滥用,使得它成为可信的提交通道。ISP 愿意开放此端口。
- 意义: 使用587端口 + 认证确保只有授权的程序/用户能通过这个邮件服务发信,保护了服务商的资源。
-
TLS 加密 (安全传输):
- 现代 587 端口普遍要求并支持 STARTTLS 加密。客户端(您的程序)和邮件服务器之间的传输是加密的,保护邮件内容和个人凭证。
- 而直接连接目标服务器的 25 端口,虽然也广泛支持 STARTTLS,但是否强制使用或正确协商成功取决于目标服务器。存在不加密传输邮件的风险。
-
简化客户端逻辑与运维:
- 使用 SMTP 服务器发信,客户端程序只需要关注:配置好 SMTP 服务器地址(smtp.gmail.com)、端口(587)、用户名、密码、加密方式(TLS/SSL),然后提交邮件内容。无需关心 DNS MX 查找、多服务器重试、IP 信誉、SPF/DKIM 签名(服务商通常代签)、退信处理等复杂问题。
- 意义: 大大降低应用程序开发和维护的复杂性。
总结:为什么通过 587 端口使用 SMTP 服务器发信?
- 突破网络限制: 绕开出站 25 端口被普遍封锁的问题。
- 建立信任与信誉: 利用专业服务商的良好 IP 信誉和完善的域名配置(SPF/DKIM/DMARC),确保邮件能被收件服务器接受并投入收件箱,而非垃圾箱或被拒收。
- 提供可靠性: 具备专业的邮件队列、重试、容灾机制,确保邮件最终送达。
- 强制安全性: 强制认证防止滥用,支持加密保护连接安全。
- 简化开发运维: 客户端只需实现简单的提交逻辑,无需处理邮件底层传输的复杂性。
直接连接到目标邮件服务器 25 端口发信:
在当今的互联网环境下,对于绝大多数场景(尤其是用户级的发信),这种方式:
- 网络层面可能被阻塞(你的包出不去)。
- 几乎肯定会被目标服务器拒绝或标记为垃圾邮件(IP 没信誉、无正确配置)。
- 缺失可靠性和容错能力(需要自己实现复杂的重试和错误处理)。
- 缺乏认证容易导致滥用(服务商不敢开放)。
- 运维成本极高(需要维护发信 IP 信誉、配置复杂的 DNS 记录等)。
因此,“越过步骤”直接发目标 25 端口虽然在协议上可行,但在现实的邮件生态系统中,这几乎是一条无法成功的死路(尤其对于需要高送达率的场景),或者是成本和风险极高的选择。 通过专业的 SMTP 服务器(通常是端口 587)提交邮件,是利用成熟的邮件基础设施和信任链的现实、可靠、高效的选择。这就是使用 SMTP 服务器(开放 587 端口)的意义所在。
在过去,程序员们设计了这样一套信任链,以解决邮件信誉的问题,从根源上杜绝了垃圾邮件。
SMTP & POP3 & IMAP
让我们将目光放回到 SMTP 协议的实现。
纵观前文中提到的开源项目,我们发现了许多关键词:Postfix、Dovecot
Postfix 和 Dovecot 是什么?为什么这么多邮件系统都用它们?
Postfix 和 Dovecot 是邮件服务器的核心组件,许多开源邮件系统都依赖它们,因为它们稳定、高效、安全且易于配置。
WTF ?MTA ?为什么不叫他 SMTP 服务器 ?
其实在整个电子邮件架构中,尤其是私有化的电子邮件架构中,这部分的概念模糊不清是可以接受的,不重要的。
对于用户来说,我只关心对方有没有收到邮件,对方是否可读我发的邮件。
所以站在现代的角度,不考虑公共的、多用户的读取本地收到的邮件的情况下,我们完全可以用现代软件架构来代替实现收件作业:在 25 端口接受 SMTP 会话。
要知道,SMTP 协议(1982)比 HTTP 协议(1991)还要古老,所以在不考虑兼容性的情况下,我认为这是确实可行的。
尤其是 self-hosted 且用户只有自己的情况下。
代价是重新发明轮子
MTA Mail Transfer Agent,其代表就是 Postfix,主要负责邮件的路由与转发,支持通过 SMTP 接受外部邮件;
MDA Mail Delivery Agent,代表就是 Dovecot,Dovecot 专注于邮件的存储,以及远程访问(通过 IMAP / POP3 协议);
因此,Postfix + Dovecot 是目前主流的邮件解决方案,他们两者合一组成了一个基本的邮件服务器。
对于 Postfix 和 Dovecot 的工作原理,不在本文的讨论范围内。
碎碎念:为什么需要自建一个电子邮局 ?
自建电子邮局的想法,源于我对账号底座体系的思考,当时我正深受开源社区中去中心化和匿名化思想的感染。
在国内,Email 的应用场景远不如海外广泛。这很大程度上源于即时通信的普及取代了其核心位置,使其应用范围大幅萎缩,具体原因暂不作深究。
另一方面,互联网实名制的推进,进一步固化了以手机号码为核心的账号体系。
而在海外,Email 扮演着截然不同的角色:它仍是账号注册流程中最关键的身份验证手段。
即便是在双重验证(2FA)时代,也是其中不可或缺的重要组成部分,电子邮件天生满足 2FA 。
如今,互联网已经深入我们的生活,账号资产作为个人资产的一部分,其重要性也日益增加。
我注意到,账号资产所依赖的,数字身份的所有权与控制权问题。
这是一种信任问题,作为数字资产的根,数字身份的一种:手机号码 or 电子邮件,被托管在第三方,有时令人感到生理性的厌恶。
这种托管的状态,从根本上存在一种不稳定性,用户的个人权利实际上基于信任体系绑定在服务商上,不拥有最终的解释权和控制权。
其功能支持,服务范围的变化以及终止,尤其是政治审查,会破坏身份的可用性。
这种场景出现的根本原因,是用户群体对中心化的公共服务的不满,出于现实的原因,用户作为个体在企业甚至是某些官方势力面前,力量过于渺小,以至于无法保证公平,因为一个规则体系没有相匹配的力量去维护是十分脆弱的,那么去中心化社群的诞生,其实是对现状的一种反抗与制衡;有些人无法理解这样的行为,反过来看,如果社会的个体与个体之间、群体与群体之间的沟通完全透明、公开、公正、公平,那么在这样的社会群体上建立的信任机制在基本的良好运作下一定是坚固的,没有人会质疑规则的合理性和有效性。这种质疑的产生,正是由于人类社会不是一个超个体,人心隔肚皮。另外,出于本能,人类也不可能完全的放弃个体权利而完全服务于群体。因此,信任问题一直存在,永不完结。
作为一个程序员,数字资产对我的重要性不言而喻,因此实现数字身份所有权和控制权的回归,至关重要。
基于现有的账号底座体系,手机号码显然是因特殊原因不可抗力所无法动摇的,但是在邮件上,我们可以做一些文章。
自建电子邮局的场景,用户拥有域名,拥有服务器,根本上解决了数字身份的所有权问题。
抛开数字资产的问题,许多企业都有自建邮件服务,这是出于商业行为考量下的决策,围绕域名建立商业信用是顺水推舟的品牌工作。
对于自建邮局的优势,总结如下:
- 数字身份的主权回归: 电子邮件可以作为锚点 / 根来建立数字资产
- 去中心化实践: 规避服务商的风控策略、政治审查以及服务不可用,技术层面的价值回归
- 匿名化、隐私和安全: 自建邮局是白箱,完全归你所有,归你处理
- 品牌意识和定制化