How to call the Gmail API in .NET without using the client library

This article is geared towards software developers interested in the Gmail API.

GMass makes extensive use of two APIs — the Inbox SDK API, made by Streak, and the Gmail API provided by Google. The Gmail API manages all of the backend operations for GMass, including applying the “GMass Scheduled” Label to pending campaigns and actually sending a user’s mail merge campaign. GMass is built on the .NET platform and all backend code is written in C#. Google provides a .NET client library for the Gmail API, but recently I discovered a bug in the client library that was a show-stopper, until I figured out how to call the Gmail API using raw HTTP calls.

While the Gmail API asserts that a Draft up to 35 MB in size can be created, I was getting an error from the .NET client library anytime I attempted to create a Draft greater than 1 MB in size. The error was:

Message[Request payload size exceeds the limit: 1048576 bytes.]

I would only get this error when creating a large Draft with the .NET library. Testing the Users.drafts.create method manually using the test form provided by Google did allow me to create large Drafts, which confirmed that the issue was with the .NET library. I therefore set out to create my own function to call the Gmail API to create a Draft and bypass the functionality of the client library.

Like many popular APIs, the Gmail API has an endpoint that you can make an HTTP POST to. In the case of the drafts.Create method, that endpoint is:

https://www.googleapis.com/gmail/v1/users/{EmailAddress}/drafts

where {EmailAddress} is the Gmail account address for which you want to create the Draft.

Here is the C# code I used to call service.Users.Drafts.Create manually:

string payload = "{\n\"message\": {\n" + (!string.IsNullOrEmpty(ThreadID) ? ("\"threadId\":\"" + ThreadID + "\",\n") : ("")) + "\"raw\":\n\"" + RawDraft + "\"\n}\n}";
using (var client = new HttpClient())
{
       var content = new StringContent(payload, Encoding.Default, "message/rfc822");

       var response = client.PostAsync($"https://www.googleapis.com/gmail/v1/users/{EmailAddress}/drafts?access_token={OAuthKey}", content).Result;
       string resultContent = response.Content.ReadAsStringAsync().Result;
       return resultContent;
}

Using the HttpClient object will be familiar to most .NET developers, but the differentiating part of the call is that the mediaType has to be set to “message/rfc822”, as that is what the Gmail API requires.

Also note the payload is formatted according to how the payload is formatted on the Google test form for this method. In my code it’s assumed that:

  • ThreadID is the Gmail Thread ID if the created Draft is to be part of an existing thread, or non-existent if not
  • RawDraft is a base 64 encoded string of the fully formatted email draft. If you want to see an example of a base 64 encoded Draft from your own Gmail account, use the Users.drafts.get method test form to plug in a Draft Id from your own account, set the Format to RAW, and retrieve the base 64 string.
  • EmailAddress is the Gmail account address for whom we’re creating the Draft.
  • OAuthKey is a string containing a valid unexpired OAuth 2.0 key to access the Gmail account of EmailAddress.

After calling the Gmail API, resultContent will contain a string containing the created Draft ID and its Message ID, and these values can easily be extracted with this code:

dynamic GmailDraftResult = JsonConvert.DeserializeObject(resultContent);

You can then access the Gmail Draft ID with GmailDraftResult.id and the Gmail Message ID with GmailDraftResult.message.id.

The code above can be adapted to call any Gmail API method for which the .NET client library doesn’t work.

Leave a Reply

Your email address will not be published. Required fields are marked *