I'm working with the Gmail API and encountering an issue with email threading. Here's the workflow:
The email forwarding is successful, but when User 3 replies to User 2, the reply appears as a new email in User 2's inbox, instead of being threaded with the original email. Below is the code snippet I'm using to forward emails:
def get_payload_as_string(message):
if message.is_multipart():
return "".join(part.get_payload(decode=True).decode('utf-8') for part in message.get_payload())
else:
return message.get_payload(decode=True).decode('utf-8')
def create_forward_message(service, user_id, message_id, to_email):
original_message = service.users().messages().get(userId=user_id, id=message_id, format="raw").execute()
msg_raw = base64.urlsafe_b64decode(original_message['raw'].encode('ASCII'))
parsed_msg = message_from_bytes(msg_raw)
payload_str = get_payload_as_string(parsed_msg)
forward_msg = MIMEText(payload_str, _subtype='plain', _charset='utf-8')
forward_msg['to'] = to_email
forward_msg['from'] = user_id
forward_msg['subject'] = "Fwd: " + parsed_msg['subject']
if 'Message-ID' in parsed_msg:
forward_msg['In-Reply-To'] = parsed_msg['Message-ID']
if 'References' in parsed_msg:
forward_msg['References'] = parsed_msg['References']
elif 'Message-ID' in parsed_msg:
forward_msg['References'] = parsed_msg['Message-ID']
raw_message = base64.urlsafe_b64encode(forward_msg.as_bytes())
body = {'raw': raw_message.decode('utf-8')}
sent_message = service.users().messages().send(userId=user_id, body=body).execute()
print("Message Id: %s" % sent_message['id'])
Notably, when manually forwarding emails through Gmail's web interface, replies are correctly threaded. This issue seems specific to the API workflow.
Has anyone encountered this issue or can suggest what might be causing this threading behavior?
I figured out, this answer helped me: https://stackoverflow.com/a/54727532/7802590
The logic that I changed in my code was;
message_id
that I gathered the value from User 2's inbox (IMPORTANT: message_id should be the MIME message id).thread_id
to the body of the request (which you can get it from users.messages.get
.thread_id
in the raw message (which is equals to message_id
.