Python Gmail API 'not JSON serializable' Python Gmail API 'not JSON serializable' json json

Python Gmail API 'not JSON serializable'


I had this same issue, I assume you are using Python3 I found this on another post and the suggestion was to do the following:

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

Check out:https://github.com/google/google-api-python-client/issues/93


I've been struggling through the (out of date) Gmail API docs and stackoverflow for the past day and hope the following will be of help to other Python 3.8 people. Please up-vote if it helps you!

import osimport base64import picklefrom pathlib import Pathfrom email.mime.text import MIMETextimport googleapiclient.discoveryimport google_auth_oauthlib.flowimport google.auth.transport.requestsdef retry_credential_request(self, force = False):    """ Deletes token.pickle file and re-runs the original request function """    print("⚠ Insufficient permission, probably due to changing scopes.")    i = input("Type [D] to delete token and retry: ") if force == False else 'd'    if i.lower() == "d":        os.remove("token.pickle")        print("Deleted token.pickle")        self()def get_google_api_credentials(scopes):    """ Returns credentials for given Google API scope(s) """    credentials = None    # The file token.pickle stores the user's access and refresh tokens, and is    # created automatically when the authorization flow completes for the first    # time.    if Path('token.pickle').is_file():        with open('token.pickle', 'rb') as token:            credentials = pickle.load(token)    # If there are no (valid) credentials available, let the user log in.    if not credentials or not credentials.valid:        if credentials and credentials.expired and credentials.refresh_token:            credentials.refresh(google.auth.transport.requests.Request())        else:            flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file('credentials-windows.json', scopes)            credentials = flow.run_local_server(port=0)        # Save the credentials for the next run        with open('token.pickle', 'wb') as token:            pickle.dump(credentials, token)    return credentialsdef send_gmail(sender, to, subject, message_text):    """Send a simple email using Gmail API"""    scopes = ['https://www.googleapis.com/auth/gmail.compose']    gmail_api = googleapiclient.discovery.build('gmail', 'v1', credentials=get_google_api_credentials(scopes))    message = MIMEText(message_text)    message['to'] = to    message['from'] = sender    message['subject'] = subject    raw = base64.urlsafe_b64encode(message.as_bytes()).decode()    try:        request=gmail_api.users().messages().send(userId = "me", body = {'raw': raw}).execute()    except googleapiclient.errors.HttpError as E:        print(E)        drive_api = retry_credential_request(send_gmail)        return    return request


If you are running in Python3, b64encode() will return byte string

You would have to decode it for anything that will do a json.dumps() on that data

b64_encoded_message = base64.b64encode(message.as_bytes())if isinstance(b64_encoded_message, bytes):    b64_encoded_message = bytes_message.decode('utf-8')body = {'raw': b64_encoded_message}