首页/网络/协议速查/SMTP 会话全流程(含应答)

SMTP 会话全流程(含应答)

一条完整会话:问候 → 加密 → 认证 → 信封 → 数据 → 收尾;最容易记错的是 DATA 的结束标志是「单独一行的一个点」。

协议速查网络更新于 2026-10-13

一条投递会话的五个阶段

SMTP 是纯文本命令与三位应答码交替的协议,一次投递固定走五段:服务端问候(220)→ 客户端问候与能力协商(EHLO)→ 加密升级与身份认证(STARTTLS、AUTH)→ 信封声明(MAIL FROM、RCPT TO)→ 数据投递(DATA 与结束标志)。理解这条顺序,抓包时就能一眼判断会话卡在哪一段。

基本信息

服务端口中继与投递用 25;提交用 587(要求 STARTTLS);加密提交 465(隐式 TLS)
传输TCP,命令与应答默认按 CRLF 分行
认证时机提交类连接必须先 AUTH 再声明信封,25 端口一般不做认证
行长度限制命令行不超过 512 字节,正文行不超过 998 字节(RFC 5321)

典型使用场景

  • 邮件发不出去时逐段核对应答码,判断是 DNS、连接、认证还是策略拒收
  • 写发信程序时确认库是否正确处理 STARTTLS 升级后的 EHLO 重发
  • 排查「正文被截断」:多半是 DATA 阶段遇到单独一行的点,或正文里有超长行
  • 用 telnet 或 openssl s_client 手写会话,验证凭据与退信路径是否正常

完整投递(含 STARTTLS 与认证)

完整投递(含 STARTTLS 与认证)
S: 220 mail.example.com ESMTP ready
C: EHLO client.local
S: 250-mail.example.com
S: 250-SIZE 10485760
S: 250-AUTH PLAIN LOGIN
C: STARTTLS
S: 220 Ready to start TLS
(完成 TLS 握手,之后所有内容加密)
C: EHLO client.local
C: AUTH PLAIN AHVzZXIAcGFzcw==
S: 235 2.7.0 Authentication successful
C: MAIL FROM:<me@example.com>
S: 250 2.1.0 Ok
C: RCPT TO:<you@example.net>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: Subject: test
C: (空行)
C: hello
C: .
S: 250 2.0.0 Ok: queued as 4XyZ123
C: QUIT
S: 221 2.0.0 Bye

应答码分段读法

码段含义会话位置
220 / 250服务就绪 / 命令成功问候与信封阶段
235认证成功AUTH 之后
354可以开始送正文DATA 之后
421 / 450服务不可用 / 临时失败可重试,不必放弃
550 / 554永久失败 / 事务被拒策略或地址问题,重试无用
正文里若出现以点开头的行(例如 .hidden),发送方要在行首再加一个点做转义,接收方去掉一个点还原;在 DATA 阶段直接粘贴含单独一行的点,会提前结束正文并投出一封被截断的邮件。
STARTTLS 之后必须重新发一次 EHLO:加密通道里的能力列表与明文阶段可能不同,老代码只在升级前发一次 EHLO 会出现「认证命令不被识别」的报错。
多位收件人时 RCPT TO 可重复出现,服务器对每个地址单独应答;只要有一个地址被 550 拒,就要在正文里跑一遍投递结果,不能因为整体返回 250 就认为全部成功。

易错点

  • 在 DATA 阶段粘贴含单独一行的点(日志、补丁、base64 文本里很常见)会提前结束正文,邮件内容被静默截断
  • 把 250 当成「已经送达」:它只代表本跳接收并排队,跨域投递失败是异步的,要看后续退信
  • 只用 25 端口做认证提交:该端口通常被服务商限制为服务器间中继,客户端提交应走 587 或 465
  • 忽略命令行 512 字节限制:超长 MAIL FROM 参数或邮箱地址会以 500 系列报错返回,表现为「偶发发信失败」

数据来源与参考

  • RFC 5321 §4.3(过程)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