企业邮箱 SPF / DKIM / DMARC 配置实战(含 Python 校验脚本)

本文面向企业 IT 管理员和开发者,手把手完成邮件三大认证协议的 DNS 配置,并附带可落地的自动化校验代码。

一、为什么必须配齐这三件套

企业邮箱发出去的邮件,如果收件方(QQ、网易、Gmail)无法验证"这封信确实来自你的域名",就会被直接扔进垃圾箱,甚至被冒名伪造(spoofing)发钓鱼邮件。

  • SPF:声明"哪些 IP/服务器有权以本域名发信",防止伪造发件人。
  • DKIM:给邮件体加数字签名,中途被篡改立即被发现。
  • DMARC:在前两者基础上定义"验证失败怎么办",并回收失败报告,形成闭环。

三者是递进关系:SPF + DKIM 负责"验真",DMARC 负责"处置 + 复盘"。只配 SPF 不配 DMARC,等于装了门禁却没规定陌生人来了怎么处理。


二、SPF 配置

在域名 DNS 控制台添加一条 TXT 记录

字段
主机记录(Host) @ 或留空(根域名)
记录类型 TXT
记录值 v=spf1 include:spf.mxhichina.com -all

不同邮件服务商 include 的域名不同。阿里邮箱(企业版)官方建议的 include 值为 spf.mxhichina.com;如果你同时使用其他发送服务(如阿里云 DirectMail、自建网关),需把它们的 include 也追加进去,例如:
v=spf1 include:spf.mxhichina.com include:dm.aliyun.com -all

注意两个坑:

  1. 一个域名只能有一条 SPF 记录。如果已有 SPF,必须把新内容合并到同一条 TXT 里,不能开两条。
  2. 结尾用 -all(硬失败)比 ~all(软失败)更安全,但迁移期建议先用 ~all 观察,确认无误再改 -all

三、DKIM 配置

DKIM 不是手写字符串,而是由邮件系统生成一对公私钥,你把公钥以 TXT 记录形式发布到 DNS。

阿里邮箱操作步骤

  1. 登录管理员后台 → 组织与账号 → 域名管理 → 选择域名 → 开启 DKIM 签名。
  2. 系统会自动生成一条 TXT 记录,格式类似:
字段
主机记录 default._domainkey(具体以后台显示为准)
记录类型 TXT
记录值 v=DKIM1; k=rsa; p=MIIBIjANBgkqh...(长串公钥)
  1. 把后台给出的完整记录原样复制到 DNS,保存后回到后台点"验证"。

关键提示:selector(主机名里的 default 那段)和公钥 都由后台生成,不要自己编造 p= 的值,否则签名永远校验不过。多域名或多发送通道可能有不同 selector,逐一对着后台填即可。


四、DMARC 配置

最后加一条 DMARC 的 TXT 记录,主机名固定为 _dmarc

字段
主机记录 _dmarc
记录类型 TXT
记录值 v=DMARC1; p=none; rua=mailto:dmarc@你的域名; ruf=mailto:dmarc@你的域名; sp=none; adkim=s; aspf=s

参数含义:

  • p=none:仅监控不拦截(迁移期推荐,先收报告看通过率)。
  • p=quarantine / p=reject:逐步升级为隔离 / 直接拒收。
  • rua / ruf:接收聚合报告 / 失败报告的邮箱,用于后续分析。

建议上线两周、确认 SPF/DKIM 通过率 > 98% 后,再把 p 调到 quarantine 乃至 reject


五、配置后如何验证(命令 + 代码)

1. 命令行快速查

# 查 SPF
dig +short TXT 你的域名
# 查 DMARC
dig +short TXT _dmarc.你的域名
# 查 DKIM(selector 换成你后台的值)
dig +short TXT default._domainkey.你的域名

看到返回里包含 v=spf1v=DMARC1v=DKIM1 即表示记录已生效(DNS 全球生效通常需 10 分钟 ~ 数小时)。

2. Python 自动化巡检脚本

dnspython 定期扫描,把三件套缺失的域名挑出来:

import dns.resolver

DOMAIN = "example.com"
SELECTOR = "default"  # 换成你后台的 DKIM selector

def get_txt(name):
    try:
        answers = dns.resolver.resolve(name, "TXT")
        return " ".join(b.decode() for rdata in answers for b in rdata.strings)
    except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers):
        return ""

def check(domain):
    spf = get_txt(domain)
    dmarc = get_txt(f"_dmarc.{domain}")
    dkim = get_txt(f"{SELECTOR}._domainkey.{domain}")

    report = {
        "SPF":   "OK" if "v=spf1" in spf else "MISSING",
        "DKIM":  "OK" if "v=DKIM1" in dkim else "MISSING",
        "DMARC": "OK" if "v=DMARC1" in dmarc else "MISSING",
    }
    return report

if __name__ == "__main__":
    print(check(DOMAIN))

装上依赖即可运行:pip install dnspython。把它挂在定时任务里,每天扫一遍,三件套有任何一项掉链子都能第一时间告警。


六、上线检查清单

  • 根域名仅有一条 SPF TXT,且已含所有发送源 include
  • DKIM 后台已开启并通过验证
  • DMARC 的 _dmarc 记录已添加,rua 收件箱能正常收信
  • 用真实账号对外发一封测试信,到 https://www.mail-tester.com 打分(目标 ≥ 9/10)
  • 观察 DMARC 报告两周,通过率达标后再收紧 p 策略

小结

SPF 声明身份、DKIM 保证完整、DMARC 兜底处置——三者配齐,企业邮件进箱率和防伪造能力会有质的提升。配置本身不复杂,难点在于"合并 SPF 不重复"“DKIM 用后台生成的真实公钥”"DMARC 先监控后拦截"这三点。按上面的步骤和脚本逐项落地即可。

实战建议:配置完成别急着调 reject,先用 p=none 跑两周收集 DMARC 报告,确认无误再升级策略,能避开绝大多数"误杀正常邮件"的翻车现场。

本文为技术实操分享,具体 DNS 字段请以你所使用邮件服务商后台的实际生成为准。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