术语 · SMTP 端口
应用发送邮件应该使用哪个 SMTP 端口?
大多数应用应使用其邮件服务商记录的提交端点和端口。587 端口是标准邮件提交端口,通常先以明文 SMTP 开始,再升级至 STARTTLS。465 端口使用隐式 TLS 进行邮件提交,因此 TLS 握手会立即开始。25 端口主要用于服务器到服务器的 SMTP 中继,而非日常的已验证应用提交。可用配置必须同时匹配四项:主机名、端口、TLS 模式和身份验证方法。
SMTP 端口决定了协议角色和连接模式
端口号并不只是通往同一个服务、可以随意互换的一扇门。它有助于识别服务器提供的是哪种 SMTP 角色,以及连接如何开始。邮件提交是从应用或用户代理到提交服务的第一次交接。中继则是邮件服务器之间的邮件传输。标准将这两项工作分开,因为提交可能需要身份验证、发件人授权和邮件策略检查,而这些检查并不以同样的方式适用于公共邮件中继。端口还可以表明客户端是先发送 SMTP 命令、之后再用 STARTTLS 升级,还是一开始就立即进行 TLS 握手。请把服务商给出的主机名、端口、TLS 模式和身份验证说明当作一个整体配置。从不相关的服务商那里照搬端口,或者在出错后只改端口,可能会把网络问题变成 TLS 或身份验证失败,而原本的问题并没有得到解决。
25 端口主要用于邮件服务器之间的中继
25 端口是传统的 SMTP 中继端口,用于一个邮件传输代理(MTA)把邮件交给另一个 MTA。RFC 6409 将中继保留在 25 端口,同时把新邮件的提交分离到 587 端口。因此,应用不应假定直接连接收件人邮件服务器的 25 端口是发送产品邮件的常规方式。直接中继需要排队、DNS 路由、退信处理、防滥用控制、信誉管理以及符合标准的重试行为。网络和托管服务商也可能限制出站的 25 端口。例如,AWS 的文档说明,默认情况下会对 Amazon EC2 在 25 端口上的邮件流量进行限流。25 端口仍然可能是某个服务商提供的、或受控基础设施内部的有文档说明的选项,但它可用并不意味着它是首选的提交方式。只有当负责的服务明确在文档中说明了该端点、安全模式和运营模式时,才使用它。
587 端口是标准的邮件提交端口
RFC 6409 将 587 端口保留用于邮件提交,并描述了一种提交服务:它可以在接受新邮件之前拒绝未授权的邮件、要求身份验证并执行策略。常见的 587 端口会话以 SMTP 开始,在 `EHLO` 之后公布 STARTTLS 扩展,将连接升级为 TLS,再次发送 `EHLO`,进行身份验证,然后提交邮件。“常见”二字很关键:具体的身份验证机制和要求以服务商当前的文档和服务器能力为准。安全的客户端应当要求完成预期的 TLS 升级并校验服务器证书,而不是在协商失败后继续以明文方式通信。不要把最初未加密的协议问候与未受保护的身份验证会话混为一谈;STARTTLS 的设计目的就是在发送凭据和邮件数据之前升级该连接。587 端口标识的是提交服务,而能否成功强制使用 TLS 则取决于客户端策略是否正确。
465 端口使用隐式 TLS 进行提交
465 端口被注册用于通过隐式 TLS 进行邮件提交。使用隐式 TLS 时,客户端在 TCP 连接建立后立即进行 TLS 握手,并且只在受保护的通道内发送 SMTP 命令。这与使用 STARTTLS 的 587 端口不同,后者由客户端先收到 SMTP 问候,然后再请求升级。RFC 8314 推荐使用隐式 TLS 进行提交,同时也描述了一个过渡期:服务商和客户端可以同时支持使用隐式 TLS 的 465 端口和使用 STARTTLS 的 587 端口。该 RFC 指出,只要 TLS 是强制的,正确实现的客户端和服务器使用任一模式都能提供基本相当的安全性。实际的原则是,不要宣称某个端口在任何情况下都是正确的。请使用服务商支持的确切端点和模式。对隐式 TLS 监听端口配置 STARTTLS,或对 STARTTLS 监听端口配置隐式 TLS,通常会在身份验证之前就失败。
服务商特有的备用端口是明确的约定
一些服务商会提供备用端口来绕开网络限制,但这些端口号并不是适用于所有服务的通用 SMTP 标准。Amazon SES 当前的文档说明在 25、587 和 2587 端口上使用 STARTTLS,在 465 和 2465 端口上使用 TLS Wrapper(它对隐式 TLS 的称呼)。SES 要求使用加密连接,并按区域发布 SMTP 端点。这说明了为什么端口必须取自所选服务商的文档,而不是一份通用列表。2587 端口并不意味着在任何地方都是 STARTTLS,2465 端口也不能标识任意主机上的隐式 TLS 服务。备用端口也不能绕过发件人验证、凭据作用域、配额或服务商政策。请在生产配置中记录来源 URL 和核实日期,这样运维人员就能区分哪些是有意为之的服务商设置,哪些是多年前被复制进环境变量、却没人能解释的“魔法数字”。
同时配置主机名、端口、TLS 和身份验证
一个稳健的 SMTP 配置是一个整体:服务商主机名、端口、传输安全模式、证书校验策略、身份验证机制、用户名、密钥、连接超时以及发信身份。主机名很重要,因为 TLS 证书是针对它进行校验的,而且服务商可能会提供不同区域的端点。端口和 TLS 模式必须一致。只有在预期的受保护通道建立之后才进行身份验证,并且密钥应当保存在机密管理器中,而不是源代码、浏览器打包文件、日志或诊断输出中。按环境分离凭据和配置,以免本地测试意外地通过生产环境发信。设置有限的连接超时和命令超时,但让持久化的应用队列来控制邮件的重试。名为 `secure` 的库选项在一个 SDK 中可能表示隐式 TLS,在另一个 SDK 中却可能只是要求 STARTTLS,因此请核实该库的定义并测试实际协商出的行为,而不要依赖选项名称。
分层测试连接,且不暴露机密信息
先在与应用相同的运行时网络中测试 DNS 解析和 TCP 可达性。在连接建立之前就超时,说明问题可能在于路由、防火墙、服务商的出站策略、主机名错误或端口关闭。接着测试预期的 TLS 模式。对于隐式 TLS,TLS 客户端应当先收到证书,然后收到 SMTP 问候。对于 STARTTLS,支持 SMTP 的客户端应当收到问候,发送 `EHLO`,看到服务器公布了 STARTTLS,请求升级,校验证书,并在 TLS 建立后再次发送 `EHLO`。RFC 3207 要求客户端和服务器丢弃握手之前获得的信息,这就是第二次 `EHLO` 之所以重要的原因。之后再用一个受控账户测试身份验证。在分享日志之前,请隐去用户名、令牌、收件人地址、完整的服务器会话记录和邮件内容。连通性探测不需要进行生产发送,也不需要使用真实的客户地址。
按实际失败的阶段对失败进行分类
连接被拒绝表示 TCP 目标主动拒绝了连接;超时表示在时限内没有收到可用的响应。TLS 握手错误指向模式不匹配、证书问题、协议不兼容、流量被拦截或端点错误。身份验证错误发生在更后面的阶段,应当从凭据、机制、账户或授权配置方面排查,而不是靠随意更换端口来解决。在 `MAIL FROM`、`RCPT TO` 或 `DATA` 阶段出现的 SMTP 回复码,描述的是更靠后的策略和邮件层面的决定。请保留失败阶段、时间戳、端点、尝试次数、数字回复码以及经过隐私过滤的响应内容。4xx SMTP 回复通常是暂时性的,5xx 回复通常对所尝试的命令是永久性的,但重试必须有上限,并且要考虑到具体收件人。如果服务商已经受理了邮件数据,不要因为之后某个应用请求超时就盲目地重复提交;请使用服务商标识符和事件历史进行核对。
端口测试成功不等于邮件已投递或进入收件箱
TCP 连接成功只能证明有监听程序作出了应答。在证书校验通过的情况下,TLS 握手成功证明与经过认证的端点之间建立了受保护的连接。身份验证成功证明服务器在该会话中接受了客户端出示的身份。在发送邮件数据后收到 SMTP `250` 响应,意味着作出响应的服务器按照协议接受了投递责任,而不是某个人已经收到或阅读了这封邮件。之后的中继仍可能失败,收件系统也可能在接受邮件的同时,把它归类到主收件箱以外的位置。请在应用记录和监控中将这些状态分开。网络可用性、TLS 协商、身份验证、服务商受理、目标服务器受理、退信、投诉和互动都是不同的观察结果。这种区分可以防止把端口探测误报为投递测试,也可以防止仅仅因为无法证明邮件进入了收件箱,就对已被受理的邮件进行重试。
有意识地在 SMTP 提交和邮件 API 之间作出选择
当系统已有成熟 SMTP 客户端、必要平台将 SMTP 作为支持的集成方式提供,或确实需要协议级控制时,请使用 SMTP 提交。当结构化请求、限定作用域的令牌、幂等性、批量资源和机器可读事件记录适合工作负载时,HTTPS 邮件 API 可以是更好的应用边界。服务商仍可在下游使用 SMTP 到达收件人邮件系统,因此 API 并不会废除邮件传输。它会将与服务商交接相关的端口、TLS、身份验证和重试责任从应用的 SMTP 配置中移出。
常见问题
我的应用应该使用 SMTP 587 端口还是 465 端口?
使用服务商文档中规定的端口和 TLS 模式。587 端口通常使用 STARTTLS,而 465 端口使用隐式 TLS。只要正确实现并强制要求,两者都能保护邮件提交;客户端配置必须与服务器的监听端口相匹配。
为什么 SMTP 25 端口被封锁或连接超时?
托管平台、ISP、防火墙或目标方策略可能会限制 25 端口,因为它用于邮件服务器之间的中继,并且经常被滥用。请确认网络策略,并使用服务商文档中给出的提交端点,而不是换一个任意端口来规避限制。
我可以把 587 端口直接换成 465 端口,而不改其他任何配置吗?
通常不行。587 端口一般先以 SMTP 开始,再通过 STARTTLS 升级;而 465 端口一开始就立即进行 TLS 握手。请按照服务商和库的文档,同时修改端口和客户端的 TLS 模式。
587 端口默认是加密的吗?
该端口标识的是邮件提交,但是否加密仍取决于 STARTTLS 协商和客户端策略。请将客户端配置为必须成功完成升级、校验证书,并在无法建立受保护的提交时拒绝发送凭据或邮件数据。
SMTP 连接被拒绝(connection refused)是什么意思?
它表示 TCP 目标在 SMTP 协商之前就拒绝了连接。常见原因包括主机或端口错误、服务未在监听、防火墙拒绝,或者该服务商端点无法从当前网络访问。
SMTP 端口测试成功是否能证明邮件已送达?
不能。它只能证明测试实际完成了的那些阶段,例如 TCP 或 TLS。身份验证、邮件受理、目标服务器受理、退信处理、邮箱分类以及收件人的互动都需要单独的证据,并且必须分别报告。
参考来源
- RFC 6409:Message Submission for Mail(邮件提交) — RFC Editor
- RFC 8314:明文已过时:将传输层安全性(TLS)用于邮件提交和访问 — RFC Editor
- RFC 3207:基于 TLS 的安全 SMTP 服务扩展 — RFC Editor
- RFC 5321:简单邮件传输协议(SMTP) — RFC Editor
- 连接到 Amazon SES SMTP 端点 — Amazon Web Services