Files
gpt-plus-gpt/tools/team_invite_analysis.md
2026-03-15 20:48:19 +08:00

100 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 + 客户端过滤 |