I've a .NET web application with several Google API integrations and wanted to send Gmail as well. It took me all day, and I found precious little (useful) documentation, so it seemed worth a blog post.
At the start of the day I already had OAuth2 talking with Google. I did have to tweak my setup a bit, but authentication was already a solved problem with my integration.
I had to pull in two NuGet packages to get it to work:
Install-Package Google.Apis.Gmail.v1 Install-Package AE.Net.Mail
Update: In the comments below, Jon notes that using ``MimeKit`` instead of ``AE.Net.Mail`` makes it easier to send HTML-formatted email.
And here's the code that sent an email:
using System.IO; using System.Net.Mail; using Google.Apis.Gmail.v1; using Google.Apis.Gmail.v1.Data; public class TestEmail { public void SendIt() { var msg = new AE.Net.Mail.MailMessage { Subject = "Your Subject", Body = "Hello, World, from Gmail API!", From = new MailAddress("[you]@gmail.com") }; msg.To.Add(new MailAddress("yourbuddy@gmail.com")); msg.ReplyTo.Add(msg.From); // Bounces without this!! var msgStr = new StringWriter(); msg.Save(msgStr); // Context is a separate bit of code that provides OAuth context; // your construction of GmailService will be different from mine. var gmail = new GmailService(Context.GoogleOAuthInitializer); var result = gmail.Users.Messages.Send(new Message { Raw = Base64UrlEncode(msgStr.ToString()) }, "me").Execute(); Console.WriteLine("Message ID {0} sent.", result.Id); } 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("=", ""); } }
Why?
The .NET code samples in the Google documentation don't tell you how to instantiate the Message class. That's the hard part. There is a deep and complicated structure to it, and I couldn't get it to work. The Google Service complained, basically saying, "I want you to use the Raw property." And the Raw property is, well, raw: "The entire email message in an RFC 2822 formatted and URL-safe base64 encoded string." Couple tricks here:
- RFC 2822 is complicated.
- System.Net.Mail.MailMessage doesn't give access to the raw data (even though it must implement RFC 2822 internally).
- URL-safe base64 encoding isn't exactly what Convert.ToBase64String does.
Thankfully AE.Net.Mail.MailMessage provides the Save() method to get the raw RFC 2822 message, and just a little tweaking is necessary to get a URL-Safe base 64 encoding.
Hope saves someone some time! I did a lot of Googling today, and an article like this one would have saved me a ton of time.
Comments !