145 lines
5.1 KiB
Python
145 lines
5.1 KiB
Python
#!/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)
|