如何从服务帐户访问Gmail数据?

时间:2020-07-21 18:08:50

标签: python gmail-api

我想通过服务帐户使用Gmail API管理过滤器。我已经在GSuite中注册了域名,并在那里管理所有有问题的帐户。

我写了一些代码,使我可以访问日历-在所有用户日历上都可以正常工作。

从控制台创建凭据JSON文件(授予项目所有权)后,我针对gmail案例复制了此工作代码:

import googleapiclient.discovery
from google.oauth2 import service_account as google_oauth2_service_account

secrets = {
    "type": "service_account",
    "project_id": "setfilter",
    "private_key_id": "3xxxb",
    "private_key": "-----BEGIN PRIVATE KEY-----xxxDpLU\n-----END PRIVATE KEY-----\n",
    "client_email": "setfilter@setfilter.iam.gserviceaccount.com",
    "client_id": "1xxx2",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/setfilter%40setfilter.iam.gserviceaccount.com"
}
    
credentials = google_oauth2_service_account.Credentials.from_service_account_info(secrets, scopes=['https://mail.google.com/'], subject='MyAccountToAdministerTheConsole@mydomain')
service = googleapiclient.discovery.build('gmail', 'v1', credentials=credentials)
results = service.users().labels().list(userId='me').execute()
print(results)

运行此代码会产生可怕的结果

Traceback (most recent call last):
  File "D:/Nextcloud/dev-perso/setfilter/setfilter.py", line 25, in <module>
    results = service.users().labels().list(userId='me').execute()
  File "C:\Python38\lib\site-packages\googleapiclient\_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "C:\Python38\lib\site-packages\googleapiclient\http.py", line 892, in execute
    resp, content = _retry_request(
  File "C:\Python38\lib\site-packages\googleapiclient\http.py", line 177, in _retry_request
    resp, content = http.request(uri, method, *args, **kwargs)
  File "C:\Python38\lib\site-packages\google_auth_httplib2.py", line 189, in request
    self.credentials.before_request(
  File "C:\Python38\lib\site-packages\google\auth\credentials.py", line 133, in before_request
    self.refresh(request)
  File "C:\Python38\lib\site-packages\google\oauth2\service_account.py", line 359, in refresh
    access_token, expiry, _ = _client.jwt_grant(request, self._token_uri, assertion)
  File "C:\Python38\lib\site-packages\google\oauth2\_client.py", line 153, in jwt_grant
    response_data = _token_endpoint_request(request, token_uri, body)
  File "C:\Python38\lib\site-packages\google\oauth2\_client.py", line 124, in _token_endpoint_request
    _handle_error_response(response_body)
  File "C:\Python38\lib\site-packages\google\oauth2\_client.py", line 60, in _handle_error_response
    raise exceptions.RefreshError(error_details, response_body)
google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', '{\n  "error": "unauthorized_client",\n  "error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."\n}')

这是正确的方法吗?如果是这样-Gmail需要哪些特殊范围?(以及在哪里设置?)

1 个答案:

答案 0 :(得分:1)

缺少对范围的域范围访问:

您应设置服务帐户应具有域范围访问权限的适当范围,以便代表其他用户调用Users.labels: list当您将域范围的权限委派给服务帐户时,您必须定义服务帐户应该在域范围内访问的范围

这是在Admin console上完成的,同时管理域范围的委派。遵循指定的here步骤,进入域范围的委派面板时,添加一个或多个these scopes

https://mail.google.com/
https://www.googleapis.com/auth/gmail.modify
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.labels
https://www.googleapis.com/auth/gmail.metadata

注意:

  • 我假设您已经授予服务帐户域范围的权限,因为您能够访问其他用户的日历,因此您已经提供了日历范围,但没有提供适当的Gmail范围(请授予域范围的权限如果您尚未这样做,请遵循these steps)。