【问题标题】:Gmail API How to retrieve body of an emailGmail API 如何检索电子邮件的正文
【发布时间】:2020-05-11 03:55:36
【问题描述】:

伙计们,我一直在尝试在我的收件箱中获取电子邮件的消息正文。我对这个 Gmail API 很陌生,所以我一直在尝试从谷歌文档中为 API 拼凑代码

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
import base64
import email

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.modify','https://www.googleapis.com/auth/gmail.metadata', 'https://www.googleapis.com/auth/gmail.addons.current.message.metadata', 'https://www.googleapis.com/auth/gmail.addons.current.message.readonly', 'https://www.googleapis.com/auth/gmail.addons.current.message.action']



def GetMessage(service, user_id, msg_id):
  """Get a Message with given ID.

  Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    msg_id: The ID of the Message required.

  Returns:
    A Message.
  """
  try:
    message = service.users().messages().get(userId=user_id, id=msg_id).execute()

    #print('Message snippet: %s' % message['snippet'])

    return message
  except error:
    print('An error occurred: %s' % error)

def ListMessagesWithLabels(service, user_id, label_ids=[]):
  """List all Messages of the user's mailbox with label_ids applied.

  Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    label_ids: Only return Messages with these labelIds applied.

  Returns:
    List of Messages that have all required Labels applied. Note that the
    returned list contains Message IDs, you must use get with the
    appropriate id to get the details of a Message.
  """
  try:
    response = service.users().messages().list(userId=user_id,
                                               labelIds=label_ids).execute()
    messages = []
    if 'messages' in response:
      messages.extend(response['messages'])

    while 'nextPageToken' in response:
      page_token = response['nextPageToken']
      response = service.users().messages().list(userId=user_id,
                                                 labelIds=label_ids,
                                                 pageToken=page_token).execute()
      messages.extend(response['messages'])

    return messages
  except error:
    print('An error occurred: %s' % error)

def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = 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 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)

    userId='me'
    labels = ['INBOX']
    messages = ListMessagesWithLabels(service, userId, labels)
    print(messages)
    meta = messages[1]
    print(meta.get('id'))
    id = meta.get('id')
    message = GetMessage(service, userId, id)
    print(message['snippet'])
    message = service.users().messages().get(userId=userId, id=id, format='raw').execute()
    msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
    mime_msg = email.message_from_bytes(msg_str)
    print(mime_msg)


    # # Call the Gmail API
    # results = service.users().labels().list(userId='me').execute()
    # labels = results.get('labels', [])
    #
    # if not labels:
    #     print('No labels found.')
    # else:
    #     print('Labels:')
    #     for label in labels:
    #         print(label['name'])

if __name__ == '__main__':
    main()

上面的代码接收到消息,但无法正确接收可读形式的正文。我想知道如何才能以可读的形式接收电子邮件的正文?

我尝试阅读有关此问题的其他帖子,并得出结论与正文的编码方式有关。我无法实现或理解如何解码和读取数据。

【问题讨论】:

  • 你有没有试过这样的 base64.urlsafe_b64decode(msg.get("payload").get("body").get("data").encode("ASCII")).decode ("utf-8")

标签: python-3.x api email base64 gmail


【解决方案1】:

感谢 DalmTo 的回答,它帮助我解决了问题。我能够接收正文并解码内容。由于其他错误,我从头开始,但我会在这里发布我的工作代码。

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
import base64

SCOPES = ['https://mail.google.com/','https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.addons.current.message.readonly', 'https://www.googleapis.com/auth/gmail.addons.current.message.action']

def GetMessage(service, user_id, msg_id):
    message = service.users().messages().get(userId=user_id, id=msg_id, format='raw').execute()
    return message

def ListMessagesWithLabels(service, user_id, label_ids=[]):
    response = service.users().messages().list(userId=user_id, labelIds=label_ids).execute()
    messages = []
    if 'messages' in response:
        messages.extend(response['messages'])

    while 'nextPageToken' in response:
        page_token = response['nextPageToken']
        response = service.users().messages().list(userId=user_id, labelIds=label_ids, pageToken=page_token).execute()
        messages.extend(response['messages'])

    return messages

def main():

    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle','rb') as token:
            creds = pickle.load(token)

    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)
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('gmail', 'v1', credentials = creds)
    userId = 'me'
    labels = ['INBOX']
    messageId = ListMessagesWithLabels(service, userId, labels)
    #print(messageId)
    meta = messageId[3]
    id = meta.get('id')
    message = GetMessage(service, userId, id)
    #print(message)
    msg_raw = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
    print(msg_raw)


if __name__ == '__main__':
    main()

我也遇到了范围的问题。如果你去掉这两个元数据范围,它不会给出授权错误。

【讨论】:

    猜你喜欢
    • 2017-03-07
    • 2020-02-05
    • 2020-09-27
    • 2014-08-17
    • 2012-04-17
    • 2011-04-05
    • 2022-10-25
    • 2018-07-28
    • 2017-11-01
    相关资源
    最近更新 更多