Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I properly base64 encode a MIMEText for Gmail API?

From the Gmail API's developer guide:

The following code sample demonstrates creating a MIME message, encoding to a base64url string, and assigning it to the raw field of the Message resource:

def create_message(sender, to, subject, message_text):
  """Create a message for an email.

  Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.

  Returns:
    An object containing a base64url encoded email object.
  """
  message = MIMEText(message_text)
  message['to'] = to
  message['from'] = sender
  message['subject'] = subject
  return {'raw': base64.urlsafe_b64encode(message.as_string())}

But if I do something like

from email.MIMEText import MIMEText
import base64
message = MIMEText('This is a test')
message['to'] = '[email protected]'
message['from'] = '[email protected]'
message['subject'] = 'Test'
body = {'raw': base64.urlsafe_b64encode(message.as_string())}

I get TypeError: a bytes-like object is required, not 'str' If instead I do:

body = {'raw': base64.urlsafe_b64encode(message.as_bytes())}
message = (service.users().messages().send(userId='me', body=body)
               .execute())

I get the following traceback about some binary not being json serializable:

~/env/lib/python3.5/site-packages/googleapiclient/discovery.py in method(self, **kwargs)
    792     headers = {}
    793     headers, params, query, body = model.request(headers,
--> 794         actual_path_params, actual_query_params, body_value)
    795 
    796     expanded_url = uritemplate.expand(pathUrl, params)

~/env/lib/python3.5/site-packages/googleapiclient/model.py in request(self, headers, path_params, query_params, body_value)
    149     if body_value is not None:
    150       headers['content-type'] = self.content_type
--> 151       body_value = self.serialize(body_value)
    152     self._log_request(headers, path_params, query, body_value)
    153     return (headers, path_params, query, body_value)

~/env/lib/python3.5/site-packages/googleapiclient/model.py in serialize(self, body_value)
    258         self._data_wrapper):
    259       body_value = {'data': body_value}
--> 260     return json.dumps(body_value)
    261 
    262   def deserialize(self, content):

/usr/lib/python3.5/json/__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    228         cls is None and indent is None and separators is None and
    229         default is None and not sort_keys and not kw):
--> 230         return _default_encoder.encode(obj)
    231     if cls is None:
    232         cls = JSONEncoder

/usr/lib/python3.5/json/encoder.py in encode(self, o)
    196         # exceptions aren't as detailed.  The list call should be roughly
    197         # equivalent to the PySequence_Fast that ''.join() would do.
--> 198         chunks = self.iterencode(o, _one_shot=True)
    199         if not isinstance(chunks, (list, tuple)):
    200             chunks = list(chunks)

/usr/lib/python3.5/json/encoder.py in iterencode(self, o, _one_shot)
    254                 self.key_separator, self.item_separator, self.sort_keys,
    255                 self.skipkeys, _one_shot)
--> 256         return _iterencode(o, 0)
    257 
    258 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,

/usr/lib/python3.5/json/encoder.py in default(self, o)
    177 
    178         """
--> 179         raise TypeError(repr(o) + " is not JSON serializable")
    180 
    181     def encode(self, o):

TypeError: b'Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PSJ1cy1hc2NpaSIKTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogN2JpdApGcm9tOiBUZXN0IFB5dGhvbgpUbzogcmFwaGFlbC5hLmR1bWFzQGdtYWlsLmNvbQpTdWJqZWN0OiBQbGVhc2Ugc3RheSBjYWxtLCB0aGlzIGlzIGEgdGVzdAoKVGhpcyBpcyBhIHRlc3Q=' is not JSON serializable
like image 221
raphael Avatar asked Oct 10 '17 13:10

raphael


People also ask

Does Gmail support base64 images?

Hi @Anonymous , As I can find, base64 encoded images are not supported in Gmail (from years ago on). Hope this helps. If this post helps, then please consider Accept it as the solution to help the other members find it.

What is base64 in API?

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding.

Does base64 support Unicode?

Anything that you paste or enter in the text area on the left automatically gets encoded to base64 on the right. It supports the most popular Unicode encodings (such as UTF-8, UTF-16, UCS-2, UTF-32, and UCS-4) and it works with emoji characters.


1 Answers

Try:

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

base64.urlsafe_b64encode returns a bytes object (see docs) so you need to convert the output to a string before serialising it as JSON.

like image 177
Henry Heath Avatar answered Oct 19 '22 08:10

Henry Heath