跳到主要内容

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 记录 (数字越小优先级越高):

  1. mail1.example.com (priority 10)
  2. mail2.example.com (priority 20)
  3. mail3.example.com (priority 30)

第 3 步: 尝试投递

按优先级顺序尝试连接每个主机:

  1. 尝试连接最高优先级 (最低数字) 的 MX
  2. 如果连接失败, 尝试下一优先级
  3. 持续尝试直到成功或所有 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)

最佳实践

  1. 尊重 TTL: 按 TTL 值缓存 DNS 结果
  2. 连接超时: 使用合理超时 (例如初始连接 5 分钟)
  3. 重试逻辑: 对临时失败 (4xx) 定期重试
  4. 负载均衡: 对同优先级 MX 记录随机化选择
  5. IPv6 支持: 同时尝试 A 和 AAAA 记录
  6. 错误处理: 区分临时失败和永久失败

常见错误

错误 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 主机名时, 客户端应:

  1. 同时查询 A (IPv4) 和 AAAA (IPv6) 记录
  2. 如果二者均可用, 可按实现策略偏好 IPv6
  3. 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

双栈考虑事项

  1. Happy Eyeballs: 以轻微延迟并行尝试 IPv6 和 IPv4
  2. 超时处理: 不要让 IPv6 尝试过久延迟 IPv4
  3. 偏好: 允许配置 IPv4/IPv6 偏好
  4. Fallback: 始终保留 IPv4 fallback 以兼容