0

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": ""
}
2
  • What happens if you request the endpoint with the same query in say Postman? Commented Jan 10, 2024 at 5:56
  • I am using Postman as well to compare and verify the API call is working. The response I get in Postman matches exactly what I get in the app; it is the same json response that I am parsing in ParseMessage() function. Commented Jan 10, 2024 at 5:59

1 Answer 1

2

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

This was almost exactly what I needed! Just two minor changes. First, I actually needed to use jsonObject["raw"]!.GetValue<string>();, because ToJsonString() includes quotation marks in the message. Second, I needed to do one more step. The raw format from the Google API is not directly Base64, it is URL-safe Base 64. I needed to add the step payload.Replace('_', '/').Replace('-', '+'); (see solution here: stackoverflow.com/questions/26353710/…). Can you update the answer and I will make it as the answer?
I’ve just updated my answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.