Search code examples
c#google-apigmail-apimimemimekit

Message parsing with Mimekit Parsing Gmail API is always empty


I am making a call to the Gmail API endpoint: https://gmail.googleapis.com/gmail/v1/users/me/messages/[id] to get an email message (where [id] is the ID of the message I am getting).

I know that my OAuth and API call are working, as I can successfully display the basic email info (subject, snippet, etc) in my app. I am struggling to parse the MIME data for the body, however.

I am using MimeKit, and have reviewed and implemented the documentation for parsing messages. My code looks something like this:

public static string ParseMessage(string content)
{
    // 'content' contains the json returned from the Gmail API call.
    JsonNode jsonObject = JsonNode.Parse(content);

    // ... parsing other stuff here that works ...

    // Parsing the MIME content that does NOT work...
    string payload = jsonObject["payload"].ToJsonString();
    string body = ParseMime(payload);

    // ... other stuff ...
}

public static string ParseMime(string content)
{
    MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(content));
    MimeMessage message = MimeMessage.Load(stream);

    // Implementation from 'Working with Messages' goes here ...
    // http://www.mimekit.net/docs/html/Working-With-Messages.htm
}

I have attempted to implement each of the three strategies from the Working with Messages page of the documentation, but none of them are working as expected. Inspecting the data structures in MimeMessage, I find them empty. This leads me to believe the content isn't being parsed correctly.

  1. Am I putting in the correct content to be parsed by the MimeMessage.Load() function? Based on the API method documentation and the response REST resource documentation, I believe the json object in the payload property of the response is what is needed (the root of the MIME part tree).
  2. Is there some other encoding/decoding or other preparation step I am missing before attempting to parse the MIME content in the message?

The response I receive from the Gmail API, for reference, looks like this (data values are not blank in the actual response, but are removed here for privacy):

{
    "id": "",
    "threadId": "",
    "labelIds": [],
    "snippit": "",
    "payload": {
        "partId": "",
        "mimeType": "",
        "filename": "",
        "headers": [],
        "body": {},
        "parts": []

    },
    "sizeEstimate": ###,
    "historyId": "",
    "internalDate": ""
}

Solution

  • The "payload" attribute in the sample JSON that you pasted doesn't contain a MIME message, it contains a JSON dictionary which isn't something that MimeKit can parse.

    You need to find a way to get the raw MIME message data.

    Based on what I can tell from the documentation, you need to specify that the format you want is raw, and then the response will contain a raw attribute that will be the base64 encoded MIME data.

    SO it sounds like you'd get this:

    {
        "id": "",
        "threadId": "",
        "labelIds": [],
        "snippit": "",
        "raw": "<URL-safe base64 encoded raw MIME data goes here>",
        "sizeEstimate": ###,
        "historyId": "",
        "internalDate": ""
    }
    

    Then your code would need to change to this:

    // Parsing the MIME content
    string payload = jsonObject["raw"].GetValue<string>();
    string body = ParseMime(payload.Replace(‘_’, ‘/‘).Replace(‘-‘, ‘+’));
    

    And ParseMime() would need to be changed to this:

    public static string ParseMime(string base64)
    {
        MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64), false);
        MimeMessage message = MimeMessage.Load(stream);
    
        // Implementation from 'Working with Messages' goes here ...
        // http://www.mimekit.net/docs/html/Working-With-Messages.htm
    }