#!/usr/bin/env python3 """Gmail OAuth 授权脚本 用于首次配置 Google OAuth 并生成 token.json 文件。 运行此脚本后,浏览器会自动打开 Google 授权页面。 """ import os import sys from pathlib import Path # 添加项目根目录到 Python 路径 project_root = Path(__file__).parent sys.path.insert(0, str(project_root)) try: from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request from googleapiclient.discovery import build except ImportError: print("❌ 错误:缺少依赖库") print("请运行以下命令安装:") print(" pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client") sys.exit(1) # Gmail API 权限范围(只读) SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'] # 凭据文件路径 CREDENTIALS_FILE = project_root / "DroidBot" / "guiagent_core" / "credentials.json" TOKEN_FILE = project_root / "DroidBot" / "guiagent_core" / "token.json" def authorize_gmail(): """执行 Gmail OAuth 授权流程""" print("=" * 60) print("Gmail OAuth 授权工具") print("=" * 60) creds = None # 检查是否已有 token if TOKEN_FILE.exists(): print(f"\n✓ 发现已有 token 文件:{TOKEN_FILE}") try: creds = Credentials.from_authorized_user_file(str(TOKEN_FILE), SCOPES) print("✓ Token 加载成功") except Exception as e: print(f"⚠️ Token 加载失败:{e}") creds = None # 如果 token 无效或不存在,重新授权 if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: print("\n⏳ Token 已过期,正在刷新...") try: creds.refresh(Request()) print("✓ Token 刷新成功") except Exception as e: print(f"⚠️ Token 刷新失败:{e}") print("将进行重新授权...") creds = None if not creds: # 检查 credentials.json 是否存在 if not CREDENTIALS_FILE.exists(): print(f"\n❌ 错误:凭据文件不存在") print(f"路径:{CREDENTIALS_FILE}") print("\n请按照以下步骤操作:") print("1. 阅读文档:docs/GOOGLE_OAUTH_SETUP.md") print("2. 在 Google Cloud Console 创建 OAuth 凭据") print("3. 下载 credentials.json 并放置到上述路径") sys.exit(1) print(f"\n✓ 凭据文件已找到:{CREDENTIALS_FILE}") print("\n⏳ 开始 OAuth 授权流程...") print("提示:浏览器将自动打开,请登录 Google 账号并授权") print(" 如果看到「此应用未经 Google 验证」,点击「高级」→「继续」") try: flow = InstalledAppFlow.from_client_secrets_file( str(CREDENTIALS_FILE), SCOPES ) creds = flow.run_local_server(port=0) print("\n✓ 授权成功!") except Exception as e: print(f"\n❌ 授权失败:{e}") sys.exit(1) # 保存 token TOKEN_FILE.parent.mkdir(parents=True, exist_ok=True) with open(TOKEN_FILE, 'w') as token: token.write(creds.to_json()) print(f"✓ Token 已保存到:{TOKEN_FILE}") # 测试 API 访问 print("\n⏳ 正在测试 Gmail API 访问...") try: service = build('gmail', 'v1', credentials=creds) # 获取用户信息 profile = service.users().getProfile(userId='me').execute() email_address = profile.get('emailAddress') # 获取标签列表 results = service.users().labels().list(userId='me').execute() labels = results.get('labels', []) print("✓ Gmail API 访问成功!") print(f" 授权邮箱:{email_address}") print(f" 标签数量:{len(labels)}") if labels: print(f" 部分标签:{', '.join([l['name'] for l in labels[:5]])}") except Exception as e: print(f"❌ Gmail API 访问失败:{e}") sys.exit(1) print("\n" + "=" * 60) print("✓ Gmail OAuth 配置完成!") print("=" * 60) print(f"\n配置文件位置:") print(f" 凭据文件:{CREDENTIALS_FILE}") print(f" Token 文件:{TOKEN_FILE}") print(f"\n⚠️ 安全提示:") print(f" - 这些文件包含敏感信息,请勿提交到版本库") print(f" - 已在 .gitignore 中配置忽略规则") print(f" - Token 有效期 1 小时,过期后会自动刷新") print(f"\n现在可以使用 GuiAgent 的邮箱验证码功能了!") if __name__ == "__main__": try: authorize_gmail() except KeyboardInterrupt: print("\n\n⚠️ 授权已取消") sys.exit(1) except Exception as e: print(f"\n❌ 发生错误:{e}") import traceback traceback.print_exc() sys.exit(1)