跳到主要内容

4. SMTP 规范 (The SMTP Specifications)

本节包含 SMTP 命令, 响应, 排序, 跟踪信息和实现问题的详细规范.

4.1. SMTP 命令 (SMTP Commands)

4.1.1. 命令语义和语法 (Command Semantics and Syntax)

SMTP 命令是不区分大小写的 ASCII 单词, 通常为 4 个字母, 某些扩展可达 8 个字母, 后面可选地跟随参数.

Extended HELLO (EHLO) 或 HELLO (HELO)

语法: EHLO domainHELO domain

EHLO 命令启动 SMTP 会话并请求服务扩展. HELO 是不支持扩展的服务器的 fallback.

示例:

C: EHLO client.example.com
S: 250-server.example.com
S: 250-SIZE 52428800
S: 250-8BITMIME
S: 250 STARTTLS

MAIL (MAIL FROM)

语法: MAIL FROM:<reverse-path> [parameters]

通过指定发送者启动邮件事务.

示例:

C: MAIL FROM:<[email protected]>
S: 250 Ok

参数: 可以包括 SIZE, BODY, AUTH 等.

RECIPIENT (RCPT TO)

语法: RCPT TO:<forward-path> [parameters]

标识邮件的一个接收者.

示例:

C: RCPT TO:<[email protected]>
S: 250 Ok

DATA

语法: DATA

表示消息内容开始. 内容以 <CRLF>.<CRLF> 结束.

示例:

C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: [email protected]
C: To: [email protected]
C: Subject: Test
C:
C: Message body here.
C: .
S: 250 Ok: queued as 12345

RESET (RSET)

语法: RSET

中止当前邮件事务并重置缓冲区.

示例:

C: RSET
S: 250 Ok

VERIFY (VRFY)

语法: VRFY string

验证邮箱是否存在.

示例:

C: VRFY Jones
S: 250 Fred Jones <[email protected]>

注意: 许多服务器出于安全原因禁用此命令.

EXPAND (EXPN)

语法: EXPN string

展开邮件列表.

示例:

C: EXPN staff
S: 250-Alice <[email protected]>
S: 250 Bob <[email protected]>

HELP

语法: HELP [command]

提供帮助信息.

示例:

C: HELP
S: 214-This server supports the following commands:
S: 214 EHLO MAIL RCPT DATA RSET VRFY HELP QUIT

NO OPERATION (NOOP)

语法: NOOP

不执行任何操作, 可用于保持连接.

示例:

C: NOOP
S: 250 Ok

QUIT

语法: QUIT

终止 SMTP 会话.

示例:

C: QUIT
S: 221 server.example.com closing connection

4.1.2. 命令参数语法 (Command Argument Syntax)

命令遵循 ABNF (RFC 5234) 定义的严格语法规则.

邮箱格式: local-part@domain

  • Local-part: 最多 64 个字符
  • Domain: 完全限定域名或地址 literal

地址 Literals:

  • IPv4: [192.0.2.1]
  • IPv6: [IPv6:2001:db8::1]

4.1.3. 地址 Literals (Address Literals)

地址 literal 是括在方括号中的域:

  • [192.0.2.1] - IPv4 地址
  • [IPv6:2001:db8::1] - IPv6 地址

4.1.4. 命令顺序 (Order of Commands)

有效命令序列:

  1. Connection: 服务器发送 220
  2. Greeting: 客户端发送 EHLO/HELO
  3. Transaction: MAIL -> 一个或多个 RCPT -> DATA
  4. Termination: QUIT

无效序列会导致 503 "Bad sequence of commands" 错误.

4.1.5. 私有使用命令 (Private-Use Commands)

X 开头的命令保留用于私有使用和实验.

4.2. SMTP 响应 (SMTP Replies)

4.2.1. 响应代码严重性和理论 (Reply Code Severities and Theory)

响应代码是 3 位数字:

  • 2yz: 肯定完成
  • 3yz: 肯定中间状态
  • 4yz: 临时否定 (可重试)
  • 5yz: 永久否定 (不应重试)

第二位表示类别:

  • x0z: 语法
  • x1z: 信息
  • x2z: 连接
  • x5z: 邮件系统

4.2.2. 按功能组划分的响应代码 (Reply Codes by Function Groups)

连接建立:

  • 220: Service ready
  • 421: Service not available

客户端启动:

  • 250: OK
  • 500: Syntax error
  • 502: Command not implemented

