使用c#邮件消息发送MHT文件

本文关键字:MHT 文件 消息 使用 | 更新日期: 2023-09-27 18:16:23

有没有人得到任何示例代码发送MHT使用SmtpClient和MailMessage在c#中?

我发现了使用替代视图的诱人参考,但我不知道如何使用我的SSRS生成的MHT。

如果任何人有任何工作代码,他们愿意分享,我将非常感激。

使用c#邮件消息发送MHT文件

所以看起来。net MailMessage不支持开箱即用。我发现了一些方法,它们可以获得不同程度的成功。

MHTML -> HTML解码器

David Benko写了https://github.com/DavidBenko/MHTML-to-HTML-Decoding-in-C-Sharp/blob/master/MHTMLParser.cs,虽然它有效,但当我查看结果电子邮件时,我无法使图像出现。HTML看起来是正确的,只是在Outlook 2010中不工作。

将MimeKit MimeMessage转换为。net邮件消息

杰弗里指出,这是一个开始https://github.com/jstedfast/MimeKit/issues/140。我又遇到了图像没有显示在结果消息中的问题。

使用MimeKit &MailKit

我最终使用https://github.com/jstedfast/MimeKit来完成这项工作。这可以通过以下方式实现:

   MimeMessage messageMimeKit = MimeMessage.Load(Request.MapPath("~/Blah/378921.mht"));
   messageMimeKit.From.Add(new MailboxAddress("Dev", "developer@gmail.com"));
   messageMimeKit.To.Add(new MailboxAddress("Homer", "homer@gmail.com"));
   messageMimeKit.Subject = "Another subject line";
   using (var client = new MailKit.Net.Smtp.SmtpClient()) 
   {
      client.Connect("smtp.gmail.com", 465, true);
      client.Authenticate("homer@gmail.com", "*****");
      client.Send(messageMimeKit);
      client.Disconnect(true);
   }

Using System.Net.Http.Formatting

我的方法利用了System.Net.Http.Formatting库中HttpContent上的ReadAsMultipartAsync扩展方法。(microsoft . asp.net . webapi . client nuget包的一部分)

唯一棘手的一点是从文件中获取正确的内容类型。为了使ReadAsMultipartAsync方法工作,它需要将流内容的ContentType头设置为正确的类型("multipart/related"),包括内容类型值的正确边界参数:

multipart/related;
    boundary="----=_NextPart_01C35DB7.4B204430"

请注意,由于我的解决方案仅用于发送以MTHML格式导出的SSRS报告中的内容,因此我的代码假设多部分内容只有一个文本/html部分,其余部分为图像,但是该技术是合理的,可以调整为以更通用的方式处理多部分内容。

const string ContentTypePrefix = "Content-Type: ";
AlternateView htmlView = null;
var linkedResources = new List<LinkedResource>();
var content = File.ReadAllText("report.mhtml");
var startIndex = content.IndexOf(ContentTypePrefix, StringComparison.OrdinalIgnoreCase) + ContentTypePrefix.Length;
var endIndex = content.IndexOf("'"", startIndex, StringComparison.Ordinal) + 1;
var contentType = content.Substring(startIndex, endIndex);
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
    using (var stream = new StreamContent(memoryStream))
    {
        stream.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);
        if (!stream.IsMimeMultipartContent())
        {
            throw new Exception("Not correct format.");
        }
        var parts = stream.ReadAsMultipartAsync().ConfigureAwait(false).GetAwaiter().GetResult();
        foreach (var part in parts.Contents)
        {
            part.Headers.ContentType.CharSet = part.Headers.ContentType.CharSet?.Replace("'"", string.Empty); // Needed since the SSRS report defaults the charset to '"utf-8'", instead of utf-8 and the code fails to find the correct encoder
            var compressedContent = part.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
            if (!part.Headers.ContentType.MediaType.Contains("image"))
            {
                var encoding = Encoding.GetEncoding(part.Headers.ContentType.CharSet);
                var partContent = encoding.GetString(Convert.FromBase64String(compressedContent));
                htmlView = AlternateView.CreateAlternateViewFromString(partContent, encoding, part.Headers.ContentType.MediaType);
            }
            else
            {
                linkedResources.Add(new LinkedResource(new MemoryStream(Convert.FromBase64String(compressedContent)), part.Headers.ContentType.MediaType)
                {
                    ContentId = part.Headers.ContentDisposition.FileName.Replace("'"", string.Empty)
                });
            }
        }
    }
}
foreach (var linkedResource in linkedResources)
{
    htmlView?.LinkedResources.Add(linkedResource);
}
using (var message = new MailMessage("from@mail.com", "to@mail.com", "Subject", string.Empty))
{
    message.BodyEncoding = Encoding.UTF8;
    message.AlternateViews.Add(htmlView);
    using (var client = new SmtpClient("smtpserver.com", 25))
    {
        client.Send(message);
    }
}