Gmail API - 无法按标签列出所有邮件

Gmail API - Unable to list all mails by Labels

您好,非常感谢您的回复

我几天前开始了我的编程之旅,只是为了好玩,因为我喜欢 Python 有一段时间了,但从未真正有机会研究它或尝试尝试它。

一天前,我突然想到,如果我可以通过自定义用户标签从一组特定的电子邮件中下载附件,即 "MyEmail" 或 "EmailCool",并存储所有附件会怎样?在这些标签下。

我对 Gmail API 进行了一些试验,并通过以下方式自己进行了一些初步测试:https://developers.google.com/gmail/api/v1/reference/users/messages/list 但问题是我只能抓取和存储附件,如果我只指定我创建的自定义标签之一,即 "MyEmail" 作为参数。

如果我输入这两个标签作为参数,API 会抛出 resultSizeEstimate = 0 的响应,这意味着好像没有电子邮件。

我在service.users().messages.list()方法下申请有什么问题吗?如果我给一个标签作为参数,但不能同时给两个自定义标签,那么我的代码同样有效。

这是我的代码,供您参考:

import base64
import email
import os
import requests
import google.oauth2.credentials
import pickle
import sys

from google_auth_oauthlib.flow import InstalledAppFlow
from apiclient.discovery import build
from httplib2 import Http
from apiclient import errors
from apiclient import discovery
from google.auth.transport.requests import Request


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,
                                               maxResults=500).execute()
    print(response)
    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,
                                                 maxResults=500).execute()

      messages.extend(response['messages'])

      print('... total %d emails on next page [page token: %s], %d listed so far' % (len(response['messages']), page_token, len(messages)))
      sys.stdout.flush()

    return messages

  except errors.HttpError as error:
      print('An error occurred: %s' % error)

def GetAttachments(service, user_id, store_dir, label_ids):

    """Get and store attachment from 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: ID of Message containing attachment.
    prefix: prefix which is added to the attachment filename on saving
    """

    try:
        # email_list = ListMessagesWithLabels(GMAIL, user_id, [label_id_one,label_id_two])  # to read unread emails from inbox
        email_list = ListMessagesWithLabels(service, user_id, label_ids)

        for email in email_list:
            message_id = email['id'] # get id of individual message
            message = service.users().messages().get(userId='me', id=message_id).execute()

            for part in message['payload']['parts']:
                newvar = part['body']

                if 'attachmentId' in newvar:
                    att_id = newvar['attachmentId']
                    att = service.users().messages().attachments().get(userId=user_id, messageId=message_id, id=att_id).execute()
                    data = att['data']
                    file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
                    print(part['filename'])
                    path = ''.join([store_dir, part['filename']])
                    f = open(path, 'wb')
                    f.write(file_data)
                    f.close()

    except Exception as error:
        print('An error occurred: %s' % error)




# Setup the Gmail API
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', ]
CLIENT_SECRETS_FILE = 'client_secret.json'
mail_labels = ['Label_3679404043833618922', 'Label_7190264889161813326']

workingDir = os.environ['USERPROFILE']

gmailDownloadDir = os.path.join(workingDir, 'GmailDownload/')
attachDir = os.path.join(gmailDownloadDir, 'attachments/')
cred_file = os.path.join(gmailDownloadDir, 'credentials.token')
refreshtoken_file = os.path.join(gmailDownloadDir, 'refresh.token')

if 'GmailDownload' not in os.listdir(workingDir):
    os.mkdir(gmailDownloadDir)

if 'attachments' not in os.listdir(gmailDownloadDir):
    os.mkdir(attachDir)


# Get Gmail Credentials
if not os.path.exists(cred_file):
    flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
    credentials = flow.run_local_server()

    with open(cred_file, 'wb') as token:
        pickle.dump(credentials, token)
else:
    with open(cred_file, 'rb') as token:
        credentials = pickle.load(token)

if credentials.expired:
    credentials.refresh(Request())

service = discovery.build('gmail','v1',credentials=credentials)

#GMAIL = discovery.build('gmail', 'v1', http=creds.authorize(Http()))
#service = build('gmail', 'v1', http=creds.authorize(Http()))


GetAttachments(service, user_id='me', label_ids=mail_labels, store_dir=attachDir)

如果您查看您发布的 link,labelIds[] 会显示

Only return messages with labels that match all of the specified label IDs.

因此电子邮件必须包含列表中的所有标签,而不仅仅是任何标签。

另一种方法是将 q 参数与类似 label:MyEmail or label:EmailCool or ...

的内容一起使用

查看此页面:https://support.google.com/mail/answer/7190

如果您确定可以传递的名称,则可以使用自己的标签 lablelIds= [],如果您不确定标签名称,请先列出并从中选择您要使用的标签。

Gmail api 如果使用 labels().list() 方法可以获取所有标签,请使用以下链接作为参考

https://developers.google.com/gmail/api/v1/reference/users/labels/list

http://googleapis.github.io/google-api-python-client/docs/dyn/gmail_v1.users.labels.html#list