§3 · DKIM
DKIM — DomainKeys Identified Mail。
DKIM (RFC 6376) 为每一封出站消息附加密码学签名。收件方服务器从 DNS 的 TXT 记录拉取您的公钥,针对特定消息头与正文验证签名,数学校验通过即认证消息真实。SPF 说"这个 IP 被允许代表我们发送";DKIM 说"这一封消息的正文与 From 头自签名以来没被篡改"。
机制
- 您生成一对 RSA 密钥对 (最低 1024 位,新部署建议 2048 位)。
- 公钥以 TXT 记录形式发布到 DNS 的
{selector}._domainkey.{yourdomain}。selector 是您挑选的任意字符串 (例如 k1、mail、20251208),用于在不中断在途消息的情况下轮换密钥。
- 私钥留在您的发送服务器上。MTA (或发送中继) 用它给每封出站消息签名,加入一个
DKIM-Signature 头。
- 收件方邮件服务器从签名头读取
d= (域名) 与 s= (selector),查询 {s}._domainkey.{d},拉取公钥并验证。
AcelleMail 中的 DKIM
SendingDomain::generateDkimKeys() 位于 app/Model/SendingDomain.php:221,通过 PHP 的 OpenSSL 绑定生成一对 1024 位 RSA 密钥对,把私钥存到 dkim_private,公钥存到 dkim_public。selector 从模型上的 dkim_selector 读取,若无则回退到全局 dkim_selector 设置。DNS 记录值通过 $this->getDomain()->getDkimDnsRecord() (第 270 行) 渲染,并在"待发布的值"旁附带复制按钮展示给运营者。
密钥生成模式 (来自 generateDkimKeys()):
$config = [
'digest_alg' => 'sha256',
'private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$res = openssl_pkey_new($config);
openssl_pkey_export($res, $privKey);
$pubKey = openssl_pkey_get_details($res)['key'];
验证:$this->getDomain()->verifyDkim() 查询 DNS 的 {selector}._domainkey.{domain},并将已发布的公钥与本地存储的值对比。模型上完整的 verify() 方法 (第 300 行) 在一次调用中编排身份 + DKIM + SPF + DMARC 检查。
厂商托管的 DKIM
如果您通过 Amazon SES、SendGrid、Mailgun 或任何在其侧签名的厂商发送,您发布的是厂商的 selector + 公钥,而不是自己生成。AcelleMail 驱动级的 SignsDkimOnServer 能力 (见 app/SendingServers/Capabilities/SignsDkimOnServer.php) 标记远程处理 DKIM 的驱动;UI 随即显示要发布的厂商 CNAME 记录,而不是生成本地密钥对。SES 使用三条把 _domainkey 委派给 amazonses.com 的 CNAME — 一次设置后,SES 会为您轮换底层密钥。