Search code examples
pythongmailgmail-apigoogle-api-python-client

Sending a reply with Gmail API Python


I created two Gmail accounts and I'm trying to create an e-mail thread between them with the Python Gmail API.

I can send e-mails without any issue, but when it comes to replying to each other and creating a thread, it is simply not working : the new message is successfully displaying as the answer of the received email for the sender, but it is appearing as a new message - without a linked thread - for the receiver.

This problem was described here in 2019 : https://stackoverflow.com/a/63186609/21966625

However, the Gmail APIs changed a lot since this article and I didn't find how to use these advices with today's API.

I tried to carefully respect the instructions of the docs by defining the message's parameters References and In-Reply-To as the received message's id when replying.

Indeed, I retrieve the email :

received_email= service.users().messages().get(userId='me', id=label['id']).execute()

I get a dict looking like:

{'id': '189462395f418017', 'threadId': '189462395f418017', 'labelIds': ['UNREAD','INBOX'], 'snippet': 'xxx'....}

Hence, when I'm building my e-mail, the following method should work :

message_id=received_email['id']

message = EmailMessage()
message.set_content('')
message['To'] = '[email protected]'
message['From'] = '[email protected]'
message['References'] = message_id
message['In-Reply-To'] = message_id
message['Subject'] = 'Automated draft'

In the same way, I defined the threadId as the id of the message I wanted to reply to.

create_message = {'raw': encoded_message,
                  'threadId': message_id
                 }
send_message = (service.users().messages().send(userId="me", body=create_message).execute())

Thanks to this part of the code, the answers are correctly displayed (for the sender of the answer) as explained above, but it appears as a new message - unlinked to a thread - for the receiver.


Solution

  • Actually I found why my method did not work ; even if the dict mention a kind of message id :

    email = {'id': '189462395f418017', 'threadId': '189462395f418017', 'labelIds': ['UNREAD','INBOX'], 'snippet': 'xxx'....}
    

    I thought the messageIDcould be taken just by call email['id'].

    The real messageID is somewhere in the ['payload']['headers'] dictionnary ; one could find it by a loop like :

     for p in email['payload']['headers']:
                        if p['name']=='Message-ID' :
                            message_id=p['value']
    

    This way we have the true messageID of the email, and the threads are successfully created.