Python forward a gmail message using Google API

I’m trying to forward a message using Google’s API client. In order to do that, I am reading the message, modifying it and would then like to send it, but I run into a problem where the message that I download has the wrong type and I don’t know how to encode it. Here is my code:

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import os
import base64
from datetime import datetime
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.send']

creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
    creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(               
            # your creds file here. Please create json file as here https://cloud.google.com/docs/authentication/getting-started
            'credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open('token.json', 'w') as token:
        token.write(creds.to_json())

    
service = build('gmail', 'v1', credentials=creds)
results = service.users().messages().list(userId='me', labelIds=['INBOX']).execute()
messages = results.get('messages',[]);


message = messages[0]
msg = service.users().messages().get(userId='me', id=message['id']).execute()
print(type(msg))

msg['To'] = '[email protected]'

encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {"raw": encoded_message}

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

outputs:

<class 'dict'>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[57], line 32
     28 print(type(msg))
     30 msg['To'] = '[email protected]'
---> 32 encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
     33 create_message = {"raw": encoded_message}
     35 message = (service.users().messages().send(userId='me', body=body).execute())

AttributeError: 'dict' object has no attribute 'as_bytes'

Does anyone know how to encode the downloaded message object which is a dictionary?

The documentation for the gmail API (https://developers.google.com/gmail/api/reference/rest/v1/users.messages#Message) suggests each message is a Message type. Each message has a Payload object that contains a MessagePart object. MessagePart then has body and parts that you’ll probably want to parse.

You may also have some success by passing the Message['raw'] to Python’s email.parser.Parser class, which will provide a more Pythonic way to access the parts of the email while providing the correct string decoding.

If you’re just forwarding the message, you may just want to extract Message['raw'] and pass it on.

Leave a Comment