title: Encoding email as base64 in Python 3
body: <p>I'm trying to create and send an email using gmail, based on the instructions<a href="https://developers.google.com/gmail/api/guides/sending" rel="nofollow noreferrer">here</a> to encode as base64.</p>
  
  <p>I create the message in this way:</p>
  
  <pre><code>import smtplib
  from email.mime.text import MIMEText
  import base64
  to='name@gmail.com'
  sender = 'me@email.com'
  subject = 'Menu'
  message_text = 'Spam'
  message = MIMEText(message_text)
  message['to'] = to
  message['from'] = sender
  message['subject'] = subject
  </code></pre>
  
  <p>But, when I convert to base64</p>
  
  <pre><code>msg = {'raw': base64.urlsafe_b64encode(message.as_string())}
  </code></pre>
  
  <p>I get this error:
  <code>TypeError: a bytes-like object is required, not 'str'</code></p>
  
  <p>So I try this:</p>
  
  <pre><code>msg = {'raw': base64.urlsafe_b64encode(message.as_bytes())}
  </code></pre>
  
  <p>But then, when I come to send the message</p>
  
  <pre><code>result = (service.users().messages().send(userId=user_id, body=message)
             .execute())
  </code></pre>
  
  <p>I get this error:</p>
  
  <pre><code>TypeError                                 Traceback (most recent call last)
  &lt;ipython-input-33-3c5bbd8af82c&gt; in &lt;module&gt;
        8 send_message(service=service,
        9              user_id = 'MYEMAIL',
  ---&gt; 10              message = msg)
  
  &lt;ipython-input-32-c2348e02ff45&gt; in send_message(service, user_id, message)
       12   """
       13   #try:
  ---&gt; 14   result = (service.users().messages().send(userId=user_id, body=message)
       15                .execute())
       16   print ('Message Id: %s' % message['id'])
  
  ~/gmail_env/lib/python3.7/site-packages/googleapiclient/discovery.py in method(self, **kwargs)
      787     headers = {}
      788     headers, params, query, body = model.request(headers,
  --&gt; 789         actual_path_params, actual_query_params, body_value)
      790 
      791     expanded_url = uritemplate.expand(pathUrl, params)
  
  ~/gmail_env/lib/python3.7/site-packages/googleapiclient/model.py in request(self, headers, path_params, query_params, body_value)
      156     if body_value is not None:
      157       headers['content-type'] = self.content_type
  --&gt; 158       body_value = self.serialize(body_value)
      159     self._log_request(headers, path_params, query, body_value)
      160     return (headers, path_params, query, body_value)
  
  ~/gmail_env/lib/python3.7/site-packages/googleapiclient/model.py in serialize(self, body_value)
      265         self._data_wrapper):
      266       body_value = {'data': body_value}
  --&gt; 267     return json.dumps(body_value)
      268 
      269   def deserialize(self, content):
  
  ~/anaconda3/lib/python3.7/json/__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
      229         cls is None and indent is None and separators is None and
      230         default is None and not sort_keys and not kw):
  --&gt; 231         return _default_encoder.encode(obj)
      232     if cls is None:
      233         cls = JSONEncoder
  
  ~/anaconda3/lib/python3.7/json/encoder.py in encode(self, o)
      197         # exceptions aren't as detailed.  The list call should be roughly
      198         # equivalent to the PySequence_Fast that ''.join() would do.
  --&gt; 199         chunks = self.iterencode(o, _one_shot=True)
      200         if not isinstance(chunks, (list, tuple)):
      201             chunks = list(chunks)
  
  ~/anaconda3/lib/python3.7/json/encoder.py in iterencode(self, o, _one_shot)
      255                 self.key_separator, self.item_separator, self.sort_keys,
      256                 self.skipkeys, _one_shot)
  --&gt; 257         return _iterencode(o, 0)
      258 
      259 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
  
  ~/anaconda3/lib/python3.7/json/encoder.py in default(self, o)
      177 
      178         """
  --&gt; 179         raise TypeError(f'Object of type {o.__class__.__name__} '
      180                         f'is not JSON serializable')
      181 
  
  TypeError: Object of type bytes is not JSON serializable
  </code></pre>
  
  <p>So, how do i format the message? (I think this may be to do with a Python 3 / Python 2 difference but can't be sure)</p>