【问题标题】:Python Gmail API 'not JSON serializable'Python Gmail API'不是 JSON 可序列化的'
【发布时间】:2016-12-02 16:38:11
【问题描述】:

我想使用 Gmail API 通过 Python 发送电子邮件。一切都应该没问题,但我仍然收到错误“发生错误:b'Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PSJ1cy1hc2NpaSIKTUlNRS ...”这是我的代码:

import base64
import httplib2

from email.mime.text import MIMEText

from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run_flow


# Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'client_secret.json'

# Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.compose'

# Location of the credentials storage file
STORAGE = Storage('gmail.storage')

# Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http()

# Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
  credentials = run_flow(flow, STORAGE, http=http)

# Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http)

# Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http)

# create a message to send
message = MIMEText("Message")
message['to'] = "myemail@gmail.com"
message['from'] = "python.api123@gmail.com"
message['subject'] = "Subject"
body = {'raw': base64.b64encode(message.as_bytes())}

# send it
try:
  message = (gmail_service.users().messages().send(userId="me",     body=body).execute())
  print('Message Id: %s' % message['id'])
  print(message)
except Exception as error:
  print('An error occurred: %s' % error)

【问题讨论】:

  • *错误是“fhkakjfwjkfbmdn... is not JSON serializable

标签: python json api email gmail


【解决方案1】:

我也遇到了同样的问题,我假设您使用的是 Python3,我在另一篇文章中发现了这个问题,建议执行以下操作:

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

查看: https://github.com/google/google-api-python-client/issues/93

【讨论】:

  • 也为我工作
  • 哇,你为我节省了更多的绝望时间。
  • 感谢@Robert,为我工作
【解决方案2】:

如果你在 Python3 中运行,b64encode() 将返回字节字符串

您必须对其进行解码以获取任何会对该数据执行 json.dumps() 的操作

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}

【讨论】:

    【解决方案3】:

    在过去的一天里,我一直在努力阅读(过时的)Gmail API 文档和 stackoverflow,希望以下内容对其他 Python 3.8 人员有所帮助。如果对您有帮助,请投票!

    import os
    import base64
    import pickle
    from pathlib import Path
    from email.mime.text import MIMEText
    import googleapiclient.discovery
    import google_auth_oauthlib.flow
    import google.auth.transport.requests
    
    def 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 credentials
    
    def 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
    
    

    【讨论】:

    • 您先生是救生员。我错误地使用了 decode() 方法。你有我的赞成票。
    • 我很高兴 - 感谢您抽出时间告诉我@Gergely :)
    【解决方案4】:

    我假设您已从 Google Gmail API 帮助中获取此代码。 (如果有人感兴趣-https://developers.google.com/gmail/api/quickstart/python

    我遇到了同样的问题,不得不多次修改代码。

    你的问题可以通过改变来解决:

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

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

    我尝试并修复了在运行上面链接中提供的示例代码时遇到的大多数问题,我消除了大部分问题,如果有人需要,这里是对我有用的代码:

    (附注:我使用的是 Python 3.8)

    from __future__ import print_function
    import pickle
    import os.path
    from googleapiclient.discovery import build
    from google_auth_oauthlib.flow import InstalledAppFlow
    from google.auth.transport.requests import Request
    from email.mime.text import MIMEText
    import base64
    
    reciever = input("Please whom you want to send the mail to - ")
    subject = input("Please write your subject - ")
    msg = input("Please enter the main body of your mail - ")
    
    SCOPES = ['https://www.googleapis.com/auth/gmail.modify']
    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)
    service = build('gmail', 'v1', credentials=creds)
    message = MIMEText(msg)
    message['to'] = reciever
    message['from'] = "ayush.abhishek.bhatt@gmail.com"
    message['subject'] = subject
    raw = base64.urlsafe_b64encode(message.as_bytes())
    raw = raw.decode()
    body = {'raw' : raw}
    message = (service.users().messages().send(userId='me', body=body).execute())
    

    您只需导入此代码、运行它并输入所需的任何内容。这是完全安全的,因为它来自谷歌本身。

    如果这对你有帮助,我会很荣幸。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 2015-01-07
      相关资源
      最近更新 更多