Node.js发送邮件至mail-tester.com出现‘Your message is not signed with DKIM’错误的解决求助
解决DKIM未签名问题的核心思路与步骤
首先得纠正一个关键误区:Let's Encrypt生成的证书是用于SMTP TLS加密的,和DKIM签名完全是两码事。你之前用它的私钥生成公钥配置DKIM记录,这根本不对——DKIM需要一套独立的RSA密钥对,和TLS证书无关。下面一步步帮你解决:
1. 生成专属的DKIM密钥对
别再用Let's Encrypt的密钥了,重新生成专门用于DKIM的RSA密钥对:
- 生成私钥:
openssl genrsa -out dkim_private.pem 2048 - 从私钥导出公钥(用于域名DNS配置):
之后把公钥文件里的内容(去掉openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----,合并成一行)放到域名的DKIM TXT记录里,格式保持v=DKIM1;k=rsa;p=你的公钥内容,注意p后面不要有换行。
2. 在Node.js邮件发送流程中添加DKIM签名
你之前的代码只做了TLS加密,完全没有添加DKIM签名的逻辑——这就是mail-tester提示“未签名”的直接原因。推荐用mailauth库来处理DKIM签名,比自己实现简单太多:
安装依赖
npm install mailauth
修改你的邮件内容生成逻辑
在ConvertForSMTP函数里(或者生成邮件原始内容后),添加DKIM签名步骤。举个适配你现有代码的例子:
const { DKIMSigner } = require('mailauth'); const fs = require('fs'); // 加载DKIM私钥 const dkimPrivateKey = fs.readFileSync('./dkim_private.pem', 'utf8'); const signer = new DKIMSigner({ domain: 'hailmail.co.uk', // 你的域名 selector: 'default', // 你的DKIM记录的selector(比如配置的是default._domainkey.hailmail.co.uk,这里就填default) privateKey: dkimPrivateKey, }); function ConvertForSMTP(from, to, subject, body) { // 先构建基础邮件内容 const rawEmail = [ `From: ${from}`, `To: ${to}`, `Subject: ${subject}`, `MIME-Version: 1.0`, `Content-Type: text/plain; charset=utf-8`, '', body ].join('\r\n'); // 添加DKIM签名 const signedEmail = signer.sign(rawEmail); return { data: signedEmail.split('\r\n'), // 适配你原来的逐行发送逻辑 mailFrom: `MAIL FROM:<${from}>`, mailTo: `RCPT TO:<${to}>`, commandData: 'DATA', commandQuit: 'QUIT' }; }
3. 验证配置是否正确
- 先确认域名的DKIM记录已经生效:可以用
nslookup工具检查selector._domainkey.yourdomain.com的TXT记录是否和你配置的一致。 - 重新发送测试邮件到mail-tester,之后查看检测结果——如果配置正确,DKIM签名会显示为通过。
额外提醒
- 你之前的TLS配置是对的(用Let's Encrypt证书做STARTTLS),这个和DKIM是互补的安全措施,不用改动。
- 如果不想用第三方库,手动实现DKIM签名需要严格遵循RFC 6376规范,处理签名算法、header选择、哈希计算等细节,非常繁琐,所以还是推荐用成熟的库。
内容的提问来源于stack exchange,提问作者Cribe
相关产品推荐
相关产品推荐

