2017-05-05 4 views
3

Je rencontre des problèmes avec l'encodage des emails. Je lis un fichier HTML à partir du disque et je l'envoie via Gmail. Quand j'ouvre le HTML dans le navigateur, ça a l'air génial. Lorsque je copie la chaîne HTML à partir de Visual Studio et l'enregistre en tant que fichier HTML, il est très bien. Lorsque je reçois l'e-mail, il contient un tas de caractères non valides. Même les balles de la liste sont foiré! Je suis sûr que c'est un problème avec l'encodage, mais le fichier est encodé en UTF-8 et semble bien jusqu'à ce qu'il soit converti en RAW et envoyé via Gmail.HTML semble correct dans le navigateur, mais pas dans l'e-mail

Voici le processus. Nous lisons à partir d'un docx en utilisant le OpenXML SDK puis nous utilisons le HtmlConverter pour enregistrer le document au format HTML. Plus tard, le HTML est lu à partir du fichier, converti au format RAW et envoyé via l'API GMail.

Voici un code correspondant Cisaille:

C'est là que nous sauvons notre fichier HTML en utilisant HtmlConverter.

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); 

C'est ici que nous lisons le HTMl stocké et le convertissons pour l'envoyer via Gmail. (Nous utilisons Mimekit pour la conversion.)

// 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(); 

Et voici comment nous encodage 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("=", ""); 
} 

L'email se termine comme "Content-Type: multipart/mixed" avec deux alternatives. L'un est

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

et l'autre est

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

La fois le texte et le code HTML contiennent des chaînes comme = C3 = A2 = E2 = 82 = AC = E2 = 84 = A2 pour une apostrophe et la partie HTML contient un en-tête HTML contenant des caractères "3D" bizarres.

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

Aucune de ces bizarreries n'était dans le code HTML avant la conversion en base64 et l'envoi.

Des idées ce que le problème pourrait être? Cela a-t-il quelque chose à voir avec UTF8 et Mimekit?

+0

Je ne peux pas répondre à votre question, mais il obtient mon upvote pour l'effort. – adv12

+0

Pourquoi remplacez-vous des parties de votre chaîne Base64? Je ne comprends pas ce que le commentaire «spécial» url-safe «base64 encoder» signifie. – Equalsk

+0

Avez-vous vérifié si la sortie de mimekit vérifie avec RFC 2822? Puisque c'est ce que les docs de l'API GMail disent, c'est nécessaire si vous travaillez avec Raw. –

Répondre

0

C'est ce que votre code devrait ressembler pour obtenir les données de message « brutes » pour une utilisation avec Google de l'API:

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

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

    message.Raw = base64; 
} 

Comme brandon927 a souligné, le contenu de la partie mime text/html a été cité -printable codé. Ceci est un encodage MIME utilisé pour le transport afin de s'assurer qu'il s'intègre dans la gamme 7bit ASCII.

Vous devrez le décoder afin d'obtenir le code HTML d'origine.

Avec MimeKit, cela est fait pour vous si vous utilisez soit mimeMessage.HtmlBody ou si vous lancez le MimeEntity représentant la partie text/html dans un TextPart et accéder à la propriété Text.

+0

Merci beaucoup @jstedfast! J'ai passé des heures là-dessus la semaine dernière. J'ai remplacé la ligne 'message.Raw = Base64UrlEncode (mimeMessage.ToString())' avec votre code et maintenant les emails s'affichent correctement dans Gmail et dans mon client de messagerie. Je n'aurais probablement jamais compris cela. :) – mack

+0

Génial, heureux que cela a fonctionné pour vous :) – jstedfast

0

La réponse à votre question est: il n'y a pas de problème. C'est tout simplement la façon dont Raw est présenté, avec le codage quoted-printable. C'est ainsi que Gmail l'a également présenté si vous l'envoyez et l'envoyez par e-mail et regardez la source de celui-ci.

+0

Merci @ brandon927 Alors, comment pourrais-je faire pour que le texte s'affiche correctement dans l'e-mail? – mack