简体   繁体   English

使用适用于Google Calendar API的代码,为什么Gmail API会因403错误而失败?

[英]Why does Gmail API fail with a 403 error, using code that works properly for Google Calendar API?

I'm following these guides: https://developers.google.com/google-apps/calendar/quickstart/python , https://developers.google.com/gmail/api/quickstart/python . 我正在关注这些指南: https//developers.google.com/google-apps/calendar/quickstart/python,https//developers.google.com/gmail/api/quickstart/python

I've completed all the setup steps for both, and the calendar API code works fine, while the Gmail API code fails with a 403 error. 我已完成两者的所有设置步骤,日历API代码工作正常,而Gmail API代码失败,出现403错误。 What's causing this? 是什么导致了这个? What's different between these two APIs? 这两个API之间有什么不同?

I've combined the code from these two different examples, so they are sharing as much of the API setup code as possible, to rule out a mistake there. 我结合了这两个不同示例中的代码,因此他们尽可能多地共享API设置代码,以排除那里的错误。

I've disabled and re-enabled Gmail API in Google Dev Console. 我已在Google开发者控制台中停用并重新启用了Gmail API。

As mentioned here , I've enabled the Contacts and Google+ APIs. 如前所述在这里 ,我已经启用联系人和Google+的API。

As mentioned here , I've tried all three combinations for Gmail scopes - just the scope from the example, just ' https://mail.google.com/ ', or both. 正如这里提到的,我已经尝试了Gmail范围的所有三种组合 - 只是示例中的范围,只是' https://mail.google.com/ ',或两者兼而有之。

This answer, as well as several other sources, suggest 'setting the "Referers" to "Any referer allowed"', but there is no page in Dev Console I can find that contains this option. 这个答案,以及其他几个来源,建议'将“Referers”设置为“允许任何引用”,但是我可以找到包含此选项的Dev Console中没有页面。 I can add a domain through the "domain verification" tab, but this does not seem to affect anything. 我可以通过“域验证”标签添加域名,但这似乎不会影响任何内容。

Code: 码:

import httplib2
import os
from pprint import pprint

from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools

import datetime

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None


class GoogleApi(object):
    client_secret_file = 'client_secret.json'
    application_name = 'test_app'

    def __init__(self):
        self.credentials = self.get_credentials()
        self.http = self.credentials.authorize(httplib2.Http())
        self.service = discovery.build(self.api_name, self.api_version, http=self.http)

    def get_credentials(self):
        """Gets valid user credentials from storage.

        If nothing has been stored, or if the stored credentials are invalid,
        the OAuth2 flow is completed to obtain the new credentials.

        Returns:
            Credentials, the obtained credential.
        """
        home_dir = os.path.expanduser('~')
        credential_dir = os.path.join(home_dir, '.credentials')
        if not os.path.exists(credential_dir):
            os.makedirs(credential_dir)
        credential_path = os.path.join(credential_dir,
                                       'test-app.json')

        store = oauth2client.file.Storage(credential_path)
        credentials = store.get()
        if not credentials or credentials.invalid:
            flow = client.flow_from_clientsecrets(self.client_secret_file, self.scopes)
            flow.user_agent = self.application_name
            if flags:
                credentials = tools.run_flow(flow, store, flags)
            else:  # Needed only for compatability with Python 2.6
                credentials = tools.run(flow, store)
            print 'Storing credentials to ' + credential_path
        return credentials


class CalendarApi(GoogleApi):
    scopes = 'https://www.googleapis.com/auth/calendar.readonly'
    api_name = 'calendar'
    api_version = 'v3'

    def get_calendar_ids(self):
        cl = self.service.calendarList().list().execute()
        ids = [x['id'] for x in cl['items']]
        return ids


class GmailApi(GoogleApi):

    scopes = 'https://mail.google.com/'
    #scopes = 'https://www.googleapis.com/auth/gmail.readonly'
    api_name = 'gmail'
    api_version = 'v1'

    def get_labels(self):
        ml = self.service.users().labels().list(userId='me').execute()
        labels = results.get('labels', [])
        return labels


def main():
    cc = CalendarApi()
    ids = cc.get_calendar_ids()
    print(ids)

    m = GmailApi()
    labels = m.get_labels()
    print(labels)


if __name__ == '__main__':
    main()

Current error ("Insufficient Permission"): 当前错误(“权限不足”):

Traceback (most recent call last):
  File "gmail_api_test.py", line 92, in <module>
    main()
  File "gmail_api_test.py", line 87, in main
    labels = m.get_labels()
  File "gmail_api_test.py", line 76, in get_labels
    ml = self.service.users().labels().list(userId='me').execute()
  File "/usr/local/lib/python2.7/site-packages/oauth2client/util.py", line 140, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/googleapiclient/http.py", line 729, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/labels?alt=json returned "Insufficient Permission">

Error from a previous version of the code ("Access Not Configured. The API (Gmail API) is not enabled for your project. Please use the Google Developers Console to update your configuration."): 先前版本的代码出错(“未配置访问权限。您的项目未启用API(Gmail API)。请使用Google Developers Console更新您的配置。”):

Traceback (most recent call last):
  File "gmail_demo.py", line 71, in <module>
    main()
  File "gmail_demo.py", line 59, in main
    results = service.users().labels().list(userId='me').execute()
  File "/usr/local/lib/python2.7/site-packages/oauth2client/util.py", line 142, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/googleapiclient/http.py", line 729, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/labels?alt=json returned "Access Not Configured. The API (Gmail API) is not enabled for your project. Please use the Google Developers Console to update your configuration.">

The reason why the permission is still insufficient is because the refresh_token in your file is still valid. 权限仍然不足的原因是因为文件中的refresh_token仍然有效。 The access_token and refresh_token you get when authenticating your users only have the scopes you specify at that time. 在验证用户身份时获得的access_tokenrefresh_token仅具有您当时指定的范围。

Just imagine if that was not the case. 试想一下,如果不是这样的话。 You could then ask your users for readonly and later add the all encompassing https://mail.google.com/ -scope and do a lot of additional stuff without the user's consent. 然后,您可以要求用户为readonly ,并在以后添加包罗万象https://mail.google.com/ -scope,做了很多额外的东西,而用户的同意。

This has been answered more thoroughly here: 这里有更彻底的回答:

How do I get around HttpError 403 Insufficient Permission? 我如何解决HttpError 403不足的权限? (gmail api, python) (gmail api,python)

Even though your question deals with the google calendar API, the 403 error is similar to many of the google API apps. 即使你的问题涉及谷歌日历API,403错误类似于许多谷歌API应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM