0

I'm attempting to send an existing email to another thread using the gmail API in Flask.

Context: I've created a new message object and successfully made the In-Reply-To, References and threadId equal the message_id and thread_id respectively. (Following Gmail's API reference)

def create_message(sender, to, subject, thread_id, message_id, message_text, service):
  """Create a message for an email.

  Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.

  Returns:
    An object containing a base64url encoded email object.
  """
  if type(message_text) != str:
    message_text = str(message_text)

  message = MIMEText(message_text)
  message['to'] = to
  message['from'] = sender
  message['subject'] = subject
  message['In-Reply-To'] = message_id
  message['References'] = message_id
  message['threadId'] = thread_id
  print('created message threadId: %s does == ..' %message['threadId'])
  print(thread_id)

  raw = base64.urlsafe_b64encode(message.as_bytes())
  raw = raw.decode()
  body = {'raw': raw}

  messages = service.users().messages()
  send = messages.send(userId='me', body=body).execute()

Problem: I'm able to successfully send the new messages to my inbox but they are created with a new threadId even though the print statement in the above code shows the same threadId.

Then, when I follow the code example from this thread:

  body = {'message': {'raw': raw, 'threadId': thread_id}}

I get the following error:

googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/gmail/v1/users/me/messages/send?alt=json returned "'raw' RFC822 payload message string or uploading message via /upload/* URL required">

Question: How can I generate these emails so they thread with the same threadId?

Note: I have found similar questions here for javascript, and here for java but haven't found an answer for python.

koopmac
  • 936
  • 10
  • 27

1 Answers1

2

As can be gathered from the information in the links you provided, you do not need to provide the In-Reply-To and References to enable threading, providing the threadId in the request body and make the Subject within the raw message body match, as specified in the documentation is enough.

Please perform the following modification:

Remove the line message['threadId'] = thread_id - the threadId belongs into the request body, not the message body

Sample:

def create_message(sender, to, subject, thread_id, message_text, service):
  """Create a message for an email.

  Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.

  Returns:
    An object containing a base64url encoded email object.
  """
  if type(message_text) != str:
    message_text = str(message_text)

  message = MIMEText(message_text)
  message['to'] = to
  message['from'] = sender
  message['subject'] = subject
  raw = base64.urlsafe_b64encode(message.as_bytes())
  raw = raw.decode()
  body = {'raw': raw, 'threadId':thread_id}
  messages = service.users().messages()
  send = messages.send(userId='me', body=body).execute()
ziganotschka
  • 25,866
  • 2
  • 16
  • 33
  • In the documentation link you provided it says at the bottom that: "1. The requested `threadId` must be specified on the `Message` or `Draft.Message` you supply with your request. 2. The `References` and `In-Reply-To` headers must be set in compliance with the RFC 2822 standard." ie with the same `message_id` – koopmac Oct 11 '19 at 23:53
  • In reply to modification 1: I did attempt to remove this and add it to the request body as described in the question, however the HTTP error isn't originating from the `as_bytes()` method outlined in your 2nd modification. I should have mentioned that in python 3, the `as_bytes()` method is needed, as discussed here: https://github.com/googleapis/google-api-python-client/issues/93 – koopmac Oct 11 '19 at 23:56
  • 1
    https://developers.google.com/gmail/api/v1/reference/users/messages/send specifies that `threadId` is an optional property that does not go inside of the row message body - i.e. it doe snot need to be encoded. You can test it yourself with the corresponding "Try this API" method of the documentation. The References and In-Reply-To headers must be set in compliance with the RFC 2822 standard - if they are set at all, but they do not need to be set. – ziganotschka Oct 12 '19 at 09:47
  • 1
    I updated my code according to the python 3 requirements, it should work for you now and thread correctly. – ziganotschka Oct 12 '19 at 14:37
  • Thanks @ziganotschka, the "Try this API" section helped me better understand the format of the HTTP request. – koopmac Oct 13 '19 at 21:49
  • Glad to hear this! – ziganotschka Oct 14 '19 at 06:51