
自建邮件服务器最容易栽跟头的地方不是装 Postfix,而是装好之后发出去的邮件全部进 Gmail 垃圾箱。原因几乎都一样:SPF、DKIM、DMARC 三件套没配齐,或者配齐了但没对齐。本文教你如何在一台 Linux 服务器上把这三道防线都跑通,覆盖 DNS 记录写法、OpenDKIM 落地、Postfix milter 串联、对齐排查与最终的发信验证流程,帮助你把发件信誉从零拉到主流邮箱都能直送收件箱。下面默认你已经能登上服务器、对 DNS 控制台有改记录的权限,对 Postfix 有最基本的认知,不需要你之前真正运营过邮件服务。
三件套各自管什么
很多人把 SPF、DKIM、DMARC 当成同一件事,实际上它们分工很清楚。SPF 告诉收件方”哪些 IP 可以代表我这个域名发信”,靠 DNS 的 TXT 记录声明;DKIM 给每封邮件加一个用私钥签的 header,收件方用 DNS 里挂的公钥验签,证明邮件没被中途篡改;DMARC 则是策略与汇报层,告诉收件方”如果 SPF 或 DKIM 失败该怎么处理”,并要求 From 域必须与 SPF 或 DKIM 通过的域对齐。
理解这层关系很重要:SPF 与 DKIM 各自通过还不够,DMARC 还要求至少一项与 From 头部域名对齐,才算真正放行。这就是为什么很多人 SPF 显示 pass、DKIM 显示 pass,DMARC 却 fail——通常是 SPF 验的是 Return-Path 域、DKIM 签的是别的子域,From 又是主域,对不上号。先把这个心智模型建好,后面的命令才不至于抓瞎。
DNS 记录怎么写
假设主域是 example.com,邮件服务器 IP 是 203.0.113.10。先准备好下面三条记录:
example.com. IN TXT "v=spf1 ip4:203.0.113.10 ~all"
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0G..."
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; adkim=s; aspf=s; pct=100"
几个关键点:SPF 末尾用 ~all 软失败比 -all 硬失败更友好,上线初期不容易误伤合作方,等监控稳定再收紧;DKIM 的 selector 这里叫 mail,可以自定义,建议带年份方便轮换,例如 m2026;DMARC 的 p= 建议从 none 起步只收报告不拦截,跑两周确认没误伤再升到 quarantine,最后才是 p=reject。adkim=s 与 aspf=s 是严格对齐,要求子域完全一致,初期可以先用 r 放宽。
在 Postfix 上落地 DKIM 签名
SPF 与 DMARC 是 DNS 端的工作,DKIM 必须在邮件传输代理上做签名动作,最常用的方案是把 OpenDKIM 作为邮件过滤器挂到 Postfix 上。安装与基础配置如下:
apt install opendkim opendkim-tools
mkdir -p /etc/opendkim/keys/example.com
opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s mail -v
chown -R opendkim:opendkim /etc/opendkim/keys
生成的 mail.txt 里就是要发布到 DNS 的公钥,取出 p= 后面的字符串贴进上一节的 TXT 记录即可。然后在 /etc/opendkim.conf 里指定 socket、KeyTable、SigningTable,再在 /etc/postfix/main.cf 末尾追加:
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:127.0.0.1:8891
重启两个服务后,从本机发一封测试邮件到自己的 Gmail,查看原始邮件头,应该能看到 DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=mail; ... 这一行,并且 Gmail 显示 dkim=pass。
对齐与验证
走到这里最容易卡的不是签名本身,而是对齐。检查清单可以这样跑:先用 dig +short TXT example.com 看 SPF 是否生效,注意一个域上同时存在两条 SPF TXT 会导致整条失效;再用 dig +short TXT mail._domainkey.example.com 确认公钥已下发,长记录注意是否被 DNS 控制台切成多段引号;本地用 opendkim-testkey -d example.com -s mail -vvv 验签,输出 key OK 才算双向通;最后发一封到 mail-tester.com 或 check-auth@verifier.port25.com,能看到三项的逐项判定,分数到 9 分以上才算合格。如果 DMARC 提示 from-alignment 失败,多半是 Return-Path 用了 mailgun、sendgrid 之类的中转域,要么改 aspf=r 放宽对齐,要么在中转方添加自定义返回路径,把 5321.MailFrom 调成自己的域。
与上游服务器、网络层的协同
邮件链路除了软件本身,跑在哪台机器上同样重要。要稳定发信,服务器的 IP 反向解析必须能解回域名,否则 Gmail 直接判进垃圾箱。如果你的部署环境是境外服务器,IP 信誉与地理位置都会影响通过率,可以参考 美国 VPS(虚拟专用服务器)部署教程 评估机房与初始 IP 的可用性。Web 业务和邮件业务最好分机器跑,前面的 Web 入口套上 Nginx 反向代理与负载均衡 也不会影响邮件的 25 端口出站,互不干扰。
服务器开放 25、465、587 端口意味着扫描压力比纯 Web 站点大很多,SSH 加固这一步省不得,建议参照 SSH 与 Fail2ban 加固指南 把暴力破解挡在外面。日常面向国内用户的 webmail 入口想要更稳定的连接体验,可以叠加一层 CDN(内容分发网络),例如 Cloudflare CDN 中国加速,但要注意 CDN 只服务 web 流量,邮件 25 端口不能也不应该走 CDN。如果业务恰好跑在 WordPress 站点上发通知邮件,前端缓存配置可以参考 WordPress 与 W3 Total Cache 调优 的思路,避免发信脚本被缓存层意外拦截。
常见踩坑
SPF 同一个域名挂了两条 TXT 是最经典的坑,结果整条 SPF 失效,必须把多条合并成一条记录才能恢复。DKIM 公钥贴到 DNS 控制台时容易被自动加上引号或截断,粘贴前先把换行去掉,再用 dig 反查一次确认完整。OpenDKIM 启动后 Postfix 卡在邮件队列里,多半是 socket 权限不对,把 postfix 用户加进 opendkim 组就能解决,重启之后队列会自动恢复。用 root 身份手动测试发信,From 默认是 root 加主机名,对齐自然失败,必须改用真实业务账号。DMARC 报告里的 rua 邮箱如果不存在,会导致接收方拒收报告,建议先把这个邮箱真正建好再上 DMARC 记录。
总结
SPF、DKIM、DMARC 三件套不是一次配完就万事大吉,建议把它当成一个持续运营的项目。如果你需要稳定发信,推荐按”DNS 起底 → DKIM 签名落地 → DMARC 监控两周 → 收紧策略”的节奏推进,每一步都用 mail-tester 之类的工具拿到客观分数再前进。可以考虑把 DMARC 的 rua 报告接到一个解析平台,每天扫一眼来源 IP 与对齐失败率,比凭感觉调整稳得多。整套链路走通之后,你会发现邮件能不能进收件箱,归根结底是发信方的工程化能力问题,而不是某家邮箱”故意为难”。