Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gmail not threading replies sent via API

I'm trying to send replies via the Gmail API in Python and can't seem to get the Gmail web client to thread the messages. However, they are being threaded in Outlook, which is very strange.

Here's how I'm creating the messages:

def create_message(sender, to, subject, message_text, reply_to, thread_id, message_id):
    message = MIMEText(message_text, 'html')
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject

    if reply_to:
        message['threadId'] = thread_id
        message['In-Reply-To'] = message_id
        message['References'] = message_id


    return {'raw': base64.urlsafe_b64encode(message.as_string())}

Where both thread_id and message_id are the MIME Message-ID, formatted like <CAGvK4+WJmQGjg6R_QT4rJQApFPeH2xV14DnAVcksTtrc7giE8A@mail.gmail.com>.

I tried changing the message['threadId'] to the threadId returned by createMessage (something like 168f38ab8c831d11) while keeping the In-Reply-To and References headers as the MIME Message-ID, but that doesn't work either (in fact, that makes the message not thread in both Gmail and Outlook).

Any help is appreciated! I've tried just about every combination of setting these headers that I can think of with no luck. Thank you!

like image 797
Adam Bowker Avatar asked Mar 06 '26 07:03

Adam Bowker


1 Answers

For anyone who comes across this in the future, I was able to get it figured out!

Looks like setting the threadId header to the message['threadId'], the In-Reply-To header to the email address (sender in my case), and References header to the MIME Message-ID is enough to get the message to thread on the recipient side, but not on the sender's side. In a lot of cases this would be fine, but I wanted the sender's mailbox to remain organized, so threading there was necessary.

In order to get the messages threaded on the sender's side, you need to add threadId to the message as an additional parameter, outside of raw:

{'raw': base64.urlsafe_b64encode(message.as_string()), 'threadId': thread_id}

Now, my create_message function looks like this:

def create_message(sender, to, subject, message_text, reply_to, thread_id, message_id):
    message = MIMEText(message_text, 'html')
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject

    if reply_to:
        message['threadId'] = thread_id
        message['In-Reply-To'] = sender
        message['References'] = message_id

        return {'raw': base64.urlsafe_b64encode(message.as_string()), 'threadId': thread_id}

    return {'raw': base64.urlsafe_b64encode(message.as_string())}

Where:

  • reply_to is a boolean indicating whether or not the specific message being created is a reply to a thread or a brand new message
  • thread_id is the message['threadId'], should look something like 168f809fbb5e9838
  • message_id is the MIME Message-ID header, should look something like <CAGvK4+W5G3KnYQmjvcpTJ=OCfvPQeWUHcLJG39JVGX4V3y1efA@mail.gmail.com>

I hope someone finds this helpful!!

like image 199
Adam Bowker Avatar answered Mar 08 '26 19:03

Adam Bowker