Search code examples
c#gmaildiacriticsmimekitaccent-sensitive

Mimekit sending accented characters through Gmail


I'm using C# and MimeKit (AE.Net.Mail) to send email through Gmail. Everything works perfectly, until I have an accented name in the body.

I have been unable to figure out how to send the accented characters properly. This is where I am with the code right now. I've tried many dozens of iterations, and so far, nothing works. I've tried encoding in various formats, none of it worked, so I removed all of that for this example. I want to reiterate. The email works perfectly, it's just the accented characters that cause an issue. I know it's related to encoding, but I just can't find the secret sauce to get it to work. (Note, the answer does need to work in all major mail clients)

var msg = new AE.Net.Mail.MailMessage
{
     Subject = "Hello Tést",
     From = new MailAddress("[email protected]"),
     Sender = new MailAddress("[email protected]"),
     Body = "Dear Tést, Thanks",
     ContentType = "text/html",
     Importance = AE.Net.Mail.MailPriority.Normal,
};
msg.ReplyTo.Add("[email protected]");
var mimeMessage = MimeMessage.CreateFromMailMessage(msg);
var result = new GmailService(new BaseClientService.Initializer()
{
       HttpClientInitializer = GetCredentials("[email protected]"),
       ApplicationName = "DomainApp",
})
.Users.Messages.Send(new Message
{
       Raw = urlSafeToBase64(mimeMessage.ToString())
},
"me");
var t = result.ExecuteAsync().GetAwaiter().GetResult();


private string urlSafeToBase64(string input)
{
    return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(input))
    .Replace('+', '-')
    .Replace('/', '_')
    .Replace("=", "");
}

Solution

  • This is the cause of the problem:

    Raw = urlSafeToBase64(mimeMessage.ToString())
    

    The ToString() method is not meant for doing stuff like this, it's only meant for debugging purposes. See the docs: http://www.mimekit.net/docs/html/M_MimeKit_MimeMessage_ToString.htm

    You will need to write the message to a Stream and then modify your urlSafeToBase64() method to either take a stream or a byte[]