python - 如何从服务帐户访问 gmail 数据?
问题描述
我想通过服务帐户使用 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 需要哪些特殊范围?(以及在哪里设置它们?)
解决方案
缺少对范围的域范围访问:
您应该设置服务帐户应该具有域范围访问权限的适当范围,以便调用Users.labels:代表其他用户列出:当您将域范围的权限委派给服务帐户时,您必须定义哪些范围服务帐户应该具有对.
这是在管理控制台上完成的,同时管理域范围的委派。按照此处指定的步骤,当您进入域范围委派面板时,添加以下一个或多个范围:
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 范围(如果您没有,请授予域范围的权限'没有这样做,按照这些步骤)。
推荐阅读
- php - Firebase 推送通知不会持续存在
- static-typing - 类型声明是静态类型语言优点的重要组成部分吗?
- c++ - 如何阅读 NDEF 消息?(M24SR04-Y)
- angular - 默认情况下在另一个组件中显示来自 mat-selection-list 的第一个列表项值
- c - sprintf 格式:固定字符数,可变小数位数
- klipfolio - 如何在 Klipfolio 中按每一天计算不同的用户 ID?
- javascript - 如何在 JQuery 中添加和删除数组而不重新索引数组键
- nlp - 谷歌语音识别 - 仅限数字
- cakephp - 如何使用 cakephp 获取数据表中列的总和
- node.js - 如何在 EJS 中读取 JSON 文件?