feat(registration): Add email retry mechanism for API registration failures

- Add `allow_fallback` parameter to `register_openai_account_auto()` to control fallback behavior
- Return `"retry_new_email"` status when API registration fails without fallback enabled
- Return `"domain_blacklisted"` status when domain is blacklisted during registration
- Update `register_only()` to handle and propagate `"retry_new_email"` status
- Update `register_and_authorize()` to handle and propagate `"retry_new_email"` status
- Add retry logic in `process_accounts()` to regenerate email and reinvite on API failures
- Add retry logic in `_process_single_account_worker()` to regenerate email and reinvite on API failures
- Improve error handling to distinguish between domain blacklist and API failures requiring email regeneration
This commit is contained in:
2026-01-30 12:24:40 +08:00
parent e4f330500d
commit 79c3eb733c
2 changed files with 75 additions and 9 deletions

View File

@@ -1208,11 +1208,10 @@ def register_openai_account_api(email: str, password: str, proxy: str = None,
def register_openai_account_auto(page, email: str, password: str, use_api: bool = True,
proxy: str = None, team_name: str = None) -> bool:
proxy: str = None, team_name: str = None,
allow_fallback: bool = False) -> bool:
"""自动选择模式注册 OpenAI 账号
优先使用 API 模式,失败则回退到浏览器模式
Args:
page: 浏览器实例 (用于浏览器模式回退)
email: 邮箱地址
@@ -1220,10 +1219,15 @@ def register_openai_account_auto(page, email: str, password: str, use_api: bool
use_api: 是否优先使用 API 模式
proxy: 代理地址 (API 模式使用)
team_name: Team 名称 (用于验证码超时时邀请新邮箱)
allow_fallback: 是否允许 API 失败后回退到浏览器模式 (默认 False)
Returns:
bool: 是否成功
str: 如果返回 "new_email:xxx@xxx.com:password",表示使用了新邮箱
bool/str:
- True: 成功
- False: 失败
- "retry_new_email": API 失败,需要重新生成邮箱重试
- "new_email:xxx@xxx.com:password": 使用了新邮箱
- "domain_blacklisted": 域名被列入黑名单
"""
# 如果启用 API 模式且可用
if use_api and API_MODE_AVAILABLE:
@@ -1233,12 +1237,23 @@ def register_openai_account_auto(page, email: str, password: str, use_api: bool
elif isinstance(result, str) and result.startswith("new_email:"):
# 使用了新邮箱,返回新邮箱信息
return result
elif result == "domain_blacklisted":
return "domain_blacklisted"
elif result is False:
if not allow_fallback:
log.warning("API 模式注册失败,需要重新生成邮箱重试")
return "retry_new_email"
log.warning("API 模式注册失败,回退到浏览器模式...")
# result is None 表示 API 模式不可用,直接使用浏览器模式
# result is None 表示 API 模式不可用
elif result is None and not allow_fallback:
log.warning("API 模式不可用,需要重新生成邮箱重试")
return "retry_new_email"
# 使用浏览器模式
return register_openai_account(page, email, password)
# 如果不使用 API 或允许回退,使用浏览器模式
if not use_api or allow_fallback:
return register_openai_account(page, email, password)
return "retry_new_email"
def register_openai_account(page, email: str, password: str) -> bool:
@@ -2284,6 +2299,7 @@ def register_only(email: str, password: str, use_api_register: bool = True) -> s
str: 注册结果
- "success": 注册成功
- "domain_blacklisted": 域名被列入黑名单
- "retry_new_email": API 失败,需要重新生成邮箱重试
- "failed": 注册失败
"""
with browser_context_with_retry(max_browser_retries=2) as ctx:
@@ -2300,6 +2316,11 @@ def register_only(email: str, password: str, use_api_register: bool = True) -> s
ctx.stop()
return "domain_blacklisted"
# 检查是否需要重新生成邮箱
if register_result == "retry_new_email":
ctx.stop()
return "retry_new_email"
if not register_result:
if attempt < ctx.max_retries - 1:
log.warning("注册失败,准备重试...")
@@ -2330,7 +2351,7 @@ def register_and_authorize(email: str, password: str, use_api_register: bool = T
Returns:
tuple: (register_success, codex_data, new_email_info)
- register_success: True/False/"domain_blacklisted"
- register_success: True/False/"domain_blacklisted"/"retry_new_email"
- CRS 模式: codex_data 包含 tokens
- CPA/S2A 模式: codex_data 为 None (后台自动处理)
- new_email_info: 如果使用了新邮箱,返回 {"email": "xxx", "password": "xxx"},否则为 None
@@ -2364,6 +2385,11 @@ def register_and_authorize(email: str, password: str, use_api_register: bool = T
ctx.stop()
return "domain_blacklisted", None, None
# 检查是否需要重新生成邮箱
if register_result == "retry_new_email":
ctx.stop()
return "retry_new_email", None, None
# 检查是否使用了新邮箱
if isinstance(register_result, str) and register_result.startswith("new_email:"):
# 解析新邮箱信息: "new_email:xxx@xxx.com:password"