邮件事务:

  • 250: OK
  • 354: Start mail input
  • 450/550: Mailbox unavailable
  • 451/551: Error in processing
  • 452/552: Insufficient storage
  • 553: Mailbox name invalid
  • 554: Transaction failed

4.2.3. 数值顺序的响应代码 (Reply Codes in Numeric Order)

  • 211: System status
  • 214: Help message
  • 220: Service ready
  • 221: Closing connection
  • 250: OK
  • 251: User not local; will forward
  • 252: Cannot VRFY user, but will accept
  • 354: Start mail input
  • 421: Service not available
  • 450: Mailbox unavailable
  • 451: Local error
  • 452: Insufficient storage
  • 455: Server unable to accommodate parameters
  • 500: Syntax error
  • 501: Syntax error in parameters
  • 502: Command not implemented
  • 503: Bad sequence of commands
  • 504: Command parameter not implemented
  • 550: Mailbox unavailable
  • 551: User not local
  • 552: Storage allocation exceeded
  • 553: Mailbox name not allowed
  • 554: Transaction failed
  • 555: Parameters not recognized

4.2.4. 响应代码 502 (Reply Code 502)

502 表示命令未实现. 客户端不应重试未实现的命令.

4.2.5. DATA 和后续 <CRLF>.<CRLF> 之后的响应代码

DATA 完成后:

  • 250: Message accepted
  • 450/550: Mailbox unavailable
  • 451/551: Processing error
  • 452/552: Insufficient storage
  • 554: Transaction failed

4.3. 命令和响应的排序 (Sequencing of Commands and Replies)

4.3.1. 排序概述 (Sequencing Overview)

SMTP 是 lock-step 的: 客户端发送命令, 等待响应, 然后发送下一个命令. PIPELINING 扩展允许批量发送, 是例外.

4.3.2. 命令-响应序列 (Command-Reply Sequences)

最小实现:

S: 220
C: EHLO
S: 250
C: MAIL FROM
S: 250
C: RCPT TO
S: 250
C: DATA
S: 354
C: (message data)
C: .
S: 250
C: QUIT
S: 221

4.4. 跟踪信息 (Trace Information)

每个 SMTP 服务器在接受消息时都会添加一个 Received 头部字段:

格式:

Received: from sender.example.com (host.example.com [192.0.2.1])
by receiver.example.com (Postfix) with ESMTP id 12345
for <[email protected]>; Mon, 24 Dec 2024 10:00:00 +0000 (UTC)

组成部分:

  • from: 发送主机标识
  • by: 接收主机
  • with: 使用的协议 (SMTP, ESMTP 等)
  • for: 接收者地址
  • Timestamp

4.5. 其他实现问题 (Additional Implementation Issues)

4.5.1. 最小实现 (Minimum Implementation)

功能完整的 SMTP 必须支持:

  • 命令: EHLO, MAIL, RCPT, DATA, RSET, NOOP, QUIT
  • 响应代码: 所有标准代码
  • 排队和重试逻辑
  • 正确错误处理

4.5.2. 透明性 (Transparency)

服务器必须处理 dot-stuffing: DATA 传输期间以 . 开头的行必须转义为 ...

4.5.3. 大小和超时 (Sizes and Timeouts)

4.5.3.1. 大小限制和最小值

最小要求:

  • Local-part: 64 octets
  • Domain: 255 octets
  • Path: 256 octets
  • Command line: 512 octets
  • Reply line: 512 octets
  • Text line: 1000 octets
  • Recipients buffer: 100 recipients

4.5.3.2. 超时

客户端超时:

  • 初始 220 消息: 5 分钟
  • MAIL 命令: 5 分钟
  • RCPT 命令: 5 分钟
  • DATA 启动: 2 分钟
  • 数据块: 3 分钟
  • DATA 终止: 10 分钟

服务器超时:

  • 等待命令: 5 分钟
  • 等待 DATA: 10 分钟

4.5.4. 重试策略 (Retry Strategies)

出现临时失败 (4yz 代码) 时:

  • 至少每 30 分钟重试一次
  • 至少持续尝试 4-5 天
  • 定期向发送者发送警告
  • 最终失败后生成 bounce

4.5.5. 带 Null Reverse-Path 的消息 (Messages with a Null Reverse-Path)

Bounce 消息使用 MAIL FROM:<> (null reverse-path) 防止邮件循环. 服务器必须接受 null reverse-path, 但不得为它们生成 bounce.