jstedfast / MimeKit

A .NET MIME creation and parser library with support for S/MIME, PGP, DKIM, TNEF and Unix mbox spools.
http://www.mimekit.net
MIT License
1.81k stars 368 forks source link

DKIM Signature Failing on MimeMessages with HtmlBody instead of TextBody using BodyBuilder (Seven Bit Encoding Set) #935

Closed mtmulch0191 closed 1 year ago

mtmulch0191 commented 1 year ago

Describe the bug When attempting to relay an email through Office 365 using MailKits SMTP Client and constructing a MimeMessage containing an HtmlBody the DKIM validation fails on the recipient side of gmail, yahoo, aol. Switching the HTMLBody to a TextBody allows DKIM validation to pass. I am preparing the message with SevenBit Encoding prior to signing with DKIM and attempted to switch to EightBit encoding and none.

I also attempted to convert the string that is being appended to the HTML Body as ASCII.

Platform (please complete the following information):

To Reproduce Steps to reproduce the behavior:

  1. Construct MimeMessage in the following way using the code snippets below.
  2. Send MimeMessage through Office 365.

Expected behavior I would expect the HTMLBody to pass DKIM validation without extra data being appended to the HTML body causing the validation to fail just like the TextBody.

Code Snippets If applicable, add code snippets to help explain your problem.

Constructing the MimeMessage

        private async Task<MimeMessage> ConstructEmailFromMessagDto(MessageDto messageDto, IFormCollection body, string messageId)
        {
            MimeMessage message = new MimeMessage();
            message.Headers.Add(EmailHeaders.ResoluteMessageId, messageId);
            FacultyEntity userFrom = await this.facultyRepository.FindByUniqueId(this.currentCallContext.UserId);
            message.From.Add(new MailboxAddress("On behalf of " + userFrom.fname + " " + userFrom.lname, "notifications@resoluteera.com"));
            foreach (FacultyDto toUser in messageDto.MessageTo)
            {
                message.To.Add(new MailboxAddress(toUser.fname + " " + toUser.lname, toUser.email));
            }
            foreach (FacultyDto ccUser in messageDto.MessageCc)
            {
                message.Cc.Add(new MailboxAddress(ccUser.fname + " " + ccUser.lname, ccUser.email));
            }
            foreach (FacultyDto bccUser in messageDto.MessageBcc)
            {
                message.Bcc.Add(new MailboxAddress(bccUser.fname + " " + bccUser.lname, bccUser.email));
            }
            message.Subject = messageDto.MessageSubject;
            BodyBuilder bodyBuilder = new BodyBuilder();
            foreach (var file in body.Files)
            {
                using MemoryStream stream = new MemoryStream();
                await file.OpenReadStream().CopyToAsync(stream);
                byte[] attachmentBytes = stream.GetBuffer();
                bodyBuilder.Attachments.Add(file.FileName, attachmentBytes);
            }
            bodyBuilder.HtmlBody = messageDto.MessageBody;
            message.Body = bodyBuilder.ToMessageBody();
            message.Prepare(EncodingConstraint.SevenBit);
            using FileStream stream2 = File.Create(ResoluteKeys.DKIM.BaseDirectory + "\\email.txt");
            message.WriteTo(stream2);
            return message;
        }

Signing with DKIM

private async Task SendDKIMSignedEmail(MessageDto messageDto, IFormCollection body, string messageId)
        {
            using FileStream domainFileStream = new FileStream(ResoluteKeys.DKIM.Domain, FileMode.Open, FileAccess.Read);
            using FileStream selectorFileStream = new FileStream(ResoluteKeys.DKIM.Selector, FileMode.Open, FileAccess.Read);
            using StreamReader domainStreamReader = new StreamReader(domainFileStream);
            using StreamReader selectorStreamReader = new StreamReader(selectorFileStream);
            string domain = await domainStreamReader.ReadToEndAsync();
            string selector = await selectorStreamReader.ReadToEndAsync();
            using MemoryStream privateKeyMemoryStream = new MemoryStream(File.ReadAllBytes(ResoluteKeys.DKIM.PrivateKey));
            DkimSigner signer = new DkimSigner(privateKeyMemoryStream, domain, selector)
            {
                HeaderCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple,
                BodyCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple,
                AgentOrUserIdentifier = "@" + domain,
                QueryMethod = "dns/txt",
            };
            HeaderId[] headers = new HeaderId[] { HeaderId.From, HeaderId.Subject, HeaderId.Date };
            MimeMessage message = await this.ConstructEmailFromMessagDto(messageDto, body, messageId);
            signer.Sign(message, headers);
            EmailSettings emailSettings = await this.GetEmailSettings(this.currentCallContext.InstCode);
            EmailQueueItem queueItem = new EmailQueueItem()
            {
                EmailSettings = emailSettings,
                Message = message,
            };
            this.emailQueue.Add(queueItem);
        }

