Mailkit/Mimekit七比特编码与点填充问题及DKIM验证失败求助
我之前在使用MailKit/MimeKit实现DKIM时也碰到过类似的坑,刚好能给你一些实际的解决方向。你猜测的点填充(dot-stuffing)问题确实是核心原因——SMTP协议在7位传输模式下,会自动移除行首的单个句号(这是为了避免和SMTP的结束标记..混淆),但如果MimeKit没有正确处理这个逻辑,就会导致原文中的句号丢失,进而让DKIM哈希验证不通过。
下面是具体的解决步骤:
不要手动干预编码和内容处理
很多时候问题出在我们手动把HTML内容转成7位编码,或者强行设置ContentTransferEncoding = ContentEncoding.SevenBit。正确的做法是让MimeKit自动处理编码逻辑:通过BodyBuilder构建邮件内容,它会根据内容自动选择合适的编码,同时正确处理点填充。示例代码:var bodyBuilder = new BodyBuilder(); bodyBuilder.HtmlBody = "<p>你的HTML内容,包含行首的句号比如:.这是一段测试文本</p>"; var message = new MimeMessage(); message.Body = bodyBuilder.ToMessageBody(); // 之后再进行DKIM签名如果必须强制7位编码,让MimeKit处理点填充
如果你因为某些要求必须使用7位编码,不要手动修改内容,而是通过MimeKit的API来设置,它会自动为行首的句号添加额外的点(也就是点填充),确保SMTP传输后内容不会丢失。比如:var textPart = new TextPart("html") { Text = "你的HTML内容", ContentTransferEncoding = ContentEncoding.SevenBit }; // MimeKit会自动处理点填充,不需要你手动在内容里加..验证邮件原始内容
在发送前,可以把邮件保存为.eml文件,查看原始内容是否存在丢失的句号:using (var stream = File.Create("test-email.eml")) { message.WriteTo(stream); }打开这个.eml文件,检查原本应该有句号的位置是否被正确处理(行首的句号应该变成
..,这样SMTP传输后会还原成单个句号)。确保DKIM签名在内容最终确定后执行
DKIM签名是基于邮件的完整内容哈希的,所以一定要在所有内容构建、编码处理完成后再调用签名方法,避免签名后内容又被修改。
按照这个思路调整后,应该就能解决句号丢失和DKIM验证失败的问题了。
内容的提问来源于stack exchange,提问作者Aron

