ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

邮件服务器发信被拒收?SPF/DKIM/DMARC配置排查全解析

邮件服务器发信被拒收?SPF/DKIM/DMARC配置排查全解析 如果你自建过邮件服务器迟早会撞上这么一堵墙邮件明明发出去了日志里显示250 OK可对方就是收不到。打电话一查退信躺在对方邮件管理员手里上面写着550 5.7.1 Message rejected as spam。第一次遇到这种事的反应基本都是——我的服务器是不是被拉黑了其实大多数情况下不是你的 IP 在黑名单里而是对方邮件网关在“验明正身”环节没验出你的发件身份凭证直接把你的邮件判定成了伪造邮件地址。这个场景凡是跑过 Postfix、Exchange 或任何自建邮件系统的人多少都经历过。今天我想好好聊一聊邮件被拒收这件事背后的完整链路从原理到配置从错误码到实测修复把“自检的邮件服务器发送的邮件可能被拒收”这个现象讲透。这篇文章适合三类人刚把邮件服务器搭起来、正在为发信进垃圾箱发愁的新手公司的邮服运维想彻底搞清楚 SPF、DKIM、DMARC 三者关系的半老手以及单纯想知道“为什么大厂能发进来、我的不行”的普通用户。1. 被拒收的真相邮件网关把你当成了伪冒发件人1.1 你发出的信源头被“信任层”拦住了先说结论自建邮件服务器发信被拒收九成跟垃圾内容无关而是因为接收方无法验证“这封邮件真的是你这个域名发出来的”。邮件系统从诞生那天起就带着一个先天缺陷——SMTP 协议本身不校验发件人身份。你可以在自己的电脑上随便发一封MAIL FROM: ceoexample.com的邮件对方服务器不会阻止你因为 SMTP 是纯文本命令谁都能伪造。为了对抗这种伪造业界在 2000 年后逐步补上了三层认证SPF、DKIM、DMARC。现在主流邮件服务商如 Gmail、Outlook、QQ 邮箱、网易、腾讯企业邮都会对入站邮件执行这三层检查。问题就出在这里很多自建服务器只配置了基础的 SMTP 收发没有同步发布 SPF 记录、没有配置 DKIM 签名、也没有 DMARC 策略。于是当邮件到达 Gmail 或 Outlook 的网关时网关发现“这个域名声称它发了信但没有任何凭证能证明”RFC 里的默认逻辑就是按伪造处理——直接拒收或者扔进垃圾箱。这不是偶尔抽风是每天都在发生的事情。我见过不止一个公司的业务邮件被 QQ 邮箱拒收用户反馈“你们是不是没给我发”结果后台日志显示对方服务器返回554 5.7.1 Retry was not successful原因就是 SPF fail。1.2 “伪造邮件地址”在技术上是如何被定义的我们先从报文层面理解伪造。一封邮件有两个发件人概念一个是信封发件人MAIL FROM指令里的 Return-Path一个是信头发件人From:头字段。普通用户看到的是后者而邮件网关检查的是前者与域名的匹配关系。SPF 检查的是信封发件人。流程是这样的对方邮件服务器收到你的邮件后会查你域名在 DNS 里的 TXT 记录如果写着“允许 IP 1.2.3.4 发送本域名的邮件”而你这封邮件的来源 IP 恰好是 1.2.3.4SPF 就 pass如果不是那就是 fail。DKIM 检查的则是邮件头部是否带着一个用私钥签名过的DKIM-Signature字段对方通过 DNS 找到你的公钥来验签能验过说明这封信确实经过了你的服务器。这个机制补上了 SMTP 的漏洞但也把“身份凭证没配齐”的自建服务器推向了对立面。你以为自己在正常发信但在对方网关眼里你和他见过的那些垃圾邮件群发 bot 没有任何区别——都在用别人没有授权的域名发信。所以后续所有拦截手段都合理了。搞清楚这一点后续配置才有方向不是去跟对方网关注册什么白名单而是把自己的“身份凭证”补齐。1.3 常见被误判的三种情况我总结下来自建邮件服务器被判定为伪造的典型情况就三种整个域名没有任何 SPF 记录。接收方查不到 TXT 记录直接按 fail 处理。这是最普遍也最致命的问题。有 SPF 记录但漏了发信源的 IP 或子域名。比如公司网站用第三方营销邮件服务发送newsexample.comSPF 里只列了自建服务器的 IP漏了营销平台的那段 IP对方一查就是 fail。DKIM 签名配置了但 DNS 里没有发布公钥或选择器selector对不上。签名无效等于没签照样 fail。下面几个章节我从最基础也最关键的 SPF 开始逐一讲清楚每条记录怎么写、为什么这么写、以及我踩过的坑。2. SPF用一条 TXT 记录圈定“谁有权替你发信”的边界2.1 SPF 语法拆解一条记录里到底写了什么SPFSender Policy Framework本质是一条 DNS TXT 记录普通得不能再普通但它的内容决定了所有接收方对你的第一印象。典型的记录长这样vspf1 mx ip4:203.0.113.10 include:_spf.example.net -all我们来拆解一下vspf1声明这是一条 SPF 记录版本号必须是这个。mx允许 MX 记录指向的服务器作为发件源。如果你的域名的邮件收发都走同一台服务器这个机制很实用。ip4:203.0.113.10直接指定一个 IPv4 地址段作为合法来源。支持ip4:1.2.3.4/24这样的 CIDR 写法。include:_spf.example.net把另一个域名的 SPF 记录完整包含进来。如果你用了第三方邮件平台通常会用它提供的这条 include。-all兜底规则。意思是“除了上面列的其余全部判定为失败”。这是最严格也最推荐的方式。与-all相对的是~all软失败标记为可疑但不直接拒收和all全部通过千万不能这么写等于敞开大门。2.2 写 SPF 最容易翻的车少了发件源我见过最典型的翻车场景是公司有主邮件服务器跑在阿里云 ECS 上SPF 里只写了vspf1 ip4:ECS_IP -all。看起来没问题但后来市场部接了一个线索管理工具用这个工具以公司域名给客户发跟进邮件结果大量退信。退信原因就是 SPF fail——线索工具的服务器 IP 不在允许列表里。这种情况要么让市场工具改用自有域名子域名比如marketing.example.com要么在 SPF 里加上对应的include段。很多第三方发送工具都有自己的 SPF 配置说明页你要做的是打开工具的帮助文档把它的 include 段复制进自己的 SPF。这里最需要注意的是每次新增发信源都去更新 SPF并且发布后用工具检查一遍否则“发不出去”的锅永远甩给你。还有一个容易忽略的点邮件服务器常常会用本机 hostname 所在域名发 HELLO 命令但实际发件域名又是另一个。SPF 只关心信封域名Return-Path 的域名和 From 头域名无关。如果你用noreplyexample.com发信但服务器的 MX 记录和 hostname 都在mail.example.net只要 SPF 里没有授权 mail.example.net 的 IP照样失败。2.3 SPF 的有效性判断结果当接收方完成 SPF 检查后会得到一个结果常见的有结果含义接收方通常的处理pass来源 IP 匹配身份验证通过正常投递fail来源 IP 未被授权明显伪冒拒收或垃圾箱softfail~all场景不能确定但可疑可能需要额外分析neutral记录存在但没说明是否允许继续其他检查temperrorDNS 临时故障查不到记录通常会继续检查可能延迟permerrorSPF 记录语法错误按 fail 处理我的建议是先用dig TXT example.com看看自己的 SPF 记录是否真实存在、语法是否正确。很多自建邮服的问题就出在“根本没人写过这条记录”。2.4 实操用 dig 验证并发布 SPF发布 SPF 不复杂在 DNS 管理后台给域名加一条 TXT 记录主机记录填或留空取决于面板记录值填vspf1 mx ip4:你的IP -allTTL 可以是 300 或 600等 DNS 生效后用dig确认dig TXT example.com short输出里应该出现你的记录。接着可以再用nslookup -typeTXT example.com复核。这里有一个容易踩的坑有些域名注册商的 DNS 面板会自动把 TXT 记录加引号你复制的时候要确保不要把多余的引号或空格带进去否则语法解析会出问题。SPF 记录的总长度不能超过 255 字符如果 include 太多超过限制DNS 会因为无法完整解析而导致 SPF permerror。如果你用了多家第三方发信平台建议尽量让它们改用子域名发送而不是把所有 include 全塞进主域名的 SPF。3. DKIM把“防伪签章”贴进邮件头部3.1 DKIM 的工作过程和它解决的本质问题SPF 解决的是“从哪个服务器发出的”它有一个天然的短板如果发件域名和服务器 IP 都是被允许的SPF 只能证明服务器有发送权不能证明送达过程中邮件内容没有被篡改。你需要 DKIM。DKIMDomainKeys Identified Mail的原理和电子合同签章很像发件服务器用私钥对邮件内容包括正文和关键头部做哈希签名生成一个DKIM-Signature字段附加在邮件头部。接收方收到邮件后通过 DNS 查询到发件域名的公钥对签名进行验签。如果验签通过不仅证明邮件确实来源于该域名授权的服务器还说明内容在传输过程中没有被改动。对自建邮件服务器来说DKIM 是花费最少、收益最明显的一项配置只要密钥对生成好、DNS 记录发布好、服务器签名功能打开绝大多数主流邮箱就能判定为 pass。3.2 手把手用 OpenDKIM 生成和配置签名以最常见的 Postfix OpenDKIM 组合为例步骤如下安装 OpenDKIMapt install opendkim opendkim-tools生成密钥对。这里需要先规划一个选择器selector它是 DNS 记录里的一个名称标识“用哪套公钥验证我的签名”。我习惯用域名年份方式比如defaultmkdir -p /etc/opendkim/keys/example.com cd /etc/opendkim/keys/example.com opendkim-genkey -s default -d example.com -b 2048-b 2048指密钥长度。以前大家用 1024 位现在建议至少 2048 位部分大厂已经开始拒绝验证 1024 位的 DKIM 签名。生成完毕后目录里会有两个文件default.private私钥和default.txt公钥用于发布到 DNS。私钥文件权限要收紧chown opendkim:opendkim /etc/opendkim/keys/example.com/default.private chmod 600 /etc/opendkim/keys/example.com/default.private配置 opendkim.conf把例子里注释掉的KeyTable、SigningTable、InternalHosts路径指向你的配置目录。然后在/etc/opendkim/signing.table写上* example.com default:example.com:/etc/opendkim/keys/example.com/default.private这样所有来自本服务器的邮件都会用 example.com 的密钥签名。重启服务再在 Postfix 主配置文件里挂上 miltersmtpd_milters inet:localhost:8891 non_smtpd_milters inet:localhost:8891 milter_default_action accept需要确认你的 opendkim 监听端口和 socket 类型默认是inet:8891或local:/var/run/opendkim/opendkim.sock配置要一致。3.3 DNS 侧的公钥发布与常见错误下一步是发布公钥。打开default.txt你会看到类似这样的内容default._domainkey IN TXT vDKIM1; krsa; pMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC...在 DNS 管理后台添加一条 TXT 记录主机名填default._domainkey记录值填引号里的全部内容去掉最后一段反引号。注意这个记录名里有一个下划线不要漏掉。DNS 生效后验证dig TXT default._domainkey.example.com short接下来很容易翻车的地方有三个选择器不一致签名时代理用的 selector 是defaultDNS 查询必须是default._domainkey.example.com。很多人在 DNS 台上不会填结果配成了example.com._domainkey.default.example.com查询不到公钥验签必然失败。TXT 记录长度超出限制2048 位密钥的公钥字符串很长DNS 系统会把长 TXT 记录自动拆成多段复制的时候要确保粘贴完整最好把引号里的内容整体拷贝不要只复制第一段。DNS 缓存新发布的 DKIM 记录可能过几个小时才在全球生效。验证完马上发信测有可能查不到别急着改配置。3.4 验证签名是否生效看邮件头配置完签名后发一封测试邮件给一个你能查看原始邮件头的邮箱Gmail 可以QQ 邮箱也可以。在 Gmail 里打开邮件点击“显示原文”在邮件头里找Authentication-Results行dkimpass header.iexample.com header.sdefault header.bxxxxdkimpass就是验证通过。如果显示dkimfail或dkimneutral优先检查的是记名选择器、公钥发布是否完整以及服务器时间是否准确——DKIM 验签对时间戳比较敏感服务器时间偏差超过五分钟就会出问题。4. DMARC告诉对方收到可疑邮件时怎么处理4.1 DMARC 的定位策略层的一句话SPF 和 DKIM 分别从“来源 IP”和“签名验签”两个维度证明身份但接收方拿到的结果是两个孤立的 pass/fail 信号。它还需要一个决策层告诉它如果两个都失败该怎么处理是放行、扔垃圾箱、还是直接拒收这个决策层就是 DMARCDomain-based Message Authentication, Reporting Conformance。DMARC 通过 DNS 里的 TXT 记录发布一套策略。它还有一个关键概念叫对齐alignment不仅要求 SPF/DKIM 通过还要求通过后对应的域名和用户看到的From:头域名一致。防止你用一个合法域名的 SPF 来发送另一个域名的邮件。DMARC 记录典型结构vDMARC1; pquarantine; ruamailto:dmarcexample.com; pct100; adkims; aspfs逐项解释p策略。none只观察不处理quarantine有疑问的邮件进垃圾箱reject直接拒收。刚开始上线建议用none观察一段时间再收紧。rua接收汇总报告XML 格式的邮箱定期收到来自各大邮件服务商的认证数据。ruf接收失败报告forensic report的邮箱会收到具体某封邮件为什么失败。pct策略应用比例100表示全部邮件都执行策略。adkim、aspf对齐模式。sstrict要求完全一致rrelaxed允许子域名差异。多数场景用r更省心。4.2 上线 DMARC 的正确姿势先观察再收紧我给所有自建邮件服务器的建议都是不要一上来就写preject。虽然reject的防护最强但如果你自己的 SPF 或 DKIM 还有没覆盖到的场景比如某个老系统走了第三方 SMTP、某个外包的客户关系管理系统用自己的服务器发信reject会直接把这些邮件的投递路径切断。推荐分三步走第 1~2 周pnone。通过rua收报告看看真实流量里有百分之多少的邮件没有通过 SPF/DKIM。报告可以用dmarcian或者postmark的 DMARC 报告解析工具来看不用自己解析 XML。第 3~4 周pquarantine。让失败邮件进垃圾箱观察有没有用户抱怨“正常邮件不见了”。如果有回头补 SPF/DKIM 配置。一个月后preject。确认所有合法发信都能通过认证后才能把策略拉满。这个过程我走过了无数次。基本上一个大坑是某部门用了子域名发信但父域名的 DMARC 只写了preject子域名的aspfr情况下可能还能放宽但很多运维不区分直接把子域名的合法信也拒了。建议及时查看rua报告里 report 中的 hostname 和 source ip能帮你定位具体是哪个发信源在失败。4.3 子域名的 DMARC 覆盖规则一个容易忽略的知识点DMARC 对子域名有继承策略。如果example.com写了一条preject理论上mail.example.com、newsletter.example.com等子域名如果没有自己的 DMARC 记录会继承父域名的策略。这导致很多公司的主域名配置收紧后子域名的合法邮件也跟着遭殃。解决办法是在子域名单独发布更宽松的 DMARC 记录比如先把子域名的p设为nonevDMARC1; pnone; ruamailto:dmarcexample.com或者干脆用sp标签subdomain policy单独声明子域名策略父域名记录里写spreject; pnone意思是主域名收紧、子域名单独执行别的策略。这个小标签每次我看配置清单都会重点核对一遍因为它藏得最深。5. PTR 与 HELO 主机名IP 声誉的最后一块拼图5.1 反向 DNSPTR为什么会影响拒收说完三大认证还有一个经常被人忽略、却直接影响拒收概率的环节PTR 记录也就是反向 DNS。接收方邮件服务器在完成 SPF/DKIM/DMARC 检查后还会对你的来源 IP 做一次反向解析拿着你的 IP 去 DNS 里查PTR记录得到你的反向域名然后正向解析这个反向域名看它是否解析回同一个 IP。为什么这很重要因为垃圾邮件群发器几乎不会给服务器 IP 配 PTR 记录。如果你有一个干净的 IP 和正确的 PTR接收方会认为你是“正规经营的邮件服务商”反之没有 PTR 或 PTR 和服务器 HELO 主机名不匹配很可能直接被多家邮件服务商列入低信誉池连前面辛苦配置的 SPF/DKIM 都来不及起作用。我在真实排障时遇到过一个典型案例自建邮服发出的邮件在 Gmail 那边偶尔正常、偶尔进垃圾箱查了半天没找到原因最后用nslookup -typePTR 你的IP一看反向记录指向的域名是一个云服务商默认生成的、和他毫无关系的域名。差得不是一星半点。让机房加上一条 PTR之后进垃圾箱的概率大幅下降。5.2 HELO/EHLO 主机名必须和 PTR 对齐SMTP 会话时你的服务器会在 EHLO 里向对方报一个主机名。这个主机名必须是合法的、和 PTR 记录一致的域名不能是裸 IP。比如 PTR 是mail.example.com那 EHLO 就必须是mail.example.com。对应到 Postfix 配置myhostname mail.example.com smtp_helo_name mail.example.com如果你用mail.example.com做服务器名和 PTR但发件信封域名是example.com也没有关系——SPF 检查的是信封域名PTR 检查的是服务器 IP 和主机名两者不是同一个东西。只要各自都配置正确链路就能通过。很多自建服务器默认的 myhostname 是类似localhost.localdomain或裸 IP这就是典型的“身份线索缺失”。你连自己叫什么都没说清楚对方凭什么信任你检查一下 Postfix 的myhostname别让它用默认值。5.3 IP 纯度和信誉的冷知识选择自建邮服用的 IP 时也建议做一下 IP 历史信誉检查。你可以用senderscore.org或者各大服务商提供的工具查 IP 信誉。新买的云服务器 IP 往往是“二手”的之前可能被别人用来发过垃圾邮件历史信誉就差。即使你所有技术配置都完美接收方依然会根据 IP 历史记录降低对你的信任等级。有一个对自己发件很友好的做法尽量让邮服使用独立的、干净的 IP而不是和公司其他业务网站共享同一个 IP。很多第三方营销平台也会建议用户用独立 IP因为共享 IP 里只要有人信誉差全池都会被牵连。6. 从退信错误码到完整修复一次典型拒收的排查链路6.1 拒收错误码的解读550 5.7.1 与 554 的差别自建邮服的拒收最终会以退信或日志错误的形式反馈到你这里。读懂错误码是排障的第一步。550 5.7.1 Message rejected as spam最常见通常代表 SPF/DKIM/DMARC 有一项或多项 fail。Gmail 和 Outlook 尤其喜欢用这个错误码。554 5.7.1 Retry was not successful含义比较宽泛可以直接对应到 SPF fail 或 DMARC reject。很多网关会在邮件正文里附加具体原因要连着上下文一起看。421 4.7.0临时性拒绝可能是 IP 信誉或频率限制过段时间再试可能就成功。451 4.3.2服务器内部繁忙或 DNS 查询超时多数是对方问题但也有可能是你发送频率过高。拿到错误码后第一件事是去翻邮件头的Authentication-Results。这行记录是对方服务器对你的认证判断的“直接口供”。比如Authentication-Results: mx.google.com; spffail (google.com: domain of no-replyexample.com does not designate 198.51.100.2 as permitted sender) smtp.mailfromno-replyexample.com; dkimpass header.iexample.com; dmarcfail (pNONE spNONE disNONE) header.fromexample.com这个信息量已经很大了SPF fail 了DKIM pass 了DMARC 最终 fail因为 SPF fail 且未对齐。你要修复的目标很明确把 SPF 里的 IP 198.51.100.2 加进去或者调整对齐方式。6.2 用 mail-tester 做一次全链路体检排查最有效率的方式是借助在线工具。www.mail-tester.com是我用过最顺手的免费工具——它会给你一个临时测试邮箱地址你用自建邮服给那个地址发一封测试邮件它会在页面上呈现出 SPF、DKIM、DMARC、PTR、黑名单、邮件头规范度等一系列评分。每一项都会有明确解释“为什么扣分”“该怎么改”。我一般把它当成发布配置后的“验收标准”。每次改完 SPF、DKIM 或 DMARC都发一封测试邮件看评分。从 4 分提高到 9 分以上才意味着你的邮件基本可以被主流邮箱正常接收。得分低于 6 分时优先去看看“黑名单”那一项如果 IP 被列入几个常用的公开黑名单再完美的认证配置也会大打折扣。mail-tester的页面下方还会列出具体的邮件头我习惯直接对比它显示的Authentication-Results和自己预期是否一致能快速定位是 DNS 没生效还是签名没挂上。6.3 一个完整的排障案例从退信到落地的每一步我拿一个典型的公司场景完整走一遍流程你可以直接对号入座。背景客户新买了台云服务器自建 Postfix发往公司主邮箱大约 30% 邮件进入垃圾箱有时直接退信。错误码是550 5.7.1 Message rejected as spam。排查步骤在服务器本机查看日志tail -f /var/log/mail.log发现投递过程中对方返回554 5.7.1说明被网关拦截。用dig TXT example.com short查 SPF发现根本没有 SPF 记录。这是第一个问题。查 DKIMdig TXT default._domainkey.example.com short返回空说明即便服务器上配置了 OpenDKIM公钥也没有发布到 DNS。查 PTRdig -x 云服务器IP short得到的是一个无关域名显然是机房默认生成的。需要联系云服务商提交反向解析工单把 PTR 改成mail.example.com。修复发布 SPF 记录vspf1 mx ip4:云服务器IP -all生成 DKIM 密钥并发布公钥补上 DMARCvDMARC1; pnone先观察提交 PTR 工单。再次测试用mail-tester复测第 1 项 SPF pass第 2 项 DKIM pass第 3 项 DMARC pass总分从 3.5 提到 9.8。退回的比率直接清零。修完之后你会发现之前层层叠叠的“发不出去”“进垃圾箱”问题往往都被这几个基础配置一揽子解决。自建邮件服务器不是一个“搭起来就能用”的软件它是一个需要持续维护和验证身份的系统工程。6.4 踩过坑后的几条实操清单最后分享几条我每次为新邮服上线都会走一遍的检查清单算是给自己留的规矩先查 SPF 再配置别的。没有 SPF 记录后面都白搭。SPF 里务必包含所有发信源的 IP/域名。DKIM 选择器统一登记。把各域名的 selector 和 DNS 记录主机名整理成表格避免配错或忘记发布。DMARC 必须和 SPF/DKIM 一起更新。DMARC 的策略生效前提是前两项认证都已经稳定 pass否则很容易误伤。PTR 工单要提前提。很多云厂商自动生成的反向解析记录不满足要求人工改通常要 1~2 个工作日别等被拒收才去申请。日志一定要开 verbose。Postfix 的投递日志是排查拒收的第一手材料配合mail-tester的邮件头分析基本五分钟就能定位问题。还有一点值得单独强调邮件服务器的认证不是“配一次就永久有效”。你的include可能过期、第三方平台的 SPF 段可能变更、DKIM 私钥可能过期——至少每季度自查一次 DNS 记录用mail-tester发一封测试邮件看评分趋势能省掉很多临时救火的时间。自建邮件服务器这条路技术栈其实不复杂真正复杂的反而是这些看不见的“身份细节”。我见过太多人花大力气调反垃圾策略、加内容过滤最后发现问题居然只是自家 SPF 写少了 IP。先从伪造邮件地址的视角重新审视自己的服务器你会少走很多弯路。
返回列表