5. 地址解析和邮件处理 (Address Resolution and Mail Handling)
本节描述 SMTP 客户端如何确定邮件消息应投递到哪里, 以及它们应如何处理投递过程.
5.1. 定位目标主机 (Locating the Target Host)
当 SMTP 客户端要向特定域投递邮件时, 它必须确定适当的目的地主机. 该过程使用域名系统 (DNS), 并遵循以下步骤:
第 1 步: 查询 MX 记录
查询目标域的 Mail eXchanger (MX) 记录:
$ dig example.com MX
;; ANSWER SECTION:
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
example.com. 3600 IN MX 30 mail3.example.com.
第 2 步: 按优先级排序
按优先级排序 MX 记录 (数字越小优先级越高):
mail1.example.com(priority 10)mail2.example.com(priority 20)mail3.example.com(priority 30)
第 3 步: 尝试投递
按优先级顺序尝试连接每个主机:
- 尝试连接最高优先级 (最低数字) 的 MX
- 如果连接失败, 尝试下一优先级
- 持续尝试直到成功或所有 MX 主机耗尽
第 4 步: 回退到 A/AAAA 记录
如果不存在 MX 记录, 将域本身视为邮件服务器:
- 查询 A 记录 (IPv4) 或 AAAA 记录 (IPv6)
- 尝试直接连接该 IP 地址
重要: 如果 MX 记录存在但全部失败, 不要回退到 A/AAAA 记录.
详细算法
1. 查询目标域的 MX 记录
2. 如果找到 MX 记录:
a. 移除任何指向 "." 的 MX (null MX)
b. 按优先级排序剩余 MX
c. 对每个优先级级别 (从最低数字开始):
i. 将该优先级的所有 MX 主机解析为 IP 地址
ii. 随机排列同优先级主机
iii. 尝试连接每个主机
iv. 如果连接成功, 投递邮件
v. 如果该优先级的所有主机失败, 尝试下一优先级
d. 如果所有 MX 主机失败, 延迟投递 (temporary failure)
3. 如果未找到 MX 记录:
a. 查询域的 A/AAAA 记录
b. 尝试直接连接域的 IP
c. 如果连接失败, 延迟投递
4. 如果域无法解析:
- 返回永久失败 (5xx code)
示例场景
场景 1: 标准 MX 解析
域: example.com
MX Records:
10 mail1.example.com
20 mail2.example.com
Process:
1. Try mail1.example.com -> Success, deliver mail
场景 2: 主 MX 失败
MX Records:
10 mail1.example.com (down)
20 mail2.example.com
Process:
1. Try mail1.example.com -> Connection failed
2. Try mail2.example.com -> Success, deliver mail
场景 3: 无 MX 记录
域: smallcompany.example
No MX records found
Process:
1. Look up A record for smallcompany.example
2. Connect directly to IP address
3. Deliver mail
场景 4: Null MX 记录
域: nomail.example
MX Record:
0 .
Meaning: This domain does not accept mail
Process: Return permanent failure (556 or 550)
最佳实践
- 尊重 TTL: 按 TTL 值缓存 DNS 结果
- 连接超时: 使用合理超时 (例如初始连接 5 分钟)
- 重试逻辑: 对临时失败 (4xx) 定期重试
- 负载均衡: 对同优先级 MX 记录随机化选择
- IPv6 支持: 同时尝试 A 和 AAAA 记录
- 错误处理: 区分临时失败和永久失败
常见错误
错误 1: 当 MX 存在但失败时回退到 A 记录
Wrong:
MX records exist but all fail -> Try A record
Correct:
MX records exist but all fail -> Defer delivery (temporary failure)
错误 2: 未正确处理 null MX
Wrong:
MX: 0 . -> Ignore and try A record
Correct:
MX: 0 . -> Domain explicitly rejects mail, return permanent error
5.2. IPv6 和 MX 记录 (IPv6 and MX Records)
解析 MX 主机名时, 客户端应:
- 同时查询 A (IPv4) 和 AAAA (IPv6) 记录
- 如果二者均可用, 可按实现策略偏好 IPv6
- IPv6 连接失败时回退到 IPv4
示例:
mail.example.com has:
A 192.0.2.1
AAAA 2001:db8::1
Process:
1. Try IPv6: 2001:db8::1
2. If fails, try IPv4: 192.0.2.1
IPv6 地址 Literal
SMTP 支持在 MAIL FROM 和 RCPT TO 中使用 IPv6 地址 literal:
格式: user@[IPv6:2001:db8::1]
示例:
C: MAIL FROM:<sender@[IPv6:2001:db8::1]>
S: 250 Ok
双栈考虑事项
- Happy Eyeballs: 以轻微延迟并行尝试 IPv6 和 IPv4
- 超时处理: 不要让 IPv6 尝试过久延迟 IPv4
- 偏好: 允许配置 IPv4/IPv6 偏好
- Fallback: 始终保留 IPv4 fallback 以兼容