You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测Google OAuth及Gmail API登录流程中的用户授权取消

如何在Gmail API登录流程中检测用户取消操作

当调用flow.run_local_server(port=0)引导用户登录时,若用户关闭浏览器标签页或点击授权页面的"取消"按钮,脚本会持续等待无法感知取消操作。以下是具体的解决方案:

核心思路

run_local_server在用户主动取消授权时会抛出google.auth.exceptions.FlowError,浏览器意外关闭则会触发连接中断类异常。通过捕获这些异常并设置超时时间,即可及时判定用户取消了登录流程。

修改后的代码示例

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.auth.exceptions import FlowError
import socket

# 修改权限范围后请删除token.json文件
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']


def main():
    """Gmail API基础用法示例:列出用户的邮件标签"""
    creds = None
    # token.json存储用户的访问令牌和刷新令牌,首次授权完成后自动创建
    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)
            try:
                # 设置超时时间(单位:秒),避免脚本无限等待
                creds = flow.run_local_server(port=0, timeout=300)
            except FlowError as e:
                # 用户主动点击授权页面的"取消"按钮触发此异常
                print(f"用户取消了授权操作: {e}")
                return
            except (socket.timeout, ConnectionAbortedError):
                # 浏览器关闭或连接超时触发此异常
                print("登录流程超时或连接中断,用户取消了操作")
                return
        
        # 保存凭据供下次使用
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        # 调用Gmail API
        service = build('gmail', 'v1', credentials=creds)
        results = service.users().labels().list(userId='me').execute()
        labels = results.get('labels', [])

        if not labels:
            print('未找到任何邮件标签。')
            return
        print('邮件标签:')
        for label in labels:
            print(label['name'])

    except HttpError as error:
        # 开发者可在此处理Gmail API的错误
        print(f"发生错误: {error}")


if __name__ == '__main__':
    main()

关键说明

  • 捕获FlowError:用户在Google授权页面点击"Cancel"按钮时,会直接抛出该异常,明确标识用户主动取消授权。
  • 设置timeout参数:run_local_server支持timeout参数(单位为秒),超过指定时间未完成授权则触发超时异常,避免脚本无限挂起。
  • 捕获连接类异常:用户直接关闭浏览器标签页时,本地服务器会收到连接中断信号,触发ConnectionAbortedError或socket.timeout,此时可判定用户取消了操作。

内容的提问来源于stack exchange,提问作者M.L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:48:16