Python 3.x gmail python api和python 3消息().send()获取json序列化错误

Python 3.x gmail python api和python 3消息().send()获取json序列化错误,python-3.x,google-api,Python 3.x,Google Api,我使用的是GoogleAPI python客户端==1.7.11 我有Python2代码,它是根据 我将代码转换为python 3,并在下面的urlsafe_b64encode中看到一个类型错误 我的代码: # standard from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from base64 import urlsafe_b64encode # pypi from f

我使用的是GoogleAPI python客户端==1.7.11

我有Python2代码,它是根据

我将代码转换为python 3,并在下面的urlsafe_b64encode中看到一个类型错误

我的代码:

# standard
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from base64 import urlsafe_b64encode

# pypi
from flask import current_app
from apiclient import errors

def sendmail(subject, fromaddr, toaddr, html, text='', ccaddr=None ):
    '''
    send mail
    :param subject: subject of email
    :param fromaddr: from address to use
    :param toaddr: to address to use, may be list of addresses
    :param html: html to send
    :param text: optional text alternative to send
    '''
    current_app.logger.info('sendmail(): from={}, to={}, cc={}, subject="{}"'.format(fromaddr, toaddr, ccaddr, subject))

    # Create message container - the correct MIME type is multipart/alternative.
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject
    msg['From'] = fromaddr
    if not isinstance(toaddr, list):
        toaddr = [toaddr]
    msg['To'] = ', '.join(toaddr)
    if ccaddr:
        if not isinstance(ccaddr, list):
            ccaddr = [ccaddr]
        msg['Cc'] = ', '.join(ccaddr)

    # Record the MIME types of both parts - text/plain and text/html.
    # Attach parts into message container.
    # According to RFC 2046, the last part of a multipart message, in this case
    # the HTML message, is best and preferred.
    if text:
        part1 = MIMEText(text, 'plain')
        msg.attach(part1)
    part2 = MIMEText(html, 'html')
    msg.attach(part2)

    # get credentials using the service account file
    gmail = gmail_service_account_login( current_app.config['APP_SERVICE_ACCOUNT_FILE'], 'librarian@steeplechasers.org' )

    try:
        if debug: current_app.logger.debug('sendmail(): msg.as_string()={}'.format(msg.as_string()))
        message = { 'raw' : urlsafe_b64encode(msg.as_string()) }
        sent = gmail.users().messages().send(userId='me', body=message).execute()
        return sent
    except errors.HttpError as error:
        current_app.logger.error('sendmail(): An error occurred: {}'.format(error))
        raise
我将代码修改为使用as_bytes(),类似于中提到的内容

现在,当调用messages().send()时,我看到一个json序列化错误。我看到GoogleAPI表明它支持pypi上的Python3.6。不确定我需要做什么额外的mod来让gmail接口正常工作

Traceback (most recent call last):
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 2463, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 2449, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 1866, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\flask\views.py", line 163, in dispatch_request
    return meth(*args, **kwargs)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\contracts\views\frontend\eventscalendar.py", line 249, in post
    sendmail( subject, fromlist, tolist, html, ccaddr=cclist )
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\contracts\mailer.py", line 77, in sendmail
    sent = gmail.users().messages().send(userId='me', body=message).execute()
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\googleapiclient\discovery.py", line 789, in method
    actual_path_params, actual_query_params, body_value)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\googleapiclient\model.py", line 158, in request
    body_value = self.serialize(body_value)
  File "C:\Users\lking\Documents\Lou's Software\projects\contracts\contracts\venv\lib\site-packages\googleapiclient\model.py", line 267, in serialize
    return json.dumps(body_value)
  File "C:\Users\lking\AppData\Local\Programs\Python\Python36\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "C:\Users\lking\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\lking\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\lking\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'bytes' is not JSON serializable

是的,我应该在发布问题之前尝试一下,但希望这能帮助其他正在寻找这个问题的人

