如何无需OAuth同意屏幕使用Gmail API?实现无人值守自动回复
无用户介入实现Gmail API自动回复的解决方案
一、关于"永久令牌"
不存在真正的永久OAuth令牌,但可以通过刷新令牌实现长期自动运行。只要用户不主动撤销权限、不修改账号密码,刷新令牌就能持续获取新的短期访问令牌,基本满足无人值守的需求。
二、服务账号的正确用法(仅Google Workspace/G Suite账号可用)
你遇到的401错误,是因为服务账号没有做域范围委派——服务账号本身没有邮箱权限,必须模拟你的主邮箱账号才能操作。个人Gmail账号无法使用服务账号 impersonate(模拟)自己的邮箱,只有Workspace账号支持。
配置步骤
- 登录Google云控制台,找到你的服务账号,进入「权限」标签,点击「添加域范围委派」,输入需要的API权限范围(比如
https://www.googleapis.com/auth/gmail.modify、https://www.googleapis.com/auth/gmail.send) - 登录Workspace管理控制台,进入「安全」→「API控制」→「域范围委派」,添加服务账号的客户端ID,同时授权刚才填写的API范围
修改后的代码
from googleapiclient.discovery import build from google.oauth2 import service_account SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.send'] SERVICE_ACCOUNT_FILE = 'service.json' # 替换成你的主邮箱地址 MAIN_EMAIL = 'your-main-email@your-domain.com' # 加载服务账号凭据并模拟主邮箱 creds = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) creds = creds.with_subject(MAIN_EMAIL) service = build('gmail', 'v1', credentials=creds) threads = service.users().threads().list(userId='me', q='is:unread').execute().get('threads', []) print(threads)
三、个人Gmail账号的替代方案
个人账号没法用服务账号,只能用带刷新令牌的OAuth授权:
- 首次运行程序时手动完成一次授权,程序会自动保存包含刷新令牌的凭据文件
- 后续每次启动,程序都会用刷新令牌自动获取新的访问令牌,无需用户介入
示例代码
from googleapiclient.discovery import build from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request import os.path SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.send'] def get_creds(): creds = None # 检查是否有保存的凭据文件 if os.path.exists('token.json'): creds = Credentials.from_authorized_user_file('token.json', SCOPES) # 刷新或重新获取凭据 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) # 保存凭据供下次使用 with open('token.json', 'w') as token_file: token_file.write(creds.to_json()) return creds service = build('gmail', 'v1', credentials=get_creds()) threads = service.users().threads().list(userId='me', q='is:unread').execute().get('threads', []) print(threads)
内容的提问来源于stack exchange,提问作者NeoN
相关产品推荐
相关产品推荐

