我正在try 运行一个在Gmail中设置委托的Python脚本.

作为一个基本的起点,我使用了来自谷歌的"Python quickstart".

from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.settings.sharing']


def main():
    """Shows basic usage of the Docs API.
    Prints the title of a sample document.
    """

    creds = None
    # The file token.json 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.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # 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.json', 'w') as token:
            token.write(creds.to_json())

    try:

        # Create a Gmail service client
        service = build('gmail', 'v1', credentials=creds)

        # Set delegation for a specific sender
        sender_email = 'sender@domain.com'
        delegate_email = 'delegate@domain.com'

        settings = {
            'delegateEmail': delegate_email
        }

        result = service.users().settings().sendAs().update(userId='me', sendAsEmail=sender_email, body=settings).execute()
        print('Delegation set successfully!')
    except HttpError as err:
        print(err)


if __name__ == '__main__':
    main()

我为桌面应用程序创建了一个项目和授权凭据.

当我第一次启动该脚本时,我收到以下错误消息:

"Access restricted to service accounts that have been delegated domain-wide authority". Details: "[{'message': 'Access restricted to service accounts that have been delegated domain-wide authority', 'domain': 'global', 'reason': 'forbidden'}]"

因此,我判断了Gmail API specification,发现此范围需要一个服务帐户.I created a Service Account,并将该范围添加到Google Workspace中.

使用新下载的Jason for the Service帐户try 该脚本后,弹出以下错误:

Traceback (most recent call last):
  File "D:\quickstart.py", line 58, in <module>
    main()
  File "D:\quickstart.py", line 31, in main
    flow = InstalledAppFlow.from_client_secrets_file(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\PC\AppData\Local\Programs\Python\Python311\Lib\site-packages\google_auth_oauthlib\flow.py", line 201, in from_client_secrets_file
    return cls.from_client_config(client_config, scopes=scopes, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\PC\AppData\Local\Programs\Python\Python311\Lib\site-packages\google_auth_oauthlib\flow.py", line 159, in from_client_config
    raise ValueError("Client secrets must be for a web or installed app.")
ValueError: Client secrets must be for a web or installed app.

安装的APP是什么意思?我创建的项目的OAuth客户端被设置为"桌面应用程序".

是代码有问题,还是服务帐户设置有问题?

推荐答案

当您使用Delegate User时,您需要使用this documentation中提到的模拟(委派的全域授权).

您需要对代码进行一些更改,才能使用服务帐户进行身份验证.你可以在谷歌文档here中看到这个例子.

这是一个有效的示例代码:

Note: In this sample, user1 is grating access to user2 to access to the inbox.

from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account



SCOPES = ['https://www.googleapis.com/auth/gmail.settings.sharing']


def main():

    # Location and name of the JSON file / Key of the services account. 

    SERVICE_ACCOUNT_FILE = 'ServiceAccountCredentials.json'
    credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    
    # User that will be impersonated
    # Email address of who will grant permission to access to the inbox
    
    delegated_credentials = credentials.with_subject('user1@domain.com')


    try:
        service = build('gmail', 'v1', credentials=delegated_credentials)

        # Email address of how is getting permission to manage the inbox 

        body = {
            'delegateEmail': 'user2@domain.com',
            'verificationStatus': 'accepted'
            }
        request = service.users().settings().delegates().create(userId='me', body=body).execute()
        print(request)
       

    except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

Python相关问答推荐

通过交换 node 对链接列表进行 Select 排序

剧作家Python:expect(locator).to_be_visible()vs locator.wait_for()

LAB中的增强数组

在Pandas 日历中插入一行

使用Keras的线性回归参数估计

使用SciPy进行曲线匹配未能给出正确的匹配

pandas DataFrame GroupBy.diff函数的意外输出

acme错误-Veritas错误:模块收件箱没有属性linear_util'

Python上的Instagram API:缺少client_id参数"

用Python解密Java加密文件

C#使用程序从Python中执行Exec文件

用NumPy优化a[i] = a[i-1]*b[i] + c[i]的迭代计算

将tdqm与cx.Oracle查询集成

如何在Polars中从列表中的所有 struct 中 Select 字段?

删除marplotlib条形图上的底边

从旋转的DF查询非NaN值

如何将一组组合框重置回无 Select tkinter?

为用户输入的整数查找根/幂整数对的Python练习

如何编辑此代码,使其从多个EXCEL文件的特定工作表中提取数据以显示在单独的文件中

来自Airflow Connection的额外参数