HTML在浏览器中看起来不错,但在电子邮

时间:2017-05-05 15:41:59

标签: c# html email utf-8 mimekit

我在使用电子邮件编码方面遇到了一些麻烦。我正在从磁盘读取HTML文件并通过Gmail发送。当我在浏览器中打开HTML时,它看起来很棒。当我从Visual Studio复制HTML字符串并将其保存为HTML文件时,它看起来很棒。当我收到电子邮件时,它包含一堆无效字符。甚至列表子弹也搞砸了!我确定这是一个编码问题,但该文件编码为UTF-8,看起来很好,直到它转换为RAW并通过Gmail发送。

这是一个过程。我们使用OpenXML SDK从docx中读取,然后我们使用HtmlConverter将文档另存为HTML。稍后,HTML将从文件中读入,转换为RAW格式并通过GMail API发送。

以下是一些相关的代码剪辑:

这是我们使用HtmlConverter保存HTML文件的地方。

HtmlConverterSettings settings = new HtmlConverterSettings()
{
    AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }",
    FabricateCssClasses = true,
    RestrictToSupportedLanguages = false,
    RestrictToSupportedNumberingFormats = false,
};

XElement htmlElement = HtmlConverter.ConvertToHtml( wdWordDocument, settings );
var html = new XDocument(
    new XDocumentType( "html", null, null, null ),
    htmlElement );

var htmlString = html.ToString( SaveOptions.DisableFormatting );
File.WriteAllText( destFileName.FullName, htmlString, Encoding.UTF8 );

这是我们阅读存储的HTMl并将其转换为通过Gmail发送的地方。 (我们使用Mimekit进行转换。)

// Create the message using MimeKit/System.Net.Mail.MailMessage
MailMessage msg = new MailMessage();
msg.Subject = strEmailSubject; // Subject
msg.From = new MailAddress( strUserEmail ); // Sender
msg.To.Add( new MailAddress( row.email ) ); // Recipient
msg.BodyEncoding = Encoding.UTF8;
msg.IsBodyHtml = true; 

// We need to loop through our HTML Document and replace the images with a CID so that they will display inline
var vHtmlDoc = new HtmlAgilityPack.HtmlDocument();
vHtmlDoc.Load( row.file ); // Read the body, from HTML file
...
msg.Body = vHtmlDoc.DocumentNode.OuterHtml;

// Convert our System.Net.Mail.MailMessage to RAW with Base64 encoding for Gmail
MimeMessage mimeMessage = MimeMessage.CreateFromMailMessage( msg );

Google.Apis.Gmail.v1.Data.Message message = new Google.Apis.Gmail.v1.Data.Message();
message.Raw = Base64UrlEncode( mimeMessage.ToString() );
var result = vGMailService.Users.Messages.Send( message, "me" ).Execute();

这就是我们base64编码的方式:

private static string Base64UrlEncode( string input )
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes( input );
// Special "url-safe" base64 encode.
return Convert.ToBase64String( inputBytes )
                  .Replace( '+', '-' )
                  .Replace( '/', '_' )
                  .Replace( "=", "" );
}

电子邮件最终为“Content-Type:multipart / mixed”,有两个选项。一个是

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

,另一个是

Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

纯文本和HTML都包含字符串,如= C3 = A2 = E2 = 82 = AC = E2 = 84 = A2表示撇号,HTML部分包含一个HTML标题,其中包含奇怪的“3D”字符

<meta charset=3D"UTF-8"><title></title><meta name=3D"Generator"=
 content=3D"PowerTools for Open XML">

在转换为Base64并发送之前,这些奇怪之处都不在HTML中。

任何想法可能是什么问题?这与UTF8和Mimekit有什么关系吗?

2 个答案:

答案 0 :(得分:0)

你的问题的答案是:没有问题。这就是使用quoted-printable编码呈现Raw的方式。这就是Gmail如果您发送并通过电子邮件发送并查看其来源的方式。

答案 1 :(得分:0)

这就是你的代码应该是什么样子来获得&#34; raw&#34;用于Google的API的消息数据:

using (var stream = new MemoryStream ()) {
    message.WriteTo (stream);

    var buffer = stream.ToArray ();
    var base64 = Convert.ToBase64String (buffer)
        .Replace( '+', '-' )
        .Replace( '/', '_' )
        .Replace( "=", "" );

    message.Raw = base64;
}

正如brandon927指出的那样,text / html mime部分的内容已被引用 - 可打印编码。这是用于传输的MIME编码,以确保它符合7位ascii范围。

您需要对此进行解码才能获得原始HTML。

使用MimeKit,如果您使用mimeMessage.HtmlBody或将表示text / html部分的MimeEntity转换为TextPart并访问Text,则可以使用此功能。 } property。