Additional context Example MimeMessage Written To File System Prior to Being Sent

From: On behalf of ModTester Steenburg <notifications@resoluteera.com>
Date: Fri, 23 Jun 2023 08:14:01 -0400
Subject: Welcome Home
Message-Id: <85A2T4Q2AKU4.7M4AAIXNXTFW@dev115>
X-Resolute-MessageId: 6247b715-9d1b-4c37-a49d-ff892bc8078a
To: ModTester Steenburg <mikemresolute@gmail.com>
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8

Welcome Home

Original Source of Gmail Email

Delivered-To: mikemresolute@gmail.com
Received: by 2002:a05:7001:2f2f:b0:4e7:3a9f:cd92 with SMTP id sa47csp2361487mab;
        Fri, 23 Jun 2023 05:14:11 -0700 (PDT)
X-Google-Smtp-Source: ACHHUZ75A60Dk4Zibc5yiZZ8uUWxUU7r3xX9FrsVSPxfT1rBs0X/5Lv6Opkue82X9i4yRPy5yDrn
X-Received: by 2002:aa7:c1d9:0:b0:51b:c714:a2a1 with SMTP id d25-20020aa7c1d9000000b0051bc714a2a1mr9043735edp.7.1687522451482;
        Fri, 23 Jun 2023 05:14:11 -0700 (PDT)
ARC-Seal: i=2; a=rsa-sha256; t=1687522451; cv=pass;
        d=google.com; s=arc-20160816;
        b=MRNnWUOOObhuNRVdM5y9uxUREsx6XOV2srqve/5hbhmOjUM1yBwWBWn6b6zT41W/o5
         9RBnEKe+RRZZhCabzoeP60o/5yJ4qJcCXSz5DufkAmUyoGU3xo7JpazpKlLzYiRR0AfI
         theuyjWTz3J/ws5Ss1HNzTR9S1pbr2mPQmB2R0yy3XMvGAqxbX8rUicU5Loi46vx4GQK
         hW33roWCnH71Uhx52JQAgh+WthpysdRfUspEyhj5mzBzWUj1khyOVeAtIEgX88iOJoaa
         UOQ41e99vEyjpEZI8bR8Uu7sk+FpgZEw5jFKLQXft/cJ68MohbvPbllyePN6cLv81IFZ
         Aklg==
ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=mime-version:to:message-id:subject:date:from:dkim-signature;
        bh=b0H9XUby1oPMlsaEpq4PTJ+Wu29DIK5+f/tCxi4DHoE=;
        b=IAvZHsz3n9RV2lBQF2fxz6UAPtxL90mHRq2AWfrF5NxqEw/N2ShjO22kArF9uLT7wO
         6jfUjAgYt/vKq2+UQmwtbcQed4qVjb2ULkAeoE11oS+OvFR6PjuQtISEYn6PeCHyYZni
         UXBHpZdhvMCYjfjQmQdxuEBuBIeiGBZfSPgET1SPAWxpKxZvF4R7nLBg3QG3aFNvM95l
         HUupIKH90SP9DsRNjbrvcu8BRypkQvpD2gU1ctN2p+b7lO2sr+koc6oZbKQiHfxuWtBE
         qW+RKqj8vY27tm2iEXdQTw5tN64luHUtwQeZ4YUgmaROzUgNbpcr+IzDGUoVtkLqk1Q7
         7/7w==
ARC-Authentication-Results: i=2; mx.google.com;
       dkim=neutral (body hash did not verify) header.i=@resoluteera.com header.s=1687184081.resoluteera header.b=J34puKJ0;
       arc=pass (i=1 spf=pass spfdomain=resoluteera.com dkim=pass dkdomain=resoluteera.com dmarc=pass fromdomain=resoluteera.com);
       spf=pass (google.com: domain of notifications@resoluteera.com designates 2a01:111:f400:7eab::61b as permitted sender) smtp.mailfrom=notifications@resoluteera.com
Return-Path: <notifications@resoluteera.com>
Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2061b.outbound.protection.outlook.com. [2a01:111:f400:7eab::61b])
        by mx.google.com with ESMTPS id d16-20020aa7d5d0000000b00519da04be13si2758719eds.46.2023.06.23.05.14.11
        for <mikemresolute@gmail.com>
        (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
        Fri, 23 Jun 2023 05:14:11 -0700 (PDT)
Received-SPF: pass (google.com: domain of notifications@resoluteera.com designates 2a01:111:f400:7eab::61b as permitted sender) client-ip=2a01:111:f400:7eab::61b;
Authentication-Results: mx.google.com;
       dkim=neutral (body hash did not verify) header.i=@resoluteera.com header.s=1687184081.resoluteera header.b=J34puKJ0;
       arc=pass (i=1 spf=pass spfdomain=resoluteera.com dkim=pass dkdomain=resoluteera.com dmarc=pass fromdomain=resoluteera.com);
       spf=pass (google.com: domain of notifications@resoluteera.com designates 2a01:111:f400:7eab::61b as permitted sender) smtp.mailfrom=notifications@resoluteera.com
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=k3Lpnjk18T4hyt+OUPB1Yp3rsu+SQ8j/jPri8diWX7PhhaGKpG7MDmZUGQe/Y42TSwjPrkZytSU6uEFGF1yk7nsHi/r1rObuWNTAK5cpw2JOd0YlODc4d/tUGaWaGcVjmMbiE9S8efIMzGqlAWMMrmJfDFYwbShr995RlkwtctwDcjQpL+ClRijq9dgGIItqan903cpAFHs8cpKL8Xm1eNrEbJcAsTMNHYkbxjGQV+mHH7Ko4ipJswnuOSelGVwnNtfqqzz0i18NxTwGcFreMrbKRsOZWx/tgzT7oOIEMoovw2im3zxyV19z0s2kofircyILj8Z+ui1VVV/pvEaBDw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=b0H9XUby1oPMlsaEpq4PTJ+Wu29DIK5+f/tCxi4DHoE=; b=n4dxx3pHLx+fjkemvjSNGD0p4gNBip3uRo4ZlorEs2k31zFtBXTWE+0tEER8I0SQtXfguairPFXRSweQ9uE8surmuclpLbj9evQ2MaiJ/xUv70UFFEdW0ylnyCQxHgqMY3MrD1kIrszbjpoDefMndKxX9zvQW6KFdHD/dFvdOYgq5sSHS05NIDbD38J8sC/4zc5pOsVqHT8t8oHES12jsOMQRjMyr6ZgCZPAu28Bv4vvtVVmUAh6AHYkhRv53GuUc3ovfk6Cd3+8pZ7tGeuvRgPHl6G26HAi4YgF7JBa3FJVXdii8botorWG35yasxMBPSIO4PX78mYhyKLsaDyyOA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=resoluteera.com; dmarc=pass action=none header.from=resoluteera.com; dkim=pass header.d=resoluteera.com; arc=none
Authentication-Results: dkim=error (no key for signature) header.d=none;dmarc=none action=none header.from=resoluteera.com;
Received: from DM6PR13MB4147.namprd13.prod.outlook.com (2603:10b6:5:2a0::11) by MN2PR13MB3760.namprd13.prod.outlook.com (2603:10b6:208:19f::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6521.24; Fri, 23 Jun 2023 12:14:08 +0000
Received: from DM6PR13MB4147.namprd13.prod.outlook.com ([fe80::b6c9:a61f:171f:7c87]) by DM6PR13MB4147.namprd13.prod.outlook.com ([fe80::b6c9:a61f:171f:7c87%2]) with mapi id 15.20.6521.026; Fri, 23 Jun 2023 12:14:07 +0000
DKIM-Signature: v=1; a=rsa-sha256; d=resoluteera.com; s=1687184081.resoluteera; c=simple/simple; q=dns/txt; i=@resoluteera.com; t=1687522444; h=from:subject:date; bh=VkWz0EOs3RV4lO6pLWNXofHzvt/8/CrsP88z4IkXuYA=; b=J34puKJ0hrG1hOmSqRmWDKXHQMvSoXrkger8xO83soglx2/ePmOaugjJzWgNkHReX6pOe2DFpgO scFvQsS4xKYtie9wpcgj7uaqD0NNuGaQ235COWZEVisXtAP6AB6v43l3a89XURUHfdijXfCQWEQ9w iy6sNw5vjINc7USuRZM=
From: On behalf of ModTester Steenburg <notifications@resoluteera.com>
Date: Fri, 23 Jun 2023 08:14:01 -0400
Subject: Welcome Home
Message-Id: <85A2T4Q2AKU4.7M4AAIXNXTFW@dev115>
X-Resolute-MessageId: 6247b715-9d1b-4c37-a49d-ff892bc8078a
To: ModTester Steenburg <mikemresolute@gmail.com>
Content-Type: text/html; charset=utf-8
X-ClientProxiedBy: BN0PR07CA0005.namprd07.prod.outlook.com (2603:10b6:408:141::20) To DM6PR13MB4147.namprd13.prod.outlook.com (2603:10b6:5:2a0::11)
Return-Path: notifications@resoluteera.com
MIME-Version: 1.0
X-MS-PublicTrafficType: Email
X-MS-TrafficTypeDiagnostic: DM6PR13MB4147:EE_|MN2PR13MB3760:EE_
X-MS-Office365-Filtering-Correlation-Id: f9d80f3f-40da-4b2a-19f0-08db73e357f8
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: 2AWIsfn7LpfzhJCy+pqtaD5m5Z7WpuQrIsYpxSi1hVzhlwyrLzMYHkUOi7z2M/R+l3LmukLldw1ihuN574Of8m5bt2fVrTUMxkJjmKDssgREtC7Q43bsXOz4upzpQ7mqEuUoocmRFp/vg0BT2cAEWdshnBRfeE2Ep+FQc8vMUIBItwz2tibpY3HufPwndYsdoYCwAvZM9HMszugmv6UAYQJ3TZYfpW7Yz5s82BrXcOhBNM9jxjFTnUAQ4gL518TJFFf+oVKTpJMKJvoeVNNQLNqLqMX7Aa4wPnZkwpSVBPCRtRVkekukM91mEeiHDLI+ag9SeBeAxc1DUM0ahvOjd5Ci8lDaZcIyzCmoDCsQPxo=
X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR13MB4147.namprd13.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(7916004)(376002)(136003)(39830400003)(346002)(396003)(366004)(451199021)(558084003)(478600001)(33656002)(186003)(9686003)(8936002)(8676002)(6512007)(41300700001)(33716001)(38100700002)(66899021)(316002)(4270600006)(66946007)(66556008)(66476007)(6916009)(6666004)(6506007)(7116003)(5660300002)(6486002)(52116002)(86362001)(2906002)(3480700007);DIR:OUT;SFP:1101;
X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
X-MS-Exchange-AntiSpam-MessageData-0: 5jtyMxfoOLojOrlCAqYOP5xfszZOAUclaulfqbelP4cvzs9KFLuFhbx8NemD9AGDhV0ks83LoR0NZ8Oj0DAKmYIN8nxBENA0BqncUoxxcv56xu+dv9O794AjiMD8oN+8at1NwJslQQkniEW8nBR33EYQ+B3gcGE+Idi3Gx8JGMnRZ416KuvuaJ1jxzoCuCA5uK0rSM/e8OHY7M2K6xf3dRCIISD1OUW7w/zr/sD9g4kv8xW8Sq/3Oc0dX6A5hvdRn9bLZbQY7omQe73ckLLyrfHo+DOw9CEvnuCDZVEoj3xr/ieVZBLF3N70zykJS1NpU67PoF7dGzq/bBnhTgbVXxYdR+KsSmCjzQ7u779vPjGay1KLt9aZaMcW56lJ4xOIPtkcXd+X/+tpZBR6KsbQhG8ZQk+usTs4oST8HRg7kROH2deYdlEMBShSu0OUBos62KuV/L8HcxuBo0sMg9F3uXaGoBiFLAdPELXVdmhboYXYGpTOO1cDAUSloS1lmLrGtcM+IhwaKQU6EBFjZX0vC8buyKVSWq1GgVynau/jKUHTDfBPyqNjgHJYM9B8f88DfXbbX866zUfHzBXHWRHwc8cUcYdwYHD7ZARV/ZBxeW8KTkPoZ3HPSTCRWLBN4V80wj2RQ6oHlBAr+0wj1uGE+W9TmKIGiTOR4j3vjMJerOOqTKQV9mSZ8ob4dH5+js/2W3pMv2yxWb8pgmxzTdXJffx47R95tOqYindrzZTJ5SF2rYrjNtF/BeXLVhGtjLr1re0n4i8MI8QgC1kfsTlJ6mJGZ7apbR2lXe20WeLcnood/weGh+BjLQvp2uQYikJkXbMDY336Z/gYfdhcOn3ORSEsuVSSGjysJgWIVYoMSt/TtfPsuCM+WPNP8AWr0HZpbI9IsAAU3GzL7acHsIB99fVpJvF/AHmT5o/i6WMvHudcPW1A7jba6Qjtl4U2PXUw0yadI3Cy89tCPudpq1ZIuUJA9mIcD8DHT1qTIdlbSJWLjwRr40vEIjRnZnx2mx3ouzCZA4aLj9f/wPX9SMqgYpEMdJDe5R4fEn190Nmu2sly+5vv+Q6SpChqJmaGOdrkxk/lxhsQvbTsasxiln1J3uc7CpvW3gaXiGCICYsAW/oGfWYA0dDei0o8RrILed6AQslXx0JPByV9U1oA3ef/VcoWX6QadqukXMcS75oTHksvHz8OG1Cl/WFeoUUKoN82xfug+ichcHgsEgwyBJkPe+108ph6tG5fikuEB5ar2IPNQz5COmpBULJ3eQ7pGQ991UTJ3R8O/0LHdbfK428mD6ytvuQKJpLC3LdHM5p6eIYiQbA/H00Fxt2fL1jYfbMYavGuz7g//hlZm7TuSjXKo+/3OWBUt5m+So8sUONiHbTNHzr9cjoExDALylznw+nTddIxxwjwesgcy0jcPWs3DXI4DDViUGSESYbn8XINESbil8/CONyWYKff5MsZuGa31LmP2HF2gDB1iVKrHMib9MdRGaPRh8PGr1L7lQXFToQP6f4sTROHOTvJcXTxKA0LqoDRtZA5Z3j0xlEgQO8LRob4wedcoYKCOg366kjNRq2ou8cYgEI+U3qUW+ET/nqZPTdSM1L2ygwFGufy2iVMiFvCudeurMB3ywW5TZOsKos8+qofuCQdyQdRhBkC6IBva+XvMr/ayXLWPX+ORX/3MQ5U7h2m/E0LYF2fR89Zel0=
X-OriginatorOrg: resoluteera.com
X-MS-Exchange-CrossTenant-Network-Message-Id: f9d80f3f-40da-4b2a-19f0-08db73e357f8
X-MS-Exchange-CrossTenant-AuthSource: DM6PR13MB4147.namprd13.prod.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2023 12:14:07.5364 (UTC)
X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
X-MS-Exchange-CrossTenant-Id: 8aaaceb6-3851-4b3d-890e-c954a084e3e8
X-MS-Exchange-CrossTenant-MailboxType: HOSTED
X-MS-Exchange-CrossTenant-UserPrincipalName: uRKVXC15JPptv+Bz21l3H0CCX9BjCVh+Vpf+D4qxmczptQTeHUxd/DKn6ONdsS45xbdx0wqQajhGE9kBnNoN/Nk1mnK6LoXiHHTYvHhC1Ik=
X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR13MB3760

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">Welcome Home
mtmulch0191 commented 1 year ago

So I was able to resolve this DKIM signature issue by appending the following meta tag prior to our string content from the user.

Is meta being appended due to a specification I don't know about that the SMTP server would be expecting?

bodyBuilder.HtmlBody = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" + messageDto.MessageBody;
jstedfast commented 1 year ago

MailKit isn't appending any html tags ever, but based on that, I would say it sounds like an email server somewhere is adding that.

mtmulch0191 commented 1 year ago

Great thanks for the info.