DKIM签名失败,Mimekit 1.10.1.0和Mailkit 1.10.2.0中的正文哈希未经验证。

4
我在使用Mailkit和Mimekit签署DKIM头部时遇到了一个奇怪的问题,Gmail报告错误"dkim=neutral (body hash did not verify)"。请检查以下代码和实际收到的邮件截图Gmail image 1 headers,我做错什么了吗?
        string ReturnName = "DMC12";
        string FromDomain = "backtothefuture.net";
        string FromEmail = "marty@" + FromDomain;
        string FromName = "Marty McFly";
        string SenderName = "Marty McFly";
        string ToEmail = "George.mcfly.1960@gmail.com";
        string MailServer = "DMC12.large.timemachine.com";
        string TextBody = @"If you put your mind to it, you can accomplish anything. One other thing. If you guys ever have kids, and one of them, when he's eight years old, accidentally sets fire to the living room rug... go easy on him!";
        string HtmlBody = string.Format(@"<b>如果你把你的头脑,它可以完成任何事情。 另一件事。 如果你们有孩子,其中一个,当他八岁时,不小心把火烧在客厅地毯上...去容易对他!</b>");
        string Subject  = "Message from Marty (1960)!";
        string ToName = "George McFly";
        string DKIMdomain = FromDomain;
        string DKIMSigner = "btfreturns.com";         
        string ReturnEmail = "DocBrown@" + MailServer;
        string SenderEmail = "marty@" + MailServer;
        string privatekey = System.IO.File.ReadAllText("dkim.private.key");
        var client = new SmtpClient(new ProtocolLogger("smtp.txt")); // logging SMTP connections

            try
            {
                client.Connect(MailServer, 25);
            }
            catch (SmtpCommandException ex)
            {
                Console.WriteLine("Error trying to connect: {0}", ex.Message);
                Console.WriteLine("\tStatusCode: {0}", ex.StatusCode);
                return;
            }
            catch (SmtpProtocolException ex)
            {
                Console.WriteLine("Protocol error while trying to connect: {0}", ex.Message);
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }   

            client.LocalDomain = MailServer;

            var message = new MimeMessage();
            MailboxAddress RecepientAddress = new MailboxAddress(ToName, ToEmail);

            message.From.Add(new MailboxAddress(FromName, FromEmail)); // From Address
            var builder = new BodyBuilder();

            builder.TextBody = TextBody;
            builder.HtmlBody = HtmlBody;

            List<MailboxAddress> To = new List<MailboxAddress>();
            To.Add(RecepientAddress);

            message.Subject = Subject;
            message.Body = builder.ToMessageBody();
            message.Sender = new MailboxAddress(SenderName, SenderEmail);  // Sender Address
            message.To.Add(RecepientAddress);       
            message.MessageId = Guid.NewGuid().ToString("N") + "@" + new System.Net.Mail.MailAddress(message.Sender.Address).Host;


                using (Stream s = (new MemoryStream(Encoding.UTF8.GetBytes(privatekey ?? ""))))
                {
                    var headersToSign = new[] { HeaderId.From, HeaderId.To, HeaderId.Subject, HeaderId.Date, HeaderId.MessageId };
                    var signer = new DkimSigner(s, DKIMdomain, DKIMSigner);
                    signer.SignatureAlgorithm = DkimSignatureAlgorithm.RsaSha1;
                    message.Sign(signer, headersToSign, DkimCanonicalizationAlgorithm.Relaxed, DkimCanonicalizationAlgorithm.Relaxed);
                }


                client.Send(message, new MailboxAddress(ReturnName, ReturnEmail), To);              
                client.Disconnect(true);
                client.Connect(MailServer, 25);
                client.Dispose();

我想我知道这里的问题所在。在HtmlBody中使用Utf-8字符导致DKIM签名失败,如果我将其替换为标准Ascii字符,则可以正常工作并通过测试。 - Krishnan Venkiteswaran
1个回答

5
问题在于您没有在对消息进行DKIM签名之前调用message.Prepare()。这是非常重要的一步,因为它强制将消息正文中的所有MIME部分编码为适合传输的编码方式。
请注意,如果您不使用适当的编码约束值调用Prepare(),则SmtpClient.Send()方法最终会在您对消息进行DKIM签名之后执行该操作,从而使签名无效。
我的建议是使用EncodingConstraint.SevenBit以实现最大的互操作性。
但是,如果您有信心您的SMTP服务器以及所有其他经过您的消息转移的SMTP服务器都支持8BITMIME扩展,则可以尝试改用EncodingConstraint.EightBit

@jstedfast 这是一篇很重要的文章,应该被包含在文档中。感谢你给出了这么好的答案! - SpoiledTechie.com
在REAMDE文件中 :) - jstedfast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接