Search code examples
pythongmail-apigoogle-workspacegoogle-api-python-client

Gmail API: Forwarded Email Replies Not Appearing Under The Original Thread


I'm working with the Gmail API and encountering an issue with email threading. Here's the workflow:

  1. User 2 subscribes pub/sub notifications.
  2. User 1 sends an email to User 2 via Gmail's web client.
  3. The Pub/Sub endpoint triggers and forwards the email from User 2 to User 3 (automated by a script, an API endpoint).
  4. User 3 replies to User 2 using the Gmail's web client.

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?


Solution

  • I figured out, this answer helped me: https://stackoverflow.com/a/54727532/7802590

    The logic that I changed in my code was;

    1. I added the message_id that I gathered the value from User 2's inbox (IMPORTANT: message_id should be the MIME message id).
    2. I added thread_id to the body of the request (which you can get it from users.messages.get.
    3. I added thread_id in the raw message (which is equals to message_id.