fix: handle signup phone entry mode before email submission

- 同步最新 dev 到 PR #113,并保留 dev 上更完整的 163 邮箱实现\n- 补充 Step 2 的手机号入口切邮箱逻辑与本地化邮箱输入识别\n- 避免把 Step 2 的 phone entry 提示误判成 auth add-phone 致命错误
This commit is contained in:
QLHazyCoder
2026-04-25 14:53:13 +08:00
105 changed files with 18669 additions and 1526 deletions
+222 -52
View File
@@ -22,13 +22,13 @@
- 刷新 OAuth 链接并登录
- 轮询登录验证码
- 自动确认 OAuth 同意页
- 把 localhost 回调提交到 CPA 或 SUB2API
- 把 localhost 回调提交到 CPA、SUB2API 或 Codex2API
## 2. 核心运行参与者
### 2.1 Sidepanel
[sidepanel/sidepanel.html](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/sidepanel.html) + [sidepanel/sidepanel.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/sidepanel.js) + [sidepanel/update-service.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/update-service.js)
[sidepanel/sidepanel.html](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/sidepanel.html) + [sidepanel/sidepanel.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/sidepanel.js) + [sidepanel/account-pool-ui.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/account-pool-ui.js) + [sidepanel/update-service.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/update-service.js) + [sidepanel/contribution-content-update-service.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/contribution-content-update-service.js)
职责:
@@ -39,8 +39,12 @@
- 动态渲染步骤列表
- 管理顶部“贡献”按钮与贡献模式主面板;贡献模式本身是 sidepanel 的运行态 UI 模式,不是新的 `panelMode` 来源
- 在贡献模式下复用同一套主自动流程启动,并在面板内展示贡献链路的 `OAUTH / 回调 / 总状态` 三块实时状态
- 在顶部“贡献/使用”按钮下方展示一个非强制的内容更新轻提示;提示来源于 `apikey.qzz.io` 的公开公告 / 教程摘要,用户关闭后仅对当前 `promptVersion` 静默,下次内容版本变化后会重新出现
- 在 sidepanel 初始化和点击“自动”按钮前刷新一次贡献站公开内容摘要;如果刷新失败,不阻塞主自动流程
- 在日志区通过“记录”按钮打开独立的邮箱记录覆盖层,并展示成功/失败/停止/重试统计与分页列表
- 查询 GitHub Releases 并展示更新卡片;当前更新服务会区分 `Pro` 与 legacy `v` 两个版本族,排序时优先保持版本族语义一致,同时会在读取缓存后重新排序,避免旧缓存把 `v` 版本误显示为比 `Pro` 更新
- 展示 HeroSMS 的接码国家与 API Key 设置,用于 OAuth 登录链路命中手机号验证页时直接续跑手机验证
- 为 Hotmail / 2925 账号池复用同一套“添加账号 / 取消添加 / 批量导入 / 收起列表”表单交互;共享的显隐控制放在 `sidepanel/account-pool-ui.js`,各自 manager 只保留 provider 相关字段校验与业务操作
### 2.2 Background Service Worker
@@ -132,12 +136,15 @@
- OAuth 链接
- 当前邮箱 / 密码
- 第 8 步固定的验证码页显示邮箱 `step8VerificationTargetEmail`
- 当前手机号验证激活记录 `currentPhoneActivation`
- 可复用的手机号验证激活记录 `reusablePhoneActivation`
- localhost 回调地址
- 自动运行轮次信息
- 当前自动运行 session 标识 `autoRunSessionId`
- 标签注册表
- 最近打开的来源地址
- LuckMail 当前运行时选择
- 2925 当前选中的账号 ID `currentMail2925AccountId`(运行时会同步到持久配置,用于重开浏览器后恢复同一个号池账号)
补充:
@@ -148,9 +155,14 @@
保存持久配置与账号运行历史:
- CPA / SUB2API 配置
- Codex2API 配置
- 邮箱 provider 配置
- Hotmail 账号池
- 2925 账号池
- 2925 是否启用号池模式 `mail2925UseAccountPool`
- 2925 当前选中的号池账号 ID `currentMail2925AccountId`
- Cloudflare / Temp Email 设置
- HeroSMS 的 API Key 与默认国家设置
- iCloud 相关偏好
- LuckMail API 配置
- 自动运行默认配置
@@ -160,7 +172,7 @@
注意:
- `contributionMode` 不属于持久配置,也不参与导入/导出;它只存在于运行态
- `panelMode` 仍然只表示 `cpa | sub2api` 来源,不能把贡献模式实现成新的来源枚举
- `panelMode` 当前表示 `cpa | sub2api | codex2api` 三个来源;贡献模式仍不是新的来源枚举
当启用了独立的账号运行历史本地同步配置时,账号运行历史会通过 [scripts/hotmail_helper.py](c:/Users/projectf/Downloads/codex注册扩展/scripts/hotmail_helper.py) 整体同步写入 `data/account-run-history.json` 快照文件,便于开发者直接查看完整记录。
这条配置链路独立于 `mailProvider` 和 Hotmail 的接码模式。
@@ -183,10 +195,10 @@
1. 用户点击顶部 `贡献`
2. sidepanel 直接通过 `SET_CONTRIBUTION_MODE` 切换运行态,不再弹确认窗口
3. 进入贡献模式后会强制 `panelMode = cpa`,并临时清空运行态 `customPassword`、禁用运行态账号记录快照同步
4. sidepanel 隐藏 CPA 管理地址、管理密钥、SUB2API 配置、自定义密码、本地同步等普通模式配置,并禁用来源选择、配置菜单和记录入口
4. sidepanel 隐藏 CPA 管理地址、管理密钥、SUB2API 配置、Codex2API 配置、自定义密码、本地同步等普通模式配置,并禁用来源选择、配置菜单和记录入口
5. 用户点击 `开始贡献` 后,不再单独走一条旁路 OAuth 流程,而是直接复用顶部 `自动` 的同一套主自动流
6. 步骤 1~6 仍按原来的注册自动化执行
7. 当主流程进入步骤 7 时,后台改为调用公开接口 `POST https://apikey.qzz.io/oauth/api/start` 申请贡献登录地址,而不是去 CPA / SUB2API 面板刷新 OAuth
7. 当主流程进入步骤 7 时,后台改为调用公开接口 `POST https://apikey.qzz.io/oauth/api/start` 申请贡献登录地址,而不是去 CPA / SUB2API / Codex2API 来源刷新 OAuth
8. 步骤 7 拿到 `session_id / auth_url / state` 后,继续沿用原有登录链路进入授权页
9. 步骤 9 仍负责捕获 localhost callback;贡献模式下后台也会持续监听导航变化,必要时提前兼容处理 callback
10. 步骤 10 在贡献模式下不再打开 CPA 管理页,而是围绕公开贡献会话做 callback 提交兼容和最终状态确认;当状态进入 `auto_approved / auto_rejected / manual_review_required / expired / error` 时结束
@@ -204,6 +216,26 @@
- 安全边界仍然在服务端;扩展只负责公开 OAuth 贡献前端流程
- 退出贡献模式后,要恢复普通模式 UI,并恢复持久配置中的自定义密码/本地同步偏好
### 4.5 贡献内容更新提示链路
这条链路用于把 `apikey.qzz.io` 上的公开公告 / 使用教程更新,映射成 sidepanel 顶部“贡献/使用”按钮下方的轻提示。
1. 贡献站公开暴露 `GET https://apikey.qzz.io/api/content-summary`
2. 接口返回 `announcement / tutorial` 两类内容的可见状态、更新时间,以及聚合后的 `promptVersion`
3. `sidepanel/contribution-content-update-service.js` 负责拉取这个摘要,并在本地缓存最近一次可用结果
4. `sidepanel.js` 在 sidepanel 初始化时会先拉一次摘要;如果当前 `promptVersion` 没被本地关闭过,就显示提示
5. 用户点击提示右侧 `X` 后,只会把当前 `promptVersion` 记入 `localStorage`,不会永久关闭整个能力
6. 当公告或教程再次更新,服务端返回新的 `promptVersion`,提示会重新出现
7. 用户点击“自动”按钮时,sidepanel 会在真正启动自动流程前再刷新一次摘要,尽量让提示状态更及时
8. 如果这次刷新失败,sidepanel 只记录警告并继续自动流程,不会因为提示链路故障阻塞主功能
这条链路的关键边界是:
- 它只消费公开摘要接口,不接触任何管理接口
- 它只影响顶部轻提示,不改变贡献模式主状态机
- 它使用 `localStorage` 做缓存和关闭版本记录,而不是写入 `chrome.storage.session/local`
- 它是辅助提示链路,不允许反向阻塞自动运行
## 5. 内容脚本通信链路
### 5.1 READY 机制
@@ -262,11 +294,12 @@
1. 解析本轮应使用的邮箱
2. 打开或复用注册页
3. 点击注册入口并提交邮箱
4. 以当前邮箱先写入一条“停止(流程尚未完成)”的记录占位
5. 等待邮箱提交后的真实落地页
6. 如果进入密码页,则继续执行 Step 3
7. 如果直接进入邮箱验证码页,则自动跳过 Step 3 并进入 Step 4
3. 如果注册弹窗默认停留在手机号输入模式,会先尝试点击 `继续使用电子邮件地址登录 / Continue using email address` 一类按钮切回邮箱输入模式
4. 在邮箱输入模式下提交邮箱;邮箱输入框识别同时兼容本地化占位与 `aria-label`
5. 以当前邮箱先写入一条“停止(流程尚未完成)”的记录占位
6. 等待邮箱提交后的真实落地页
7. 如果进入密码页,则继续执行 Step 3
8. 如果直接进入邮箱验证码页,则自动跳过 Step 3 并进入 Step 4
### Step 3
@@ -284,6 +317,7 @@
6. 上报完成后再异步点击提交,避免页面跳转打断响应通道
7. 延迟提交真正触发前会再次检查 Stop 状态,避免用户已停止时页面仍继续自动提交
8. 后台在真正确认 Step 3 完成前,会额外检查提交后是否切换页面;如果出现认证页 `Try again / 重试` 页面,或 `/email-verification` 上的 `405 / Route Error` 重试页,会先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复,再继续后续链路
9. Step 3 收尾阶段如果页面切换导致旧内容脚本失联,后台会把单次消息等待收口到当前收尾预算内,优先尽快重试重连;若最终仍未恢复,则输出中文的步骤级错误,而不是直接暴露底层英文通信超时
### Step 4 / Step 8
@@ -305,14 +339,19 @@
补充行为:
- `2925` provider 会关闭 Step 4 / 8 的自动重发间隔 25 秒节流;每次“重新发送验证码”之间,会在邮箱页内部执行一轮固定 15 次的刷新轮询,不再因 OAuth 剩余时间预算而缩短。
- 普通邮箱仍会携带 `filterAfterTimestamp` 做时间窗筛选;`2925` 当前既不依赖时间窗,也不再做“新旧邮件快照差集”比较,而是每次刷新后直接遍历当前列表中的匹配邮件
- 当 provider 为 `2925` 时,Step 4 会优先直接打开当前 2925 邮箱页,并先比对页面顶部显示的邮箱地址是否与当前目标邮箱一致:如果一致,就直接复用当前已登录页面;如果不一致且启用了 2925 账号池,则会先清理 cookie 再登录当前选中的账号;如果不一致且未启用账号池,则直接复用现有停止逻辑结束流程。Step 8 不再额外承接这套登录态处理
- `2925` 在执行自动登录后,如果登录页因为跳转或重载导致原内容脚本通信中断,后台不会立刻判失败;而是会等待当前标签页重新加载完成、重新确认内容脚本就绪后,再继续确认是否已经进入收件箱。这段登录恢复窗口当前按 2 分钟控制。
- 普通邮箱仍会携带 `filterAfterTimestamp` 做时间窗筛选;`2925` 在 Step 4 / Step 8 会固定使用“步骤开始时间向前回看 10 分钟”的时间窗,不再做“新旧邮件快照差集”比较,而是每次刷新后直接遍历当前列表中落在该固定时间窗内的匹配邮件。
- 自动重新发送验证码次数现在使用 sidepanel 里的单一“验证码重发”配置;普通邮箱仍按 25 秒间隔节流,Hotmail / 2925 不走这个 25 秒间隔。Step 4 若启用先请求新验证码,会先消耗一次当前步骤的自动重发次数。
- 验证码提交重试上限当前为 15 次;页面明确拒绝验证码时,会在上限内继续拉取新验证码并重提。
- `2925` 内容脚本会把每一封实际打开检测的邮件立即删除;同一验证码步骤启动后,试过的验证码会按“步骤 ID + 启动时间”隔离缓存,不会在本次步骤里重复提交;如果再次遇到相同验证码,对应邮件也会在读取后立即删除,避免后续反复打开。
- `2925` 当前不再对邮件里的收件邮箱做比对,只要邮件内容命中 ChatGPT / OpenAI 验证码过滤条件,就会尝试该邮件。
- `2925` 在 provide 模式下仍保持宽松匹配:只要邮件内容命中 ChatGPT / OpenAI 验证码过滤条件,就会尝试该邮件。
- `2925` 在 receive 模式下会恢复“弱目标邮箱匹配”:只有当邮件里显式出现了其他收件邮箱时才会跳过;如果邮件里没有明确写出邮箱,仍允许继续尝试该验证码。
- 手动点击 Step 4 重新执行时,后台会先检查 `signup-page` 认证页标签是否仍然存在;如果步骤 1 / 2 打开的认证页已经关闭,就会直接提示“请先执行步骤 1 或步骤 2,确保认证页仍然打开并停留在验证码页”,不会先重置后续步骤再报技术错误。
- 当验证码最终提交成功后,后台会异步向 2925 邮箱页发送 `DELETE_ALL_EMAILS`,执行“全选 + 删除”清理剩余邮件,不阻塞主流程。
- 如果 `2925` 邮箱页在轮询期间出现“子邮箱已达上限邮箱”,后台会记录当前时间,把当前 2925 账号禁用 24 小时,自动切到下一个可用账号并完成登录,然后直接报错结束当前尝试;如果 Auto 开启了自动重试,现有控制器会按原逻辑进入下一次尝试。
- Auto 模式下,如果 Step 4 当前轮失败,后台会沿用当前邮箱回到 Step 1 重新开始当前轮,而不是立刻换邮箱开新尝试
- Auto 模式下,普通 Step 4 失败仍会沿用当前邮箱回到 Step 1 重新开始当前轮;但若失败原因是 2925 主动要求“结束当前尝试”,则不会再回到 Step 1 重开,而是直接把错误抛给自动重试控制器
### Step 5
@@ -349,7 +388,10 @@
流程:
1. 通过 CPA / SUB2API 刷新 OAuth 地址
1. 按当前来源刷新 OAuth 地址
- CPA:打开管理页并读取 OAuth 地址
- SUB2API:打开后台并生成 OAuth 地址
- Codex2API:直接调用后台协议 `/api/admin/oauth/generate-auth-url`
2. 打开最新 OAuth 链接
3. 登录;如果进入密码页且当前有密码,则填写并提交密码;如果当前没有密码但检测到一次性验证码入口,则直接切换到一次性验证码登录
4. 确保真正进入验证码页
@@ -359,7 +401,7 @@
贡献模式补充:
- 贡献模式下,步骤 7 不再从 CPA / SUB2API 面板刷新 OAuth,而是直接调用公开贡献接口 `/oauth/api/start`
- 贡献模式下,步骤 7 不再从 CPA / SUB2API / Codex2API 来源刷新 OAuth,而是直接调用公开贡献接口 `/oauth/api/start`
- 贡献接口返回的 `auth_url` 会写回运行态 `oauthUrl`,后续步骤 7 / 8 / 9 继续复用现有授权链路
### Step 8
@@ -375,13 +417,16 @@
3. 打开邮箱页或 API 轮询入口
4. 轮询登录验证码
5. 回填登录验证码
6. 如果登录验证码提交后页面进入 `add-phone / 手机号页`,则立即判为 fatal 错误,不再把步骤 8 视为成功
6. 如果登录验证码提交后页面进入 `add-phone / 手机号页`,则步骤 8 会保留“登录验证码已提交成功”的结果,并把后续手机号验证需求继续交给步骤 9 处理
7. 如遇邮箱轮询类失败或显式的 `STEP8_RESTART_STEP7` 恢复错误,则按有限次数回到 Step 7 重试
8. 获取到登录验证码后不再触发“刷新 OAuth 并重走 Step 7”的前置回放,直接在当前验证码页提交并继续进入 Step 9
补充:
-`2925` 而言,Step 8 不依赖验证码页显示邮箱做收件匹配,而是直接测试所有命中 ChatGPT / OpenAI 过滤条件的邮件。
-`2925 provide` 而言,Step 8 不依赖验证码页显示邮箱做收件匹配,而是直接测试所有命中 ChatGPT / OpenAI 过滤条件的邮件。
-`2925 receive` 而言,Step 8 会把当前目标注册邮箱一并传给 2925 内容脚本;只有当邮件里显式写出了其他邮箱时才会跳过,从而在不破坏历史兼容性的前提下,尽量降低误收验证码的概率。
-`custom` provider 而言,Step 8 仍使用手动验证码确认弹窗;弹窗当前额外提供“出现手机号验证”按钮,点击后会直接抛出与真实 `add-phone` 页面一致的 fatal 错误,供 Auto 按既有 add-phone 分支继续下一邮箱。
- 当登录验证码提交后进入 `phone-verification` 页时,内容脚本会显式把该页面识别为“手机验证码页”,避免与邮箱验证码页混淆。
### Step 9
@@ -392,9 +437,16 @@
流程:
1. 监听 localhost callback
2. 准备 OAuth 同意页
3. 尝试多轮点击“继续”
4. 一旦捕获 localhost callback,写入状态并完成步骤
2. 准备 OAuth 同意页;如果页面已进入 `add-phone / phone-verification`,先切入手机号验证共享流程
3. 手机号验证共享流程会按当前 sidepanel 中保存的 HeroSMS 国家与 API Key 申请或复用号码、提交号码、轮询短信验证码,并在验证码被拒绝或长时间收不到短信时决定重发、换号或把自动流拉回 Step 7
4. 手机号验证完成后,继续等待 OAuth 同意页出现
5. 尝试多轮点击“继续”
6. 一旦捕获 localhost callback,写入状态并完成步骤
补充:
- HeroSMS 号码当前最多复用 3 次成功注册;超过上限后会清空可复用激活记录,下次重新申请新号码。
- 如果同一个号码在重发短信后 60 秒仍收不到验证码,后台会抛出“回到步骤 7 重新拿新号码”的恢复错误,而不是把当前号码无限重试下去。
### Step 10
@@ -405,15 +457,22 @@
流程:
1. 校验 localhost callback 是否有效
2. 判断是 CPA 还是 SUB2API
3. 打开相应后台
4. 提交回调地址
2. 判断当前来源是 CPA、SUB2API 还是 Codex2API
3. CPA / SUB2API 打开相应后台;Codex2API 直接走协议分支,不打开后台页面
4. 提交回调地址或等价的授权码交换请求
5. 仅当出现精确成功徽标,且该徽标不是红色/错误态、页面上也没有同时可见的失败提示时,才判定成功
6. 识别 `认证失败:*``认证失败: timeout of 30000ms exceeded``回调 URL 提交失败: oauth flow is not pending` 等失败提示并立即报错
7. 完成平台侧验证
8. 追加账号运行历史成功记录
9. 做成功后的清理与标记
Codex2API 补充:
- 步骤 7 直接调用 `POST /api/admin/oauth/generate-auth-url` 获取 `auth_url / session_id`
- 授权页仍沿用现有 OpenAI 登录、验证码、OAuth 同意页与 localhost callback 主链
- 步骤 10 直接调用 `POST /api/admin/oauth/exchange-code`,用 callback 中的 `code / state` 完成账号创建
- Codex2API 这条来源不新增 panel content script,也不依赖“添加账号 -> OAuth 授权 -> 生成授权链接”页面按钮 DOM
贡献模式补充:
- 贡献模式下,步骤 10 不再打开 CPA 管理页
@@ -424,29 +483,59 @@
### 7.1 2026-04-17 补充:Gmail / 2925 统一别名邮箱链路
本轮将 Gmail 与 2925 的注册邮箱逻辑统一收敛为“共享别名邮箱链路”:
本轮将 Gmail 与 `2925 + provide` 的注册邮箱逻辑统一收敛为“共享别名邮箱链路”:
- 两者都先填写“基邮箱”
- Gmail`name@gmail.com`
- 2925`name@2925.com`
- 2925(仅 provide 模式)`name@2925.com`
- 两者都允许两种入口:
- 点击侧边栏按钮自动生成完整注册邮箱
- 直接在“注册邮箱”输入框中手动填写完整邮箱
-`mailProvider = 2925``mail2925Mode = receive` 时,不再走别名基邮箱链路,而是回退到普通“邮箱生成 / 手动填写注册邮箱”路线;2925 仅负责后续收信与登录态管理
当前行为约定:
1. sidepanel 展示“别名基邮箱”输入框,并根据当前 provider 显示对应文案
1. sidepanel 会根据当前 provider 与 `mail2925Mode` 决定是否展示“别名基邮箱”输入框
2. 点击 `获取 / 生成` 时:
- Gmail 生成 `name+tag@gmail.com`
- 2925 生成 `name123456@2925.com`
- 2925 仅在 provide 模式下生成 `name123456@2925.com`
3. Step 2 / Step 3 进入注册流程前,会先判断当前 `state.email`
- 如果已经是与当前基邮箱兼容的完整邮箱,则直接复用
- 如果为空或不兼容,则按当前 provider 重新生成
4. 保存或执行 Step 3 时,如果手动填写的完整邮箱与当前 Gmail / 2925 基邮箱不兼容,sidepanel 会直接拦截
- 如果为空或不兼容,则按当前 provider / mode 重新生成
4. 保存或执行 Step 3 时,如果手动填写的完整邮箱与当前 Gmail / 2925 provide 基邮箱不兼容,sidepanel 会直接拦截`2925 receive` 不参与这条兼容性约束
5. auto-run fresh attempt reset 时,会保留:
- `gmailBaseEmail`
- `mail2925BaseEmail`
### 7.1.1 2026-04-23 补充:自定义邮箱池链路
本轮新增 `custom-pool` 生成方式,用于把一批已准备好的邮箱按顺序并入现有自动流,而不是继续为每种邮箱页面单独适配一套“新地址生成器”。
当前行为约定:
1. sidepanel 在 `邮箱生成` 中新增 `自定义邮箱池` 选项,并显示多行 `邮箱池` 输入框
2. 输入框中的邮箱会按“每行一个”归一化为数组,写入持久配置 `customEmailPool`
3. Auto 启动前会先保存当前配置;如果当前生成方式是 `custom-pool`,则自动把总轮数锁定为邮箱池长度
4. 后台在每个目标轮次开始前,会按 `targetRun` 从邮箱池读取对应邮箱,并写入当前 `state.email`
5. 同一目标轮次里的失败重试会继续复用该轮邮箱,不会提前跳到下一个
6. 如果当前目标轮次超出了邮箱池数量,后台会直接报错提示数量不一致
7. 自定义邮箱池只负责“本轮注册邮箱分配”,实际收码仍由当前 `mailProvider` 对应的既有链路负责
### 7.1.2 2026-04-23 补充:自定义邮箱服务号池链路
本轮给 `mailProvider = custom` 这条链路补上了“号池式注册邮箱分配”,目标是让“手动验证码模式”也能稳定跑多轮不同邮箱,而不是每轮都手动改一次注册邮箱。
当前行为约定:
1. sidepanel 在 `邮箱服务 = 自定义邮箱` 时,会额外显示 `自定义号池` 文本框
2. 文本框中的邮箱会按“每行一个”归一化为数组,写入持久配置 `customMailProviderPool`
3. 如果当前 `Mail = 自定义邮箱` 且号池不为空,Auto 启动前会把总轮数锁定为号池长度
4. 后台在每个目标轮次开始前,会按 `targetRun``customMailProviderPool` 读取对应邮箱,并写入当前 `state.email`
5. 只要当前邮箱还没成功认证、也没出现 `add-phone / 手机号验证`,Auto 就会继续复用该邮箱重试,不会提前切到下一个
6. 只有当当前邮箱成功完成整轮,或明确进入 `add-phone / 手机号验证` fatal 分支时,Auto 才会切到号池中的下一个邮箱
7. 如果当前目标轮次超出了号池数量,后台会直接报错提示数量不一致
8. 这条链路只影响“注册邮箱分配”;Step 4 / Step 8 仍然走 `custom` provider 既有的手动验证码确认逻辑
### 7.2 共享模块分工
- `managed-alias-utils.js`
@@ -473,6 +562,7 @@
- Duck
- Cloudflare
- Cloudflare Temp Email
- 自定义邮箱池
- iCloud 隐私邮箱
### 7.2 Hotmail
@@ -482,6 +572,8 @@
- [hotmail-utils.js](c:/Users/projectf/Downloads/codex注册扩展/hotmail-utils.js)
- [microsoft-email.js](c:/Users/projectf/Downloads/codex注册扩展/microsoft-email.js)
- [scripts/hotmail_helper.py](c:/Users/projectf/Downloads/codex注册扩展/scripts/hotmail_helper.py)
- [sidepanel/hotmail-manager.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/hotmail-manager.js)
- [sidepanel/account-pool-ui.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/account-pool-ui.js)
模式:
@@ -492,6 +584,7 @@
- 本地 helper 除了收信与验证码读取,还提供邮箱记录 JSON 快照同步接口。
- 账号运行历史本地同步由独立配置控制,不再绑定 Hotmail 的本地助手模式。
- sidepanel 中 Hotmail 账号池的新增表单默认收起,头部通过共享按钮切换“添加账号 / 取消添加”;表单显隐、按钮文案切换、清空与聚焦都复用 `sidepanel/account-pool-ui.js`,不在 Hotmail manager 内重复实现一套。
### 7.3 LuckMail
@@ -500,27 +593,97 @@
- [luckmail-utils.js](c:/Users/projectf/Downloads/codex注册扩展/luckmail-utils.js)
- LuckMail 相关后台领域逻辑仍在 [background.js](c:/Users/projectf/Downloads/codex注册扩展/background.js)
### 7.4 iCloud
### 7.4 2925 账号池
组成:
- [mail2925-utils.js](c:/Users/projectf/Downloads/codex注册扩展/mail2925-utils.js)
- [background/mail-2925-session.js](c:/Users/projectf/Downloads/codex注册扩展/background/mail-2925-session.js)
- [sidepanel/mail-2925-manager.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/mail-2925-manager.js)
- [sidepanel/account-pool-ui.js](c:/Users/projectf/Downloads/codex注册扩展/sidepanel/account-pool-ui.js)
职责:
- `mail2925-utils.js`
统一承接 2925 账号池的归一化、冷却期判断、可用账号挑选、导入格式解析与列表更新。
- `background/mail-2925-session.js`
统一承接 2925 账号池的持久化、当前账号切换、cookie 清理登出、网页登录态确认、自动登录,以及命中“子邮箱已达上限邮箱”后的 24 小时禁用与自动切号。
- `sidepanel/mail-2925-manager.js`
负责 2925 账号池的新增、导入、切换、手动登录、禁用、清冷却与删除。
- `sidepanel/account-pool-ui.js`
负责 Hotmail / 2925 账号池共用的新增表单显隐、头部按钮文案切换、清空表单与首字段聚焦;2925 manager 不再单独维护另一套表单开关状态机。
链路:
1. 用户在 sidepanel 的 2925 账号池中保存 `email / password`
2. sidepanel 中会单独展示 `提供邮箱 / 接收邮箱` 模式切换,以及独立的 `2925 号池` 开关 / 当前账号下拉框;这样即使切到 receive 模式,账号池设置也不会被别名基邮箱行一起隐藏
3. 只有当 sidepanel 中的 `mail2925UseAccountPool` 开关开启时,provide 模式下的别名基邮箱才会优先取当前账号池选中的 2925 账号邮箱;关闭时会回退到原来的手填 `mail2925BaseEmail`
4. 手动点击 `登录` 或自动流程进入 Step 4 前,后台会先打开当前 2925 邮箱页,并读取页面顶部当前邮箱地址:如果仍停留在收件箱且顶部邮箱与目标邮箱一致,则直接复用;如果顶部邮箱不一致且启用了号池模式,则先清理 cookie 后登录当前选中的账号;如果顶部邮箱不一致且未启用号池模式,则直接调用现有停止逻辑结束流程;如果页面跳到登录页,则仍然只有号池模式开启时才自动登录
5. 一旦轮询期间出现“子邮箱已达上限邮箱”,后台会先判断是否启用了号池模式:若已启用且还有下一个可用账号,则把当前账号禁用 24 小时并自动切到下一个账号重新登录;若未启用,则直接调用现有停止逻辑结束流程
6. 如果登录页已经识别到账号密码输入框,内容脚本会在填完账号密码后额外等待 1 秒再点击登录;若点击登录后 40 秒内仍未进入收件箱,且当前正处于自动运行中,则后台会直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态;这类情况常见于图片验证、行为验证或其他阻断登录的中间页
7. 如果没有下一个可用账号,或当前未启用号池模式,则不会继续消耗自动重试次数,而是直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态
8. sidepanel 中 2925 账号池的新增表单也走与 Hotmail 相同的共享交互:默认收起,头部按钮切换“添加账号 / 取消添加”,操作行右侧提供“批量导入”,保存成功后自动收起并清空。
9. 当 2925 号池模式开启时,当前选中的号池邮箱会同步回写到同一个 `mail2925BaseEmail` 字段;因此用户切换号池账号后,即使再次关闭号池模式,也会直接沿用刚才选中的邮箱作为手动基邮箱,无需重新输入。
### 7.4.1 2925 双模式维护约定
这是后续维护 `2925` 时最容易被重新打散的一段链路,建议按下面的职责边界理解:
- UI 层:
- `sidepanel/sidepanel.html`
- 负责展示 `提供邮箱 / 接收邮箱`
- 负责展示独立的 `2925 号池` 配置行
- 不负责决定“2925 是否参与别名邮箱生成”
- `sidepanel/sidepanel.js`
- 只负责把当前 `mail2925Mode`、号池开关、当前账号选择同步到 state / runtime message
- 只负责用共享规则决定当前文案、显隐和前端校验
- 不应再次复制一套“provide / receive 对应什么行为”的业务判断
- 共享规则层:
- `managed-alias-utils.js`
- 负责 `mail2925Mode` 归一化
- 负责判断 `2925` 当前是否属于“别名邮箱 provider”
- 负责保证 `2925` 只有在 `provide` 模式下才进入共享别名邮箱链路
- 如果未来要新增第三种模式,应该先改这里,再改 sidepanel / background 接线
- 注册邮箱生成层:
- `background/generated-email-helpers.js`
- 只负责根据当前 provider / mode 选择“共享别名邮箱”还是“普通邮箱生成器”
- 不负责定义 `provide / receive` 的语义本身
- `background/signup-flow-helpers.js`
- 只负责真正提交前的“复用已有邮箱 / 重新生成邮箱”
- 这里看到的 `isGeneratedAliasProvider(state)` 已经包含 `mail2925Mode` 语义,不应该再手写 `state.mail2925Mode === 'provide'`
- 收信与验证码层:
- `background/verification-flow.js`
- 负责决定是否给 2925 内容脚本下发 `mail2925MatchTargetEmail`
- 当前约定:仅 `receive` 模式开启弱目标邮箱匹配
- `content/mail-2925.js`
- 负责真正执行“弱目标邮箱匹配”
- 当前约定:只有邮件里显式出现了其他邮箱才跳过;若邮件里没有写邮箱,仍允许继续尝试
- 这样做的目的,是在不破坏历史兼容性的前提下,降低 receive 模式误收验证码的概率
- 账号池与登录态层:
- `background/mail-2925-session.js`
- 不关心 `provide / receive` 哪个负责生成注册邮箱
- 只关心当前是否允许自动登录、是否需要切号、是否命中上限、是否需要停止自动流程
- 因此后续如果只改别名生成语义,不应把这层重新卷入 provider 判定
后续如果再改 `2925`,建议最少按下面顺序自检:
1. `managed-alias-utils.js` 是否仍是 `provide / receive` 的唯一共享语义来源
2. `sidepanel/sidepanel.js` 是否只做接线,没有复制业务规则
3. `background/generated-email-helpers.js` / `background/signup-flow-helpers.js` 是否仍然只做调度,不重复写模式语义
4. `background/verification-flow.js``content/mail-2925.js` 的“弱目标邮箱匹配”是否保持同步
5. `项目文件结构说明.md` 与当前文件是否已同步更新
### 7.5 iCloud
组成:
- [icloud-utils.js](c:/Users/projectf/Downloads/codex注册扩展/icloud-utils.js)
- [content/icloud-mail.js](c:/Users/projectf/Downloads/codex注册扩展/content/icloud-mail.js)
### 7.5 163 / 163 VIP
组成:
- [content/mail-163.js](c:/Users/projectf/Downloads/codex注册扩展/content/mail-163.js)
当前行为:
1. 先在 163 收件箱列表中按发件人、主题、`aria-label` 和时间窗口筛选候选邮件
2. 如果列表文本已经直接包含 6 位验证码,则直接返回验证码
3. 如果列表文本未直接包含验证码,则自动打开候选邮件正文
4. 从正文可见文本与同源 iframe 文本中提取验证码
5. 读取后回到收件箱列表,继续后续轮询或清理流程
## 8. 自动运行完整链路
文件:
@@ -533,6 +696,8 @@
2. 为本轮自动流程分配唯一 `autoRunSessionId`
3. 计算是否从中断点继续
4. 每轮执行前重置必要运行态
- 如果当前 `Mail = 自定义邮箱` 且配置了 `customMailProviderPool`,会先按当前目标轮次把号池中的对应邮箱写回运行态
- 如果当前生成方式是 `custom-pool`,会先按当前目标轮次把邮箱池中的对应邮箱写回运行态
5. 执行 `runAutoSequenceFromStep`
- 步骤 7 内部仍保留登录态恢复的有限重试,但 `add-phone / 手机号页` 属于立即跳出的不可重试错误
- 步骤 8 若在验证码提交后进入 `add-phone / 手机号页`,会直接抛出 fatal 错误,不再先标记步骤成功
@@ -573,6 +738,10 @@
5. Step 4 / 7 的验证码流
6. 成功收尾逻辑
如果来源本身提供稳定协议接口,还必须额外判断:
7. 是否可以不打开来源后台页面,直接把步骤 7 / 10 收敛到协议分支
### 新增配置项
必须同时检查:
@@ -599,14 +768,15 @@
- 新增共享恢复层:`content/auth-page-recovery.js`
- Step 4 在等待注册验证码页时,如果命中认证页 `Try again / 重试` 页,或 `/email-verification` 上的 `405 / Route Error` 重试页,会先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复,再继续回到密码页重提和验证码页确认流程。
- 但如果 Step 4 的认证重试页正文中出现 `user_already_exists`,则会直接视为“当前用户已存在”:不点击 `重试`,不再回到步骤 1 重开当前轮,而是立即结束当前轮;开启自动重试时直接进入下一轮。
- Step 7 在识别到登录超时报错页时,会先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复当前页面;若仍未恢复,则按原有可恢复失败逻辑重跑 Step 7。
- Step 7 在识别到登录超时报错页时,会先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复当前页面;恢复成功后会优先按当前页面状态继续当前登录流程,例如直接续跑邮箱页或密码页;只有仍未恢复到可继续状态时,才按原有可恢复失败逻辑重跑 Step 7。
- Step 7 在首次识别到登录验证码页后,不会立刻把步骤判定为成功;还会额外做一轮“收尾确认”,确保页面稳定停留在登录验证码页。如果只是短暂进入验证码页、随后又掉进登录重试页,则会先走共享恢复逻辑,再按既有可恢复失败逻辑重跑 Step 7。
- Step 7 的这轮收尾确认是主要责任边界;Step 8 默认建立在“登录验证码页已经由 Step 7 稳定确认”的前提上,只在后台入口保留防御性回退判断,不替代 Step 7 收尾。
- Step 8 如果发现认证页已经进入登录超时报错/重试页,会直接报错并回到 Step 7 重新开始,而不是在 Step 8 内部点击 `重试`
- Step 8 的登录重试页判定也覆盖 `/email-verification` 上的 `405 / Route Error`,避免这类页面被误当成普通未知页。
- 任意认证页重试页如果正文中出现 `max_check_attempts`,会被视为 Cloudflare 风控触发:后台立刻完全停止流程,侧边栏会复用现有确认弹窗提示等待 15~30 分钟后再试,避免继续刷新或反复重试加重风控,确认按钮显示为“我知道了”。
- Step 9 在点击 OAuth 同意页 `继续` 后,会额外检查是否进入认证页重试页;若命中则先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复,再重新执行当前轮的 `继续` 点击
- Step 9 在点击 OAuth 同意页 `继续` 后,会持续等待页面跳转;若点击后命中认证页重试页,则直接报错,不会在 Step 9 内部点击 `重试`
## 2026-04-21 2925 邮件时间窗补充
## 2026-04 Step 2 手机号态说明
- Step 2 如果发现注册弹窗默认处于手机号输入模式,会先尝试点击 继续使用电子邮件地址登录 / Continue using email address 这类按钮,切回邮箱输入模式后再继续填写邮箱。
- Step 2 对邮箱输入框的识别不再只依赖英文 email,也会接受 电子邮件地址、邮箱 等本地化占位或 ria-label。
- Step 2 日志里的“手机号输入模式”只表示注册弹窗当前默认展示了手机号输入框,本身不等同于 auth dd-phone 致命页;只有明确进入认证流程的手机号页面时,自动运行才会按 fatal 停止。
- `2925` 在 Step 4 / Step 8 现在会携带固定的步骤开始时间窗口,实际筛选下限为“步骤开始时间向前回看 10 分钟”。
- 为了保留这段固定时间窗内已经到达的验证码邮件,后台不再在轮询开始前预先清空 2925 邮箱。
- `2925` 验证码最终提交成功后,后台仍会异步发送 `DELETE_ALL_EMAILS` 做收尾清理。