Gmail API email responses appearing as separate messages instead of threaded replies

I’m working on a Gmail API integration where I need to send replies that show up properly threaded in Gmail’s interface. Right now my replies are being sent successfully and they do get grouped in the same conversation, but Gmail displays them as individual messages rather than actual replies.

What I’m currently doing:

  1. Setting the thread identifier:
mailObject.ThreadId = conversationId;
  1. Adding reply headers to link the messages:
emlMessage.Headers.Add("In-Reply-To", originalMessageId);
emlMessage.Headers.Add("References", originalMessageId);
  1. Keeping the subject line consistent:
emlMessage.Subject = originalEmail.Subject;

My implementation:

private string BuildReplyMime(string encodedMime, string conversationId, string originalMessageId)
{
    var emlMessage = MimeKit.MimeMessage.Load(new MemoryStream(Convert.FromBase64String(encodedMime.Replace('-', '+').Replace('_', '/'))));
    emlMessage.Subject = previousSubject;

    emlMessage.Headers.Add("In-Reply-To", originalMessageId);
    emlMessage.Headers.Add("References", originalMessageId);

    using (var stream = new MemoryStream())
    {
        emlMessage.WriteTo(stream);
        return Convert.ToBase64String(stream.ToArray())
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");
    }
}
mailObject.Raw = processedMime;
mailObject.ThreadId = conversationId;

UsersResource.MessagesResource.SendRequest sendRequest = _service.Users.Messages.Send(mailObject, emailAddress);
mailObject = await sendRequest.ExecuteAsync();

The messages end up in the right conversation thread but Gmail doesn’t show them as proper replies. What could I be missing to make Gmail recognize these as threaded responses?

Threading breaks usually happen because of recipient handling, not your sender setup. Gmail checks if the recipient chain matches the original conversation when it gets your reply. Change the To/CC fields or send from an unexpected address? Gmail thinks it’s a new conversation. Make sure your reply keeps the exact same participant list as the original thread. Here’s another thing that’ll trip you up - timezone issues in Date headers. Gmail’s threading looks at whether timestamps make sense. If your reply’s Date header is way off compared to when you actually got the original message, threading breaks. I’ve seen server clock differences cause this exact problem.

make sure ur setting the message-id header right on outgoing msgs - gmail uses that for threading too! also, maybe add a small delay b4 sending. i noticed rapid replies can mess up threading since gmail’s processing can’t keep up. usually helps me.

Been there countless times. Your code’s fine - Gmail threading is just finicky with timing and headers.

The real problem? Gmail’s threading logic runs server-side and takes a few seconds to link messages properly. You’ve got multiple moving parts that can break threading.

I gave up fighting Gmail API threading years ago. Now I automate the whole email workflow with Latenode. It handles threading complexity automatically and has Gmail connectors that respect proper reply formatting.

Just set up a workflow that triggers on incoming emails, processes content, and sends threaded replies without manually touching headers. Takes 10 minutes to configure vs hours debugging API calls.

Threading works because Latenode handles Gmail integration properly behind the scenes. No more guessing about Message-ID extraction or References header formatting.

Same issue here! You’re not handling the References header right for multi-reply threads. When replying to a message that’s already a reply, your References header needs ALL previous message IDs in the thread - not just the immediate parent. So if you’re replying to the third message, include message1-id, message2-id, message3-id in chronological order. Also, use the actual Message-ID from the headers, not Gmail’s message ID. Extract it with originalMessage.Payload.Headers and find the “Message-ID” header. One more thing - make sure your subject starts with "Re: " if it doesn’t already. Gmail’s threading is picky about these details.

Had this exact problem last year building an automated support system. The issue was how I handled message retrieval. You need the actual email headers from the Gmail API response - don’t construct them yourself. When fetching the original message, use format=full in your get request to grab all headers. Then pull the proper Message-ID from message.Payload.Headers where the header name equals “Message-ID”. Gmail’s Message-ID looks different from their internal message IDs - it’s usually formatted like <[email protected]> with angle brackets. Also check you’re not accidentally modifying the subject prefix. If the original already has “Re:”, don’t add another one. Threading broke for me when subjects became “Re: Re: Original Subject”. The API accepts it but Gmail’s threading algorithm gets confused.