3

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!

Adam Bowker
  • 193
  • 9
  • EDIT: Looks like the messages are being threaded on the recipient's end, but not in the Gmail 'Sent' box of the sender. I thought maybe Gmail just didn't thread outgoing messages in the Sent folder, but if I manually reply to an email, it does get threaded. Any suggestions? – Adam Bowker Feb 16 '19 at 20:06

1 Answers1

9

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!!

Adam Bowker
  • 193
  • 9