A. Monteiro
A. Monteiro

Reputation: 371

Gmail API Error from Code Sample - a bytes-like object is required, not 'str'

I'm incorporating the Gmail API into a program that I'm making, and I'm getting an error that I haven't been able to resolve/that I haven't been able to find an answer to online. The relevant code is below, as well as the error:

from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
import base64
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import mimetypes
import os

def create_message(sender, to, subject, message_text):

    message = MIMEText(message_text)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject

    return {'raw': base64.urlsafe_b64encode(message.as_string())}

def send_message(service, user_id, message):

    message = (service.users().messages().send(userId=user_id, body=message).execute())
    print('Message Id: %s' % message['id'])
    return message

def send_email(orders):
    SCOPES = 'https://mail.google.com/'
    store = file.Storage('gmail.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
        creds = tools.run_flow(flow, store)
    service = discovery.build('gmail','v1',http=creds.authorize(Http()))

    message_text = orders[0]

    created_message = create_message('from','to','subject', message_text)
    send_message(service, 'from', created_message)
send_email(['TEST'])


Traceback (most recent call last):
  File "test_email.py", line 50, in <module>
    schoolPing(['TEST'])
  File "test_email.py", line 47, in schoolPing
    created_message = create_message('from','to','subject', message_text)
  File "test_email.py", line 27, in create_message
    return {'raw': base64.urlsafe_b64encode(message.as_string())}
  File "/Users/Andre/anaconda/lib/python3.5/base64.py", line 119, in urlsafe_b64encode
    return b64encode(s).translate(_urlsafe_encode_translation)
  File "/Users/Andre/anaconda/lib/python3.5/base64.py", line 59, in b64encode
    encoded = binascii.b2a_base64(s)[:-1]
TypeError: a bytes-like object is required, not 'str'

Upvotes: 35

Views: 8080

Answers (1)

James Cooper
James Cooper

Reputation: 881

Found a solution, replace this line:

return {'raw': base64.urlsafe_b64encode(message.as_string())}

with:

return {'raw': base64.urlsafe_b64encode(message.as_string().encode()).decode()}

Notice added .encode() and .decode() method calls.

First, str object is encoded to bytes object - base64.urlsafe_b64encode requires it in Python 3 (compared to str object in Python 2).

Then, the base64 encoded bytes object must be decoded back to str. This is needed as googleapiclient library will attempt to json serialize it later in code and that is not possible for bytes objects.

Upvotes: 78

Related Questions