本页目录

SMTP

SMTP 是互联网最老的协议之一——从 HELO 到 DATA 到 QUIT,邮件在 MTA 之间逐跳转发。SPF/DKIM/DMARC 这三层"补丁"试图在 SMTP 的信任模型上建立发送方验证。

概述

SMTP 是互联网最古老的协议之一(1982),至今仍是全球邮件传输的基础。它用简单的命令-响应模型在 TCP 连接上传输邮件。核心概念是 envelope(MAIL FROM/RCPT TO)和 header(From/To)的分离——envelope 决定路由,header 是用户看到的。SPF 验证发件服务器 IP,DKIM 对邮件内容签名,DMARC 统一两者的策略——三者联合防御垃圾邮件和域名伪造。

SMTP 会话模型

SMTP 用命令-响应模式 (类似 FTP)。所有传输在 TCP 连接上:

S: 220 mail.example.com ESMTP Postfix
C: EHLO client.example.com          ← EHLO = 扩展 HELLO
S: 250-mail.example.com
S: 250-STARTTLS
S: 250-PIPELINING
S: 250-SIZE 52428800
S: 250 AUTH PLAIN LOGIN

C: STARTTLS                         ← 升级到 TLS
S: 220 Ready to start TLS
(C: TLS handshake)
C: EHLO client.example.com          ← re-EHLO after STARTTLS (新协商)

C: AUTH PLAIN <base64(\0user\0pass)>  ← 认证
S: 235 2.7.0 Authentication successful

C: MAIL FROM:<sender@example.com>   ← envelope-from (反弹地址, SPF 检查此项)
S: 250 2.1.0 Ok
C: RCPT TO:<recipient@example.org>  ← envelope-to
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Sender <sender@example.com>  ← header-from (用户看到的, DMARC 对齐)
C: To: Recipient <recipient@example.org>
C: Subject: Test
C: Date: Thu, 01 Jan 2025 00:00:00 +0000
C: Message-ID: <abc123@example.com>
C: 
C: Hello, World
C: .                                   ← 单行 '.' 结束 DATA
S: 250 2.0.0 Ok: queued as 1A2B3C4D5E
C: QUIT
S: 221 2.0.0 Bye

Envelope vs Header

关键区别: SMTP envelope (MAIL FROM / RCPT TO) 和 message header (From / To) 是独立的⁠。SPF 检查 envelope-from domain。DMARC 强制 alignment (header From domain = envelope-from domain or DKIM domain)。

SMTP 端口

25:   MTA↔MTA relay (传统, 现在极少用于客户端)
587:  Submission (客户端 → MSA, 强制 STARTTLS + AUTH)
465:  SMTPS (SMTP over TLS, 非标准但广泛使用, 现在 RFC 8314 认可)

SPF

DNS: example.com TXT "v=spf1 ip4:192.0.2.0/24 include:_spf.google.com -all"

接收方 MTA:
  1. 查 MAIL FROM domain 的 SPF record
  2. 验证连接来源 IP 是否在 SPF 授权列表中
  3. 结果: Pass / Fail / SoftFail (~all) / Neutral (?all) / None (无 SPF)

  如 Fail + DMARC reject → 拒绝 (550 5.7.1 SPF failed)

DKIM

签名: MTA 用私钥对选定 headers (from, to, subject, date, message-id) +
      body hash (SHA-256) 签名

DKIM-Signature header:
  v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=default;
  h=from:to:subject:date:message-id;
  bh=<base64(SHA256(canonicalized body))>;
  b=<base64(RSA-SIGN(header hash + body hash))>

DNS: default._domainkey.example.com TXT "v=DKIM1; k=rsa; p=<public key>"

验证: MTA 取 p= → 验证签名 → bh 比对 → OK

DMARC

DNS: _dmarc.example.com TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100"

验证:
  1. SPF alignment:  envelope-from domain == header From domain? (strict or relaxed)
  2. DKIM alignment: d= domain == header From domain? (strict or relaxed)
  3. 任一 pass → DMARC pass
  4. 两个都 fail → 按 policy: none (只报告), quarantine (标记垃圾), reject (拒绝)

  rua: 聚合报告 (每天, XML)
  ruf: 实时失败报告 (很少用, 隐私问题)
  pct: 生效百分比 (100 = fully enforced)

参考

  • 工具⁠: swaks --to user@example.com --server mail.example.com --tls, dig TXT _dmarc.example.com
  • mxtoolbox.com for SPF/DKIM/DMARC validation

Keywords: SMTP, EHLO, envelope, STARTTLS, SPF, DKIM, DMARC, alignment, submission