RFC 6409 – 邮件消息提交
ELI5: 想象一下在街道上的公共邮箱投递信件和把信件交给邮局柜台职员的区别。街道邮箱(端口25)是邮递员在邮局之间转运邮件的地方。柜台(端口587)是你作为客户提交信件的地方——你先出示身份证,职员检查一切是否妥当。RFC 6409为电子邮件定义了邮局柜台。
RFC 存在的原因
在电子邮件的早期,用户发送新消息和服务器中继来自另一台服务器的邮件之间没有区别。两者都使用端口 25,任何人都可以连接并发送。这导致了开放中继问题——垃圾邮件发送者利用任何会接受和转发邮件而不进行身份验证的服务器。
RFC 6409(最初是 1998 年的 RFC 2476,2006 年更新为 RFC 4409,2011 年最终确定为 6409)正式区分了消息提交和消息中继:
- 提交(端口 587):经过身份验证的用户或应用程序向其邮件服务提交新消息以进行传递。服务器充当 MSA(RFC 5598)。
- 中继(端口 25):邮件服务器将消息传输到另一台邮件服务器,途中前往目的地。服务器充当 MTA。
这种分离是现代电子邮件安全的基础。它支持发件人身份验证、策略执行以及阻止未经身份验证的中继同时仍然接受合法提交的能力。
工作原理
消息提交使用 RFC 5321 中定义的相同 SMTP 协议,但在行为、策略和端口号上有重要区别。
提交过程
- 客户端(MUA 或应用程序)连接到端口 587上的 MSA。
- 客户端发出
EHLO并发现可用扩展。 - 客户端使用
STARTTLS升级到 TLS(或根据 RFC 8314 通过端口 465 上的隐式 TLS 连接)。 - 客户端使用
AUTH(RFC 4954)进行身份验证——通常在 TLS 上使用 PLAIN 或 LOGIN。 - 客户端使用
MAIL FROM、RCPT TO和DATA提交消息。 - MSA 验证消息,可能添加缺失的标头(Date、Message-ID),并将其排队以通过 MTA 基础设施进行传递。
提交与中继:并排比较
| 方面 | 提交(MSA,端口 587) | 中继(MTA,端口 25) |
|---|---|---|
| 目的 | 接受来自用户/应用的新消息 | 在服务器之间转移消息 |
| 身份验证 | 必需(SMTP AUTH) | 不需要(服务器间信任) |
| 加密 | 必需(STARTTLS 或隐式 TLS) | 机会性(可用时使用 STARTTLS) |
| 发件人验证 | MSA 检查经过身份验证的用户是否有权使用 From 地址 | MTA 检查 SPF、DKIM、DMARC |
| 标头修复 | MSA 可能添加缺失的 Date、Message-ID 和 MIME 标头 | MTA 仅添加 Received 标头 |
| 谁连接 | 最终用户、应用程序、电子邮件服务 | 其他邮件服务器 |
SMTP 示例
端口 587 上的典型提交会话:
# 客户端连接到端口 587
S: 220 smtp.mailertogo.com ESMTP Submission
C: EHLO app.example.com
S: 250-smtp.mailertogo.com
S: 250-STARTTLS
S: 250-AUTH PLAIN LOGIN
S: 250-SIZE 26214400
S: 250-8BITMIME
S: 250 ENHANCEDSTATUSCODES
# 先升级到 TLS
C: STARTTLS
S: 220 2.0.0 Ready to start TLS
# TLS 握手在此发生,然后重新 EHLO
C: EHLO app.example.com
S: 250-smtp.mailertogo.com
S: 250-AUTH PLAIN LOGIN
S: 250-SIZE 26214400
S: 250-8BITMIME
S: 250 ENHANCEDSTATUSCODES
# 身份验证(Base64 编码的凭据)
C: AUTH PLAIN AGFsaWNlQGV4YW1wbGUuY29tAHNlY3JldA==
S: 235 2.7.0 Authentication successful
# 现在提交消息
C: MAIL FROM:<notifications@example.com>
S: 250 2.1.0 OK
C: RCPT TO:<user@recipient.com>
S: 250 2.1.5 OK
C: DATA
S: 354 Start mail input
C: From: Example App <notifications@example.com>
C: To: user@recipient.com
C: Subject: Your order has shipped
C: Date: Wed, 11 Mar 2026 14:00:00 +0000
C: Message-ID: <order-12345@example.com>
C:
C: Your order #12345 has been shipped and is on its way.
C: .
S: 250 2.0.0 OK, queued as abc123
C: QUIT
S: 221 2.0.0 Bye
关键技术细节
身份验证是必需的
RFC 6409 规定 MSA 应该要求身份验证,并且不能接受来自未经身份验证的客户端的中继消息,除非有特定的组织策略允许。在实践中,每个现代提交服务器都需要身份验证。标准机制是 SMTP AUTH(RFC 4954),使用 PLAIN 或 LOGIN 机制,始终通过 TLS。
MSA 的标头修复
与 MTA(不能改变消息内容)不同,MSA 应该检查和修复提交的消息:
- 添加缺失的 Date 标头(如果客户端未包含)。
- 添加缺失的 Message-ID 以确保每条消息都有唯一标识符。
-
验证 From 地址与经过身份验证的身份匹配,或添加
Sender:标头以指示真实传输实体。 -
添加跟踪标头——MSA 添加自己的
Received:标头作为第一个条目。
端口 465:隐式 TLS
历史上,端口 465 曾被简要分配用于"SMTPS"(SMTP 上的隐式 TLS),然后被重新分配,随后被 RFC 8314 在 2018 年重新标准化。今天,带有隐式 TLS 的端口 465 是提交的推荐方式——TLS 握手在连接时立即发生,在任何 SMTP 命令之前。带有 STARTTLS 的端口 587 仍然被广泛支持并且有效。
大小和速率限制
MSA 通常比 MTA 执行更严格的限制:
- 消息大小限制(通常 10-25 MB)
- 每个经过身份验证的用户的速率限制(防止被攻击的帐户发送垃圾邮件)
- 每条消息和每个时间段的收件人计数限制
- 发件人地址限制(你只能从你被授权使用的地址发送)
常见错误
- 在端口 25 上从应用程序发送。应用程序应始终通过端口 587(或 465)提交,并进行身份验证。直接发送到收件人的 MX 在端口 25 上绕过你的电子邮件服务的身份验证、DKIM 签名和声誉管理。大多数云平台(AWS、GCP、Azure)默认阻止出站端口 25。
- 在 AUTH 之前不使用 TLS。通过未加密的连接发送凭据会暴露你的 SMTP 用户名和密码。始终在 AUTH 之前使用 STARTTLS,或使用端口 465 上的隐式 TLS。
- 混淆提交凭据与邮箱凭据。某些服务对 SMTP 提交与 IMAP/POP 访问使用单独的凭据。检查你的提供商的文档。
- 忽略 MSA 拒绝响应。如果 MSA 拒绝你的消息(例如,未授权的发件人地址、消息过大),你的应用程序需要优雅地处理这个问题,而不是静默丢弃错误。
- 在应用代码中硬编码端口 25。连接到端口 25 进行提交的旧版应用程序会导致可传递性问题,并且随着 ISP 和云提供商越来越多地为非服务器使用阻止此端口,可能会完全停止工作。
- 在 STARTTLS 后不重新发出 EHLO。TLS 握手完成后,你必须发送新的 EHLO。服务器的功能列表可能会改变(AUTH 通常仅在建立加密后宣传)。
可传递性影响
- 身份验证支持 DKIM 签名。当你通过 MSA 提交时,该服务可以对你的消息应用 DKIM 签名。直接发送到远程 MTA 会绕过这一点,意味着你的消息到达时未签名,更可能被标记为垃圾邮件。
- 发件人身份验证。MSA 验证你是否被授权从你声称的地址发送。这防止你的帐户被用于欺骗其他域并维护你的发送声誉。
- 声誉管理。你的电子邮件服务(MSA)维护共享 IP 声誉。通过提交进行路由,你的消息受益于该服务与主要邮箱提供商建立的声誉。
- 反馈环处理。处理你的消息的 MSA 可以跟踪退回、投诉和传递状态,提供你维护列表卫生和保护发送声誉所需的数据。
- 处处使用 TLS。通过 TLS 提交(对提交是强制性的)确保你的消息从应用程序加密到电子邮件服务。然后该服务处理下一跳的加密,为你提供传输中的端到端保护。