SMTP
→ 返回 计算机网络
SMTP(Simple Mail Transfer Protocol)是电子邮件的发送协议,负责将邮件从发件方客户端/服务器传输到收件方服务器。接收邮件使用 IMAP 或 POP3。
邮件系统角色
发件人
│
▼
MUA(邮件客户端:Outlook / Thunderbird / App)
│ SMTP(提交,端口 587)
▼
MTA(发送方邮件服务器:smtp.gmail.com)
│ SMTP(中继,端口 25)
▼
MTA(接收方邮件服务器:mx.example.com)
│
▼
MDA(邮件投递代理:写入收件人邮箱)
│ IMAP / POP3
▼
MUA(收件人客户端)
| 角色 | 说明 |
|---|---|
| MUA(Mail User Agent) | 用户使用的邮件客户端或 Web 邮箱 |
| MTA(Mail Transfer Agent) | 负责转发邮件的服务器,如 Postfix、Sendmail |
| MDA(Mail Delivery Agent) | 将邮件写入用户邮箱,如 Dovecot |
| MX 记录 | DNS 中标记域名对应邮件服务器地址的记录 |
SMTP 通信过程
客户端 服务端
←── 220 smtp.example.com ESMTP
EHLO client.local ───►
←── 250-smtp.example.com
←── 250-STARTTLS
←── 250-AUTH PLAIN LOGIN
←── 250 SIZE 26214400
STARTTLS ───► ← 升级到 TLS
←── 220 Go ahead
(TLS 握手)
AUTH LOGIN ───►
←── 334 dXNlcm5hbWU6 (Base64 提示)
(Base64 用户名) ───►
←── 334 cGFzc3dvcmQ6
(Base64 密码) ───►
←── 235 Authentication successful
MAIL FROM:<sender@a.com> ───►
←── 250 OK
RCPT TO:<user@b.com> ───►
←── 250 OK
DATA ───►
←── 354 Start mail input
From: ...
To: ...
Subject: ...
(邮件正文)
. ───► ← 单独一行 "." 表示正文结束
←── 250 OK: queued as abc123
QUIT ───►
←── 221 Bye
SMTP 常用命令
| 命令 | 说明 |
|---|---|
EHLO domain | 扩展握手,服务器返回支持的扩展能力 |
HELO domain | 旧版握手(不支持扩展) |
STARTTLS | 在明文连接上升级为 TLS |
AUTH LOGIN/PLAIN | 身份认证 |
MAIL FROM:<addr> | 声明发件人(信封发件人,可与 From 头不同) |
RCPT TO:<addr> | 声明收件人(可多次指定多个收件人) |
DATA | 开始传输邮件内容(头部 + 正文) |
RSET | 重置当前事务 |
QUIT | 结束连接 |
VRFY addr | 验证地址是否存在(多数服务器禁用) |
SMTP 响应码
| 代码 | 含义 |
|---|---|
| 220 | 服务就绪 |
| 221 | 服务关闭连接 |
| 235 | 认证成功 |
| 250 | 请求成功 |
| 354 | 开始输入邮件内容 |
| 421 | 服务暂时不可用(稍后重试) |
| 450 | 邮箱暂时不可用(软退信) |
| 451 | 本地错误,请求中止 |
| 452 | 系统存储不足 |
| 500 | 命令未识别 |
| 501 | 参数语法错误 |
| 535 | 认证失败(用户名或密码错误) |
| 550 | 邮箱不存在(硬退信) |
| 551 | 用户不在本地 |
| 553 | 邮件地址格式错误 |
2xx = 成功,4xx = 临时失败(可重试),5xx = 永久失败(不应重试)
端口与加密方式
| 端口 | 用途 | 加密 | 推荐 |
|---|---|---|---|
| 25 | MTA 之间中继(服务器到服务器) | 明文 / STARTTLS | 仅服务器间,不用于客户端提交 |
| 465 | SMTPS(隐式 TLS) | SSL/TLS(连接建立即加密) | 旧标准,部分服务商仍使用 |
| 587 | 邮件提交(客户端到服务器) | STARTTLS(明文升级) | 推荐,RFC 6409 标准提交端口 |
端口 25 通常被云服务商(AWS、阿里云)对外封锁,防止垃圾邮件发送;应用程序发信应使用 587。
IMAP vs POP3
| 特性 | IMAP(143 / 993) | POP3(110 / 995) |
|---|---|---|
| 邮件存储 | 保留在服务器 | 下载到本地后删除(默认) |
| 多设备同步 | 支持,文件夹/已读状态同步 | 不支持 |
| 离线访问 | 需手动同步或标记缓存 | 下载后可离线 |
| 适用场景 | 多设备、企业邮箱 | 单设备、带宽受限场景 |
| 加密端口 | 993(SSL)/ 143(STARTTLS) | 995(SSL)/ 110(STARTTLS) |
邮件头部关键字段
From: Alice <alice@example.com> 发件人(显示给收件人)
To: Bob <bob@example.com> 收件人
Cc: charlie@example.com 抄送
Bcc: archive@example.com 密送(收件人不可见)
Reply-To: support@example.com 回复地址(与 From 不同时使用)
Subject: 订单确认 #12345
Date: Mon, 18 May 2026 10:00:00 +0800
Message-ID: <uuid@smtp.example.com> 全局唯一标识
In-Reply-To: <prev-msg-id> 回复引用
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="boundary123"
X-Mailer: JavaMail 客户端标识(自定义头)
信封地址 vs 头部地址:
MAIL FROM(信封发件人)用于退信路由,可与From:头不同- 收件人看到的是
From:头,退信/SPF 校验的是信封MAIL FROM
邮件格式:MIME
MIME(Multipurpose Internet Mail Extensions)扩展了邮件格式以支持多媒体内容:
multipart/mixed ← 根节点(含附件时)
├── multipart/related ← 正文 + 内嵌资源
│ ├── text/html ← HTML 正文
│ └── image/png ← 内嵌图片(cid: 引用)
└── application/pdf ← 附件
纯文本邮件:Content-Type: text/plain; charset=UTF-8
HTML 邮件:Content-Type: text/html; charset=UTF-8
邮件送达率:SPF / DKIM / DMARC
现代邮件系统通过三个 DNS 记录验证发件方身份,未配置则极易进垃圾箱。
SPF(Sender Policy Framework)
在 DNS TXT 记录中声明允许代表该域名发送邮件的 IP/服务器:
example.com. TXT "v=spf1 include:_spf.google.com ip4:203.0.113.5 ~all"
| 修饰符 | 含义 |
|---|---|
+all | 允许所有(危险,不推荐) |
~all | 软失败(未授权 IP 的邮件标为可疑) |
-all | 硬失败(未授权 IP 的邮件直接拒绝,推荐) |
DKIM(DomainKeys Identified Mail)
发送服务器用私钥对邮件头和正文签名,收件服务器用 DNS 中的公钥验证完整性:
# DNS TXT 记录
selector._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<公钥>"
# 邮件头中的签名
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=selector;
h=from:to:subject:date; bh=<正文hash>; b=<签名>
DMARC(Domain-based Message Authentication)
基于 SPF 和 DKIM 的上层策略,定义校验失败时的处理方式:
# DNS TXT 记录
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; pct=100"
| 策略 | 说明 |
|---|---|
p=none | 仅监控,不处理(调试阶段) |
p=quarantine | 未通过的邮件送入垃圾箱 |
p=reject | 直接拒绝未通过的邮件(最严格) |
配置顺序建议:先 SPF → 再 DKIM → 最后 DMARC(none → quarantine → reject 逐步收紧)。
退信处理
| 类型 | 说明 | SMTP 响应码 | 处理策略 |
|---|---|---|---|
| 硬退信(Hard Bounce) | 收件地址永久不存在 | 5xx | 立即从邮件列表移除,不再发送 |
| 软退信(Soft Bounce) | 临时失败(邮箱满、服务器忙) | 4xx | 按指数退避重试,超次数后转硬退信 |
| 垃圾邮件投诉 | 收件人点击”举报垃圾” | — | 立即取消订阅,大量投诉会损害域名声誉 |
主流邮件发送服务(SMTP Relay)
| 服务 | 免费额度 | 特点 |
|---|---|---|
| AWS SES | 62,000 封/月(EC2 内) | 便宜、可靠,需域名验证 |
| SendGrid | 100 封/天 | 分析丰富,模板管理完善 |
| Mailgun | 1,000 封/月 | 开发者友好,日志详细 |
| Resend | 3,000 封/月 | 现代 API,React Email 支持 |
| Postmark | 100 封/月 | 事务邮件专注,送达率极高 |
| 阿里云邮件推送 | 200 封/日 | 国内送达率好 |
相关
- 通信协议 — 邮件协议在应用层的位置
- TLS — STARTTLS / SMTPS 的 TLS 握手基础
- DNS — MX 记录、SPF/DKIM/DMARC TXT 记录
- 网络安全 — 邮件欺骗、钓鱼攻击防护
- Spring Boot 邮件发送 — JavaMail + Spring Boot 实现