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 domain 或 HELO 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)
有效命令序列:
- Connection: 服务器发送 220
- Greeting: 客户端发送 EHLO/HELO
- Transaction: MAIL -> 一个或多个 RCPT -> DATA
- 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.