ARTICLE · 邮件服务

一封邮件是怎么从发件箱到收件箱的:投递原理与垃圾邮件判定

投递不是「点发送、然后到达」这一件事,而是一条有七段的链路:提交、认证、排队、DNS 查 MX、连接传输、过滤分类、落盘取信。每一段失败的表现方式都不一样——有的立刻报错,有的延后重试,有的干脆静默丢弃。本文逐段讲机制,再给出「现象 → 该查哪一段」的对照表。

2026-08-12 16IDC 原创

一封邮件是怎么从发件箱到收件箱的:投递原理与垃圾邮件判定

「我发的邮件为什么进了对方的垃圾箱?」这个问题之所以反复出现,是因为大多数人对邮件系统的心理模型只有一个动作:点发送,然后等待结果。真实过程是一条有多个环节的链路,任何一个环节出问题,看到的症状都不一样。

更麻烦的是,这些症状的可见程度差别极大。有的环节失败会立刻弹出一串错误码,有的会在几分钟后给一封退信,有的会让邮件永远停在「发送中」,还有的——也是最常见的——什么都不会告诉你,邮件安安静静地消失了。

本文把这条链路拆成七段,逐段讲机制而不是只列名词:每一段在做什么、正常情况下怎么走完、失败时你看到的是什么。然后把「信封与信头」这两套经常被混淆的发件人身份讲清,再说收件方的反垃圾系统究竟在看哪些信号,最后给出一张从现象反查环节的对照表。

读完之后,你应该能对一个具体的问题给出定位方向,而不是笼统地归因为「邮件有问题」。域名侧的域名解析基础见 域名 DNS 记录基础,发信服务器的参数细节见 SMTP 配置指南,而决定「你的域名有没有资格发信」的那套认证机制见 SPF/DKIM/DMARC 配置。

一、投递是一条七段链路

1.1 第一段:撰写与提交

第一段发生在你的邮件客户端和它所属的提交服务器之间。你在客户端里点发送,客户端并不直接把邮件投给对方的服务器,而是先交给一个「提交服务器」——通常是你的邮箱服务商,或者是你在用的邮件发送平台。

这一段用的协议严格说不叫 SMTP 传输,而是 SMTP 的提交用法:客户端要先通过身份验证(用户名密码、应用专用密码、OAuth 令牌),服务器确认「这个账号确实有权用我的服务发信」之后,才接收这封信。端口一般是 587(配合 STARTTLS 升级加密)或 465(直接 TLS)。

这一段已经埋下了很多后续问题的种子。客户端提交时写入的 From 头、Message-ID、Date,就是后面所有判定所依据的原始材料;如果客户端把 From 写成了一个服务器不认识、也没被授权的域,那么后面无论怎么补救都无法让收件方认账。自建发信时这一段最常见的问题是把它和「收件」混为一谈:以为配好了收件(IMAP/POP)就能发信,实际上两套东西的账号体系、端口、认证方式都是分开的。

另一个容易被忽略的细节是编码。中文主题、日文正文、emoji 都需要正确编码(通常是 UTF-8 + quoted-printable 或 base64),客户端一般会自动处理,但用脚本或旧库自己拼邮件时,编码错误会让主题在收件方显示成乱码,而乱码本身就会被反垃圾系统当成可疑特征。

1.2 第二段:提交认证与限额

服务器在接收你这封信之前会做一组检查,这一组检查失败的表现是「立即报错」——通常是客户端直接弹出错误,邮件没有离开你的账号。

检查大致包括四类。第一类是身份与授权:你的账号是否有效、是否被限制发信、是否触发了风控。第二类是发件人校验:很多服务商要求你提交时所用的 From 域必须是自己已经验证过的域名,否则拒收。这是防止平台被拿去伪造他人身份的第一道闸。第三类是限额:日发送量、每小时发送量、单封收件人数上限、附件大小上限。第四类是内容策略:有些平台会直接拒绝明显违规的附件类型。

限额这一项对业务系统的影响最大,也最容易被误判。你可能会看到「发送失败:超出每日配额」,而业务侧的解读是「邮件系统坏了」。真实原因往往是某段代码在循环里重复触发通知,把配额打满了。所以这一段失败时,第一件事不是去查 DNS,而是去查发信方的日志和配额用量。

值得强调的是:这一段是整条链路上唯一「失败一定会被明确告知」的一段。如果你已经收到了明确的错误,问题几乎一定出在这里,不必再往下查。

