Initial sanitized code sync

This commit is contained in:
zqq61
2026-03-15 20:48:19 +08:00
commit 17ee51ba04
126 changed files with 22546 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
# Team 邀请小号流程分析报告
## 1. 邀请流程 (Phase-7)
完整流程在 `cmd/gptplus/main.go` 第 582-718 行:
```
Team 创建成功 → 获取 workspace token → 循环 invite_count 次:
1. 创建新 HTTP client (带独立代理 session)
2. 调用 auth.Register() 注册新账号 ← 消耗一个邮箱
3. 调用 chatgpt.InviteToTeam() 发送邀请 (POST /backend-api/accounts/{id}/invites)
4. 成员登录获取 token
5. 调用 auth.ObtainCodexTokens() 获取 Team 作用域 token (最多重试 3 次)
6. 保存成员 auth 文件
```
邀请 API: `POST /backend-api/accounts/{team_account_id}/invites`
- payload: `{"email_addresses": ["xxx@outlook.com"], "role": "standard-user", "resend_emails": true}`
- 需要 workspace-scoped access token
**注意:当前流程只发送邀请,没有"接受邀请"的步骤。** 成员注册后直接通过 `ObtainCodexTokens` 获取 Team token假设邀请自动生效因为是 admin 邀请已注册邮箱)。
---
## 2. 小号获取邮件的逻辑
### 当前行为
小号注册时调用的是**同一个 `emailProv`**(第 618 行):
```go
memberRegResult, memberRegErr := auth.Register(ctx, memberClient, emailProv, memberPassword)
```
`auth.Register()` 内部会调用 `emailProv.CreateMailbox()` 获取邮箱,然后调用 `emailProv.WaitForVerificationCode()` 获取 OTP。
### 有没有问题?
**之前有问题(已修复):** `WaitForVerificationCode` 使用的 `$filter` 查询被 Outlook REST API 拒绝InefficientFilter导致永远拿不到 OTP。现在已改为无 filter + 客户端过滤。
**潜在问题:** 无 filter 模式下拉取最近 10 封邮件,如果多个小号同时注册,收件箱里会有多封 OTP 邮件。由于有 `notBefore` 时间过滤 + `$orderby=ReceivedDateTime+desc`(最新优先),且代码取到第一个匹配的 OTP 就返回,所以**正常情况下不会混淆**。但如果两个小号在同一秒内收到 OTP理论上可能取错概率极低因为是串行注册
---
## 3. 小号是否遵循邮箱设定Outlook
**是的。** 小号使用的是同一个 `emailProv` 实例:
- 主账号和所有小号共享同一个 `OutlookProvider`
- 每次 `CreateMailbox()` 调用会返回 `accounts[nextIdx]` 并递增 `nextIdx`
- 所以小号注册时会**按顺序消耗 outmail.txt 中的 Outlook 账号**
如果配置是 `email.provider: "outlook"`,所有小号都会用 Outlook 邮箱。
---
## 4. 邮箱消耗顺序问题(核心问题)
### 场景
- outmail.txt 有 10 个邮箱 (索引 0-9)
- `invite_count: 4`
- 第一次运行:邮箱 #0 注册 Plus → Team 成功 → 邀请 4 个小号
### 当前行为
```
邮箱 #0 → 主账号注册 (CreateMailbox, nextIdx: 0→1)
邮箱 #1 → 小号1注册 (CreateMailbox, nextIdx: 1→2)
邮箱 #2 → 小号2注册 (CreateMailbox, nextIdx: 2→3)
邮箱 #3 → 小号3注册 (CreateMailbox, nextIdx: 3→4)
邮箱 #4 → 小号4注册 (CreateMailbox, nextIdx: 4→5)
```
**一次完整运行消耗 5 个邮箱1 主 + 4 小号)。**
### 下一次运行会怎样?
**会从邮箱 #0 重新开始,不是 #5。**
原因:`OutlookProvider.nextIdx` 是内存变量,每次程序启动时初始化为 0。没有持久化记录哪些邮箱已经用过。
```go
// NewOutlookProvider 每次创建时 nextIdx = 0
return &OutlookProvider{
accounts: accounts,
}, nil
```
### 后果
- 第二次运行会尝试用邮箱 #0 注册,但 #0 已经注册过 → **注册失败**
- 如果 OpenAI 返回的是 "Failed to register username" 而不是 "email already exists",程序无法区分
- 需要手动从 outmail.txt 删除已用过的邮箱,或者实现已用邮箱的持久化追踪
---
## 5. 问题汇总与建议
| # | 问题 | 严重度 | 建议 |
|---|------|--------|------|
| 1 | **nextIdx 不持久化**:重启后从 #0 开始,已用邮箱会重复注册失败 | 🔴 高 | 用文件记录已用邮箱索引,或注册成功后从 outmail.txt 中移除 |
| 2 | **无接受邀请步骤**:依赖 ObtainCodexTokens 自动加入 | 🟡 中 | 目前看起来可行,但可能需要验证在某些情况下是否需要显式 accept |
| 3 | **OTP 串号风险**:多小号共用收件箱时理论上可能取错 OTP | 🟢 低 | 串行注册 + notBefore 过滤已足够,暂不需处理 |
| 4 | **Outlook filter 已修复** | ✅ | 已改为无 filter + 客户端过滤 |