← RFC Reference

SMTP 真正如何工作

Email Concepts Encyclopedia Published March 2026
ELI5: 发送电子邮件就像寄挂号信。首先你查找地址 (DNS),然后走到邮局报上身份 (EHLO)。职员检查你的身份证 (AUTH),你交上信封信息 (MAIL FROM, RCPT TO),然后是信件本身 (DATA)。职员盖章表示接受或用编号代码告诉你哪里出问题了。整个过程都是通过 TCP 连接上的纯文本进行的。

完整的SMTP事务处理流程演示——从DNS查询到最终投递。如果你以编程方式发送电子邮件,这是你需要的心智模型。

整体图景

SMTP——简单邮件传输协议——是在互联网上传输电子邮件的协议。根据RFC 5321定义,自1982年以来一直是电子邮件的骨干(原始RFC 821)。尽管经历了数十年的扩展,核心事务仍然是两个服务器之间通过TCP 25端口的简短同步文本对话。

每次电子邮件投递都遵循相同的序列:

  1. DNS查询——查找收件人的邮件服务器
  2. TCP连接——连接到25端口(或465/587提交端口)
  3. 横幅和EHLO——交换身份和功能
  4. STARTTLS——升级到加密连接(通常)
  5. AUTH——认证(如果使用587端口提交)
  6. 信封——MAIL FROM和RCPT TO
  7. DATA——传输消息头和正文
  8. QUIT——关闭连接

第1步:DNS——查找邮件服务器

在任何SMTP对话开始之前,发送服务器必须发现将消息投递到何处。它查询收件人域的MX记录DNS。

$ dig +short MX example.com
10 mx1.example.com.
20 mx2.example.com.

数字是优先级(越小越优先)。发送者首先尝试mx1.example.com。如果无法访问或返回临时错误,发送者回退到mx2.example.com。

如果不存在MX记录,发送者回退到域的A或AAAA记录——但这是最后的手段。如果存在显式Null MX记录(0 .),域不接受邮件。有关完整算法,请参见DNS和邮件路由。

第2步:TCP连接和横幅

发送者打开MX主机25端口的TCP连接。接收服务器先以220横幅响应:

# 服务器先说话
220 mx1.example.com ESMTP ready

220状态代码表示"服务就绪"。如果服务器超负荷,可能会响应421(服务不可用)并关闭连接。发送者应稍后重试。

对于消息提交(用户的邮件客户端通过其提供商发送),连接改为去往587端口(RFC 6409)或465端口(隐式TLS,RFC 8314)而不是25端口。

第3步:EHLO——宣布功能

发送者使用EHLO(扩展HELO)引入自己,提供自己的主机名。服务器响应其支持的扩展:

EHLO sender.mailertogo.com
250-mx1.example.com Hello sender.mailertogo.com
250-SIZE 52428800
250-8BITMIME
250-STARTTLS
250-AUTH PLAIN LOGIN
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 SMTPUTF8

每条250-行公布一个扩展。最后一行使用250 (空格,不是破折号)表示结束。关键扩展:

旧版HELO命令(没有"E")完全跳过扩展。在当今实践中几乎从不使用。

第4步:STARTTLS——升级到加密

如果服务器公布了STARTTLS,发送者发出命令以升级连接:

STARTTLS
220 2.0.0 Ready to start TLS
# TLS握手发生在此处
# 连接现已加密
# 发送者必须在加密通道上再次EHLO
EHLO sender.mailertogo.com
250-mx1.example.com Hello sender.mailertogo.com
250-SIZE 52428800
250 ENHANCEDSTATUSCODES

STARTTLS后,发送者必须再次发送EHLO。服务器可能在加密连接上公布不同的扩展(例如,AUTH通常仅在建立TLS后才公布)。

在465端口,TLS是隐式的——连接从第一个字节开始加密,无需STARTTLS步骤。

没有TLS,整个SMTP对话——包括密码和消息内容——以明文发送。现代最佳实践是始终使用TLS。有关强制TLS的机制,请参见MTA-STS和DANE。

第5步:AUTH——认证(仅提交)

当邮件客户端通过587端口提交消息时,它使用SMTP AUTH进行认证(RFC 4954):

AUTH PLAIN AGFsaWNlQGV4YW1wbGUuY29tAHMzY3IzdA==
235 2.7.0 Authentication successful

Base64字符串编码\0username\0password。这就是为什么TLS至关重要——没有它,凭据以明文传输。

服务器间在25端口的投递不使用AUTH。相反,接收服务器依靠发送者的IP地址、SPF记录、DKIM签名和其他认证机制来验证消息。请参见电子邮件认证说明。

第6步:信封——MAIL FROM和RCPT TO

信封与消息头分开。它告诉接收服务器谁在发送消息以及谁应接收消息:

MAIL FROM:<alice@example.com> SIZE=1024
250 2.1.0 OK
RCPT TO:<bob@example.net>
250 2.1.5 OK
RCPT TO:<carol@example.net>
250 2.1.5 OK

关键细节:

每条命令获得个别响应。250表示已接受。RCPT TO上的550表示邮箱不存在。452表示服务器暂时无法接受该收件人。发送者必须单独处理每个响应——某些收件人可能被接受,而其他的被拒绝。

第7步:DATA——发送消息

DATA命令开始消息传输:

DATA
354 Start mail input; end with <CRLF>.<CRLF>
From: Alice <alice@example.com>
To: Bob <bob@example.net>
Subject: Meeting tomorrow
Date: Tue, 11 Mar 2026 10:30:00 -0400
Message-ID: <abc123@example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8

Hi Bob,

Are we still on for 2pm?

- Alice
.
250 2.0.0 OK: queued as 4F3A21C8

消息包括头和正文,由空行分隔。消息由只包含单个句点(.)的行终止——"点转义"约定。消息正文中任何以句点开头的行在传输时前置一个额外的句点,在接收时被剥离。

DATA后的250响应意味着消息已被接受投递。它不意味着消息已被投递到收件人的邮箱。接收服务器可能在内容过滤期间仍会拒绝它,或稍后生成退回。

队列ID(例如4F3A21C8)对调试非常宝贵。记录它。

第8步:QUIT

QUIT
221 2.0.0 Bye

发送者关闭会话。TCP连接被拆除。如果发送者有更多消息要发往同一服务器,它可以发出另一个MAIL FROM而不是QUIT来重用连接。

SMTP响应代码

每个SMTP响应以三位数代码开头。第一位数字告诉你类别:

代码 含义 操作
2xx 成功 命令完成;继续
3xx 中间 服务器等待更多数据(例如DATA后)
4xx 临时失败 稍后重试。服务器在后续尝试中可能接受消息
5xx 永久失败 不重试。消息将永远不会被原样接受

你会遇到的常见代码:

使用ENHANCEDSTATUSCODES,服务器附加更具体的代码如5.1.1(坏目标邮箱)。有关完整分解,请参见理解电子邮件退回。

完整事务

以下是从连接到关闭的整个SMTP会话,附有注释:

# 1. TCP连接已建立到mx1.example.net:25
220 mx1.example.net ESMTP Postfix

# 2. 客户端介绍自己
EHLO sender.mailertogo.com
250-mx1.example.net
250-STARTTLS
250-SIZE 26214400
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 8BITMIME

# 3. 升级到TLS
STARTTLS
220 2.0.0 Ready to start TLS
# (TLS握手完成)

# 4. 在加密通道上重新介绍
EHLO sender.mailertogo.com
250-mx1.example.net
250-SIZE 26214400
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 8BITMIME

# 5. 信封
MAIL FROM:<notifications@app.example.com>
250 2.1.0 OK
RCPT TO:<bob@example.net>
250 2.1.5 OK

# 6. 消息内容
DATA
354 End data with <CR><LF>.<CR><LF>
From: App Notifications <notifications@app.example.com>
To: bob@example.net
Subject: Your invoice is ready
Date: Tue, 11 Mar 2026 14:00:00 +0000
Message-ID: <inv-7842@app.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8

Your March invoice is ready. Log in to view it.
.
250 2.0.0 OK: queued as B9C4E1A3F

# 7. 完成
QUIT
221 2.0.0 Bye

提交与中继

SMTP担当两个不同的角色:

开放中继——一个接受任何人向任何人发送邮件的服务器——是电子邮件配置的首要禁忌。垃圾邮件发送者立即利用开放中继。每个现代邮件服务器必须将中继限制在认证用户或已知发送者。

可能出错的事情

连接被拒绝或超时

MX主机已关闭或受防火墙保护。发送者的队列以指数退避重试,循环通过较低优先级的MX记录。重试期后(通常为4-5天),消息退回。

灰名单

接收服务器为未知发送者的第一次尝试返回450。合法服务器重试;垃圾邮件发送者通常不会。你的消息会延迟几分钟,但最终会投递。

在RCPT TO处被拒绝

550 5.1.1 User unknown响应意味着邮箱不存在。这是一个硬退回。立即从列表中删除该地址。

在DATA处被拒绝

服务器可能接受信封但拒绝内容。常见原因:消息太大、内容被标记为垃圾邮件或认证检查(SPF/DKIM/DMARC)失败。响应在终止句点之后出现。

已接受然后退回

服务器为DATA返回250,但后来生成DSN(退回消息),因为邮箱已满、内容过滤拒绝了它或发生了内部错误。这是最难处理的情况——你只能通过发送到MAIL FROM地址的退回消息才能了解。

TLS失败

如果STARTTLS协商失败,大多数服务器回退到明文。这是安全风险——活跃攻击者可以剥离TLS。MTA-STS和DANE防止此降级。

关键要点

进一步阅读

Related RFCs