基于此,我尝试解码从
urlsafe\u b64encode
输出的字节,因此

    message = { 'raw' : urlsafe_b64encode(msg.as_bytes()).decode("utf-8") }
我的最终代码是

# standard
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from base64 import urlsafe_b64encode

# pypi
from flask import current_app
from apiclient import errors

def sendmail(subject, fromaddr, toaddr, html, text='', ccaddr=None ):
    '''
    send mail
    :param subject: subject of email
    :param fromaddr: from address to use
    :param toaddr: to address to use, may be list of addresses
    :param html: html to send
    :param text: optional text alternative to send
    '''
    current_app.logger.info('sendmail(): from={}, to={}, cc={}, subject="{}"'.format(fromaddr, toaddr, ccaddr, subject))

    # Create message container - the correct MIME type is multipart/alternative.
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject
    msg['From'] = fromaddr
    if not isinstance(toaddr, list):
        toaddr = [toaddr]
    msg['To'] = ', '.join(toaddr)
    if ccaddr:
        if not isinstance(ccaddr, list):
            ccaddr = [ccaddr]
        msg['Cc'] = ', '.join(ccaddr)

    # Record the MIME types of both parts - text/plain and text/html.
    # Attach parts into message container.
    # According to RFC 2046, the last part of a multipart message, in this case
    # the HTML message, is best and preferred.
    if text:
        part1 = MIMEText(text, 'plain')
        msg.attach(part1)
    part2 = MIMEText(html, 'html')
    msg.attach(part2)

    # get credentials using the service account file
    gmail = gmail_service_account_login( current_app.config['APP_SERVICE_ACCOUNT_FILE'], 'librarian@steeplechasers.org' )

    try:
        if debug: current_app.logger.debug('sendmail(): msg.as_string()={}'.format(msg.as_string()))
        message = { 'raw' : urlsafe_b64encode(msg.as_bytes()).decode("utf-8") }
        sent = gmail.users().messages().send(userId='me', body=message).execute()
        return sent
    except errors.HttpError as error:
        current_app.logger.error('sendmail(): An error occurred: {}'.format(error))
        raise
# standard
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from base64 import urlsafe_b64encode

# pypi
from flask import current_app
from apiclient import errors

def sendmail(subject, fromaddr, toaddr, html, text='', ccaddr=None ):
    '''
    send mail
    :param subject: subject of email
    :param fromaddr: from address to use
    :param toaddr: to address to use, may be list of addresses
    :param html: html to send
    :param text: optional text alternative to send
    '''
    current_app.logger.info('sendmail(): from={}, to={}, cc={}, subject="{}"'.format(fromaddr, toaddr, ccaddr, subject))

    # Create message container - the correct MIME type is multipart/alternative.
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject
    msg['From'] = fromaddr
    if not isinstance(toaddr, list):
        toaddr = [toaddr]
    msg['To'] = ', '.join(toaddr)
    if ccaddr:
        if not isinstance(ccaddr, list):
            ccaddr = [ccaddr]
        msg['Cc'] = ', '.join(ccaddr)

    # Record the MIME types of both parts - text/plain and text/html.
    # Attach parts into message container.
    # According to RFC 2046, the last part of a multipart message, in this case
    # the HTML message, is best and preferred.
    if text:
        part1 = MIMEText(text, 'plain')
        msg.attach(part1)
    part2 = MIMEText(html, 'html')
    msg.attach(part2)

    # get credentials using the service account file
    gmail = gmail_service_account_login( current_app.config['APP_SERVICE_ACCOUNT_FILE'], 'librarian@steeplechasers.org' )

    try:
        if debug: current_app.logger.debug('sendmail(): msg.as_string()={}'.format(msg.as_string()))
        message = { 'raw' : urlsafe_b64encode(msg.as_bytes()).decode("utf-8") }
        sent = gmail.users().messages().send(userId='me', body=message).execute()
        return sent
    except errors.HttpError as error:
        current_app.logger.error('sendmail(): An error occurred: {}'.format(error))
        raise