使用Gmail API修改其他用户签名时遇404错误求助
用Python调用Gmail API时,管理员账号修改自身签名正常,但修改其他邮箱签名时返回404错误,GAM工具可正常完成该操作。
错误信息
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://gmail.googleapis.com/gmail/v1/users/me/settings/sendAs/test_email@example.com?alt=json returned "Requested entity was not found.". Details: "[{'message': 'Requested entity was not found.', 'domain': 'global', 'reason': 'notFound'}]">
现有代码
def main(): SCOPES = 'https://www.googleapis.com/auth/gmail.settings.basic' # Check if token.pickle exists if os.path.exists(client_token_pickle): creds = Credentials.from_authorized_user_file(client_token_pickle, 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(client_oauth_file, scopes) creds = flow.run_local_server(port=8080) # Save the credentials for the next run with open(client_token_pickle, "w") as token: token.write(creds.to_json()) service = build('gmail', 'v1', credentials=creds) signature = {'signature': 'lalala'} service.users().settings().sendAs().patch(userId='me',sendAsEmail="test_email@smava.de", body=signature).execute()
解决方法
1. 调整权限范围
把原有的SCOPES改成https://www.googleapis.com/auth/gmail.settings.sharing——这个权限允许Google Workspace管理员管理域内其他用户的邮件设置,而gmail.settings.basic只能操作授权用户自己的资源。
2. 修改userId参数
调用patch接口时,不能用me作为userId,me指代的是当前授权的管理员账号,要改成目标用户的邮箱地址(比如test_email@smava.de),sendAsEmail保持目标邮箱即可。
3. 切换到服务账号授权
普通的OAuth授权流程(InstalledAppFlow)只能操作授权用户自己的资源,要操作域内其他用户,得用服务账号+域范围授权:
- 先在Google Cloud控制台创建服务账号,下载对应的JSON密钥文件。
- 在Google Workspace管理控制台中,给这个服务账号启用域范围授权,并添加
https://www.googleapis.com/auth/gmail.settings.sharing这个权限范围。 - 修改代码用服务账号模拟目标用户操作,示例代码片段:
from google.oauth2 import service_account from googleapiclient.discovery import build def main(): SCOPES = ['https://www.googleapis.com/auth/gmail.settings.sharing'] SERVICE_ACCOUNT_FILE = 'path/to/your-service-account-key.json' target_user = 'test_email@smava.de' # 加载服务账号凭证 creds = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) # 模拟目标用户 delegated_creds = creds.with_subject(target_user) service = build('gmail', 'v1', credentials=delegated_creds) signature = {'signature': 'lalala'} # 调用接口时指定目标用户ID和发件邮箱 service.users().settings().sendAs().patch( userId=target_user, sendAsEmail=target_user, body=signature ).execute()
内容的提问来源于stack exchange,提问作者TOB the BOB