1.3 第三段:队列、重试与退避

这是全篇最重要的一段,因为它解释了为什么「发送成功」不等于「已送达」。

提交服务器接收邮件之后,并不会立刻完成投递。它把邮件放进自己的发送队列,然后由队列管理器去尝试连接收件方的服务器。这个设计的原因是网络和对方服务都不可靠:对方服务器可能正在重启、可能限流、可能暂时拒收。所以投递是异步的,队列里的每封信都有一个状态。

失败时队列会重试,而且不是死循环式地狂试,而是按退避策略拉长间隔。典型做法是前几次间隔几分钟,之后拉长到几十分钟、几小时,最多持续数十小时——各家策略不同,但方向一致:给对方的临时故障留出恢复窗口。超过重试窗口仍失败,才会生成退信通知,把信退回给你。

这就产生了一个非常常见的认知错位:发送平台显示「已发送」(accepted),只表示它收下了信并负责投递,不表示对方收下了。平台的事件体系里,这个状态通常叫 accepted 或 queued;真正的「已投递」(delivered)是另一个独立事件,可能要几秒后才出现,也可能永远不出现。

所以正确的看法是:队列把「你的动作」和「投递结果」在时间上分开了。 你在后台看到的成功是动作的成功,不是结果的成功。要判断结果,必须看投递事件,而不是看发送动作的返回值。事件与日志层面的观测方法见 送达率监控工具。

二、找到收件方:DNS 与连接

2.1 第四段:DNS 查询与 MX 记录

队列要投递一封信,第一步是知道往哪台机器投。它取出收件地址里 @ 后面的域名,向 DNS 查询这个域名的 MX 记录(Mail Exchanger,邮件交换记录)。MX 记录按优先级排列,队列会从优先级最高的那台开始尝试。

这一段有三个结局,区别很大。

成功解析:拿到目标主机名,进入下一段。注意 MX 记录指向的通常是主机名而不是 IP,还需要再解析一次地址,这一步的失败同样致命。

没有 MX 记录:绝大多数发信方的处理是「回退到该域名的 A 记录」,也就是把信投给这个域名的网页服务器所在的地址。如果那里没有监听邮件的服务,连接就会失败,最终退信。

域名不存在(NXDOMAIN):直接终结,立即退信。这类退信是硬退信,因为它不会因为重试而变好——域名本身就没注册,或者拼错了。

这一段常被忽略的实际影响是:域名过期或 DNS 服务商欠费,会让「收件」先于「网站」崩溃。网站打不开可能只是证书问题,但 MX 消失意味着所有发给这个域的信都进不来,而发信方只会给寄件人一个硬退信,你自己完全看不到。这也是为什么域名续费与 DNS 托管要被当成运维事故等级处理,而不是账单问题。

2.2 第五段:连接与 SMTP 传输

拿到目标主机的地址后,发信方要建立一条到对方 25 端口的 TCP 连接,然后开始 SMTP 会话。会话本身是一个很朴素的问答:先说自己是哪台机器(HELO/EHLO),然后声明信封发件人(MAIL FROM),声明收件人(RCPT TO),确认可以开始了(DATA),把信头与正文写进去,最后用单独一行 . 结束并等待答复。

这个过程中,对方的服务器有多次机会拒收:可以在 MAIL FROM 之后拒(通常是你的 IP 或域名信誉太差),可以在 RCPT TO 之后拒(通常是收件人不存在或拒收规则命中),也可以在 DATA 之后拒(内容被判定为垃圾)。三种拒绝的业务含义完全不同,日志里看到的位置就是线索。

这一段还有一个现代互联网的结构性障碍:很多云主机和家庭宽带默认不能对外连接 25 端口。 云厂商这么做是出于反滥用考虑——如果允许任意云主机直连 25 端口,垃圾邮件发送者会立刻把这里当成最便宜的跳板。结果是你在云主机上跑一个自建 SMTP 去投递外域,连接会超时或被直接拒,而且日志里往往只看到「连接超时」,看不出原因。

这也是为什么要发业务邮件时,最省事的方案是走专业发信服务(由服务商替你完成这一段),而不是在服务器上自己搭 SMTP。相关平台的功能差异见 SendGrid 与 Mailgun 配置指南。如果确实需要自建,去申请解封出口 25 端口是可行路径,但要接受服务商的审核,而且出口 IP 的信誉历史仍然需要自己从零经营。

三、收件方那一侧:过滤、落盘与取信

3.1 第六段:反垃圾过滤与分类

信到了对方服务器,才进入真正决定「进收件箱还是进垃圾箱」的阶段。这一段的关键特征是:它的判定结果通常不会告诉你。

过滤系统会综合多路信号打分:发件人的 IP 与域信誉、SPF/DKIM/DMARC 的认证结果与对齐情况、内容里的可疑特征(链接与文本比例、图片与文本比例、可疑词、短链)、发信模式(同一 IP 短时间内的发送量与收件人分布)、以及历史上收件人对这个发件人的行为。综合出一个分数后落到三档处理:放行到收件箱、放入垃圾箱、直接丢弃。

第三档就是所谓静默丢弃。对发件方来说它的表现与「已送达」完全一样:SMTP 会话在 DATA 之后可能返回了接受(有些系统为了不给垃圾发送者反馈信号,会故意先说接受再丢弃),队列认为投递完成,事件里显示 delivered,收件人却从来没有见过这封信。

所以判断「到底送到了没有」时,平台事件里的 delivered 也只是对方服务器的说法,不是用户的确认。想知道真实结果,唯一的办法是让用户真的去看——或者用聚合报告、发件人信誉面板这类间接证据推断整体趋势。分类判定的机制细讲见下一章。

3.2 第七段:投递到收件箱与取信

最后一公里发生在收件方内部:过滤器放行后,邮件交给 MDA(邮件投递代理),由它把邮件写入该用户的邮箱存储——在传统架构里这是一个邮箱文件或目录,在现代架构里是数据库或对象存储里的一条记录。这一步会检查用户邮箱是否超额、是否有转发规则、是否有自动回复、是否命中了用户的个人黑名单。

这一段失败的症状是「软退信」:邮箱已满、超出配额、暂时无法投递。这类错误会触发重试,用户清理了空间之后邮件可能还是会进来,所以软退信不等于这封信丢了。但如果一直不清理,重试窗口走完就变成硬退信。

邮件落盘之后,用户如何看到它取决于取信协议。IMAP 把邮件留在服务器上,客户端只同步状态,多设备看到的是同一份数据,已读与移动到文件夹都会同步回服务器;POP3 则是把邮件下载到本地并从服务器删除,适合同一个账号只在一台设备上用的场景。

这个分工对排障有实际意义:如果用户的客户端用 POP3 并且设置了「下载后删除」,那么你在服务器上找不到那封信,并不代表它没到过——它可能已经进了用户的本地邮件夹。判断「信到没到」要在服务器侧的证据(日志、邮箱存储)和客户端侧的证据(本地邮件夹)之间对齐,而不是只问用户「你收到了吗」。

四、信封与信头:两套发件人身份

4.1 Return-Path 与 From 的分工

一封邮件里存在两个「发件人」,它们不是一回事,而且协议允许它们不同。这是绝大多数邮件认证困惑的源头。

信封发件人写在 SMTP 会话的 MAIL FROM 里,收件方会把它记录成 Return-Path 头。它决定两件事:退信退给谁,以及 SPF 校验比对哪个域。它是运输层的概念,用户在收件箱里看不到它。

信头发件人写在 From 头里,这是用户在邮件列表里看到的那个名字和地址。它决定用户认为这封信是谁发的,也是 DKIM 的 d= 域通常要对齐的对象。

所以正确的理解是:SPF 校验的是信封,用户看到的是信头。 一个域名可以在 SPF 上完全合规地通过(因为信封域是自己授权的),而 From 头写的却是别人的品牌——这就是最常见的冒充形态。DMARC 之所以要把两者放在一起比,就是为了堵住这个缺口。

实务上,用第三方平台发信时,Return-Path 往往落在平台给你的一个子域上(用于收集退信),而 From 是你自己的域。这种配置下 SPF 通过、DKIM 通过,但 SPF 侧不与 From 对齐——DMARC 要么靠 DKIM 对齐通过,要么失败。理解这个分工,才看得懂报表里那些 spf=pass 但 dmarc=fail 的行。

4.2 Received 头链的读法

Received 头是唯一能还原真实投递路径的证据。每经过一台服务器,那台服务器就在信头最上方加一条 Received,记下自己是谁、从谁那里收的、用了什么协议、什么时间。

因此读法是:从下往上读。 最下面那条是离发信方最近的一跳,最上面那条是离收件方最近的一跳,也就是最后一台处理它的服务器。顺序读反了,会把发信源当成收件源,结论完全颠倒。

每条 Received 里的时间是排查的关键:相邻两条之间的时间差如果是几分钟,说明中间有排队或重试;如果是几小时,说明对方在退避重试;如果某条的时间明显早于其他(时钟不同步),那一跳的服务器可能有配置问题。

同样重要的是 Authentication-Results 头:它由收件方写入,记录这台服务器对 SPF、DKIM、DMARC 各自给出的判定。看到一封信的判定是 dmarc=fail,再配合 Received 链,就能判断是发信源的配置问题,还是中间某一段的转发破坏了签名。诊断方法与常见退信码的对应关系见 邮件退信原因分析。

五、反垃圾系统到底在看什么

5.1 发件人信誉:IP 与域的历史

信誉是权重最高的单项,也是新域新 IP 最吃亏的地方。收件方会分别维护 IP 信誉和域名信誉,两者互相参考。

IP 信誉看的是这个地址(或这个地址段)长期以来的发送行为:发送量是否稳定、退信率多高、有没有被用户点过「举报垃圾邮件」、是否出现在公共黑名单里。共享 IP 的问题在于你无法控制同 IP 上其他人在做什么;专属 IP 的问题在于你要自己从零积累历史,前期一旦发坏量,恢复很慢。

域名信誉看的是域名的年龄、认证配置是否完整稳定、发送量曲线是否平滑、投诉率是否长期处于低位。这解释了为什么「新域名第一天就发一万封」近乎必然失败:它在所有信誉维度上都是零,而发送量却是高分贝异常。

信誉是滚动更新的,向上爬需要时间,向下掉只要一次事故。所以运营上最重要的不是「怎么快速提升信誉」,而是「怎么不让它掉」——这是冷邮件与新域预热必须单独设计的原因,相关策略见 冷启动邮件发送策略。

5.2 认证结果、内容特征与投诉历史

认证结果的权重仅次于信誉,但它有一个特殊性质:它只区分「你是谁」和「不确定你是谁」,不区分「你是好是坏」。 通过认证不能保证进收件箱,但认证失败几乎一定会扣分。这也是为什么配齐 SPF/DKIM/DMARC 是必要条件而不是充分条件。规范层面的最新演进可参考 DMARC 规范更新。

内容特征是大家最熟悉、权重却常被高估的一类:可疑词、全大写的主题、过多的感叹号、图片占比过高而文字过少、链接域名与发件域不一致、短链跳转、附件类型异常。这些特征单独看都不致命,叠加起来才会触发拦截。

投诉历史是一项硬指标。用户点一次「举报垃圾邮件」,就是一次显式的负面投票,其影响远大于「不打开」。多数发信平台把投诉率千分之一量级当成警戒线,超过就要停下来查来源——不是查内容,是查名单:为什么这些人会收到这封信。

5.3 用户行为信号

这一项是很多人不知道、但权重很高的因子。

收件方能看到用户对每封信的处置:打开、点击、回复、加星标、移到收件箱、移入垃圾箱、举报、删除不读。从这些动作可以反推出「这个发件人对这个用户有没有价值」,而这比任何内容分析都准。回复和加星标是最强的正向信号,移到收件箱是明确的「分类错了」的纠正信号;长期不打开、直接删除则是缓慢的负向累积。

它带来的实践结论很直接:名单质量比内容质量更重要。 发给一批根本不想看的人,即使内容写得再好,也只会在行为信号上累积负分,最后拖累整批发送。反过来,一个小而活跃的名单,能把域名信誉稳稳托住。

这也解释了为什么「重新激活沉睡用户」的活动总是风险很高:沉睡用户的共同特征就是长期不互动,对他们做一次大规模发送,等于主动制造一批负向信号。稳妥做法是先小批量试探,只对其中仍有打开行为的人继续,而不是把整段沉睡名单一次推出去。名单的分层与清理方法见 邮件送达率优化。

六、三处最常见的误解

6.1 以为 SMTP 返回 250 就是送达了

250 是一个 SMTP 状态码,含义是「这一步我接受了」。但接受发生在会话的不同阶段,含义完全不同:对 RCPT TO 返回 250 只表示「这个收件人我收下了」;对 DATA 结尾返回 250 只表示「这封信我收下了,后面我会处理」。它不表示过滤已经通过,不表示已经落盘,更不表示用户会在收件箱里看到它。

更微妙的是,某些系统会故意对疑似垃圾返回 250 然后丢弃,目的是不给发送者反馈信号、避免对方不断试探规则。所以把 250 当成送达凭证,等于把「对方收下了信封」当成「对方读了信」。

正确的做法是以投递事件与后续反馈为准:看平台事件里的 delivered、bounce、complaint 分布,看聚合报告里的通过率,看用户真实打开与回复。协议层与业务层的证据要分开看。

6.2 以为进垃圾箱一定是内容问题

内容当然会触发拦截,但在真实故障里,内容问题的占比远低于身份与信誉问题。遇到「进垃圾箱」,排查顺序应该是:认证是否齐全且对齐 → 发信 IP 与域的信誉是否有异常 → 名单来源与投诉率是否正常 → 最后才是内容。

顺序反了会浪费大量时间:你会一遍遍改文案、换主题、删图片,而真正的问题是 DMARC 没对齐或者某个 IP 段被拉黑了。识别方法是看不同收件域的差异:如果所有收件方都进垃圾箱,多半是身份或信誉问题;如果只有某一家进,多半是那家的规则或名单问题;如果只有某个批次进,多半是那批名单或那段时间的发信模式问题。

6.3 以为换个 IP 就能解决一切

换 IP 在特定场景下确实有效——比如你用的是共享 IP,而同 IP 上有别人在大规模滥发,你被连累。这种情况下换到干净的 IP 能立刻改善。

但在更多场景下,换 IP 只会让问题更糟。新 IP 没有信誉历史,收件方对它的默认态度是保守的;如果你在问题还没定位清楚的时候就换,等于把「有历史但被污染」换成「完全没有历史」,同时丢掉了原来可用于诊断的数据。

更重要的是,信誉的主体不只是 IP,还有域名。如果问题是域名信誉(比如投诉率长期偏高、或域名本身在某份名单里),换 IP 不会有任何改善。判断依据是看报表里失败是按 IP 聚集还是按域名聚集——这一步不做就换,属于赌博。

七、现象与排查路径

7.1 现象 → 该查哪一段

把前面几段串起来,可以做成一张反向索引。遇到具体问题时先定位环节,再查该环节的细节,比盲目试错快得多。

现象 最可能出问题的环节 首要检查项
客户端立刻弹错误,信没发出去 第一、二段:提交与认证 账号权限、配额、From 域是否已验证
平台显示已发送,但一直没有后续事件 第三段:队列 队列是否有积压、是否在退避重试
收到「域名不存在」「无此收件人」类退信 第四段:DNS MX 记录、收件地址拼写
连接超时、连接被拒 第五段:连接 出口 25 端口是否被限制、对方是否限流
平台显示 delivered,收件人说没收到 第六段:过滤 认证对齐、IP 与域信誉、垃圾箱
收到「邮箱已满」类退信 第七段:落盘 收件方配额、是否持续重试
报表里 spf=pass 但 dmarc=fail 信封与信头 Return-Path 域是否与 From 域对齐

这张表的价值不在于穷尽,而在于建立「症状—环节」的映射习惯:症状的形态本身就在告密。立即报错说明还停在提交阶段;延后很久才失败说明经过了队列的退避;完全不报错说明问题出在不反馈的那一段。

7.2 排查顺序与日常监控

按固定顺序走,能避免在错误的方向上浪费时间。第一步查发信侧日志:有没有被拒、有没有配额问题、事件状态分布如何。第二步查认证:SPF、DKIM、DMARC 三条记录是否还在、是否对齐、选择器有没有失效。第三步查退信与投诉的分布:按收件域、按发信 IP、按批次分组看,异常通常集中在某一组。第四步再查内容与名单。

日常监控要盯的是趋势而不是单点:退信率、投诉率、进箱率的移动平均,比某一天的数字更有意义。发信量的突变、新增的陌生发信源、某个收件域突然全部失败,这三类信号出现时就该介入。

最后记住一条:这条链路上唯一不会主动告诉你的环节,恰恰是最常出问题的那一环。所以「没收到退信」从来不是「已经送达」的证据,只是「没有任何一方觉得有必要通知你」。要真正的可见性,只能自己把观测搭起来——协议层看认证结果,业务层看投递事件与用户行为。完整的发信 API 接入方式与事件模型见 事务邮件 API 接入指南。

来源:16IDC 原创,文中涉及的协议规范、客户端行为与平台能力以 IETF RFC 及相关服务商官方文档为准。

原文来源:16IDC 原创 ↗