fix(drivers/139): improve mail login credential renewal - #3029
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Several new code paths call base.RestyClient.Clone() without guarding against base.RestyClient being nil, which can cause a runtime panic in uninitialized contexts (e.g., some tests/embedded usage).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors and hardens the 139Yun mail-login renewal flow to support username/password login without requiring pre-supplied mail_cookies, refresh cookies after password/SMS auth, and avoid duplicate non-idempotent requests by disabling Resty retries for the login/SMS POSTs.
Changes:
- Removes the pre-login
JSESSIONIDdependency and uses the existing raw cookie context (if any), while persisting cookies returned by password/SMS login back into driver state. - Updates credential validation to allow full login with just
username + password(cookies optional), and avoids attempting cookie fast-login whenmail_cookiesis empty. - Updates tests and config help text to reflect the new credential-state behavior and cookie refresh semantics.
File summaries
| File | Description |
|---|---|
| drivers/139/util.go | Removes pre-login cookie sanitization, disables retries for login/SMS POSTs, persists response cookies, and relaxes credential-state requirements. |
| drivers/139/util_test.go | Reworks tests to cover password login without initial cookies, redirect stopping, and cookie persistence/reuse. |
| drivers/139/meta.go | Updates configuration help strings to document mail_cookies as optional for username/password login. |
Review details
Suppressed comments (2)
drivers/139/util.go:1303
- base.RestyClient may be nil before base.InitClient() runs; base.RestyClient.Clone() will panic. Add a nil guard and use base.NewRestyClient() as a fallback.
res, err := base.RestyClient.Clone().SetRetryCount(0).R().
SetHeaders(mailXMLHeaders(d.MailCookies)).
drivers/139/util.go:1382
- base.RestyClient.Clone() will panic if the global client hasn't been initialized (base.InitClient not called yet). Consider guarding nil and falling back to base.NewRestyClient() to keep this login path safe in tests/embedded usage.
res, err := base.RestyClient.Clone().
SetRetryCount(0).
SetRedirectPolicy(resty.RedirectPolicyFunc(func(_ *http.Request, _ []*http.Request) error {
return http.ErrUseLastResponse
})).R().
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fall back to base.NewRestyClient() when base.RestyClient has not been initialized, while preserving cloned global-client behavior and the login/SMS retry and redirect policies.
PR title:
fix(139): improve mail login credential renewalSummary / 摘要
This PR improves the 139Yun mail-login credential renewal flow so that password login no longer depends on a pre-login
JSESSIONID, can start without pre-supplied mail cookies, and can refresh reusable mail cookies after password/SMS authentication.此 PR 改进了 139Yun 邮箱登录凭据续期流程:账号密码登录不再依赖预登录阶段获取
JSESSIONID,首次配置时可不预先提供 MailCookies,并可在密码 / 短信验证后自动刷新可复用的 MailCookies。Username + password can now be used without initial
mail_cookies; existing cookie-only and Authorization flows remain supported.Password login sends the current raw mail-cookie context, merges response cookies back into driver storage state, and reuses refreshed cookies on later logins.
When supported 139 Mail risk control requires SMS verification, the driver sends one verification request, keeps the temporary cookies needed for the follow-up save, verifies
sms_code, then continues the normal token/authentication chain.Login and SMS POST requests explicitly disable Resty retries to avoid duplicate non-idempotent authentication/SMS requests.
Password login stops at the first 302 response instead of following the redirect, allowing the driver to extract the returned
siddirectly.Stale input MailCookies are allowed to fail fast-login when username/password fallback is available; MailCookies refreshed by a successful password login are expected to support subsequent fast login.
No public API or storage-format migration is introduced. The configuration schema is unchanged, but
mail_cookiesis now optional when username and password are provided.现在仅提供用户名和密码也可初始化登录;原有仅 Cookie 和 Authorization 登录方式仍保留。
密码登录会保留现有原始 MailCookies,上游响应中的新 Cookie 会合并回驱动状态,并在后续登录中复用。
遇到受支持的 139 邮箱短信风控时,会发送一次验证码请求、保留下一次保存所需的临时 Cookie,验证
sms_code后继续完成 token / Authorization 登录链路。登录和短信 POST 请求显式禁用 Resty 自动重试,避免非幂等认证请求或短信请求被重复发送。
密码登录不会继续跟随首个 302,而是直接从响应中提取
sid。用户手工提供的旧 MailCookies 失效时允许回退到账号密码登录;密码登录刷新得到的新 MailCookies 应可继续用于 fast login。
未引入公开 API 或存储格式迁移;配置字段结构不变,但在提供用户名和密码时
mail_cookies不再是必填项。This PR has breaking changes.
/ 此 PR 包含破坏性变更。
This PR changes public API, config, storage format, or migration behavior.
/ 此 PR 修改了公开 API、配置、存储格式或迁移行为。
mail_cookiesbecomes optional for username/password login; no field or storage-format migration is required.mail_cookies改为可选,不需要字段或存储格式迁移。This PR requires corresponding changes in related repositories.
/ 此 PR 需要关联仓库同步修改。
Related repository PRs / 关联仓库 PR:
Testing / 测试
go test ./...go test ./drivers/139 -count=1Deterministic tests additionally cover:
Basic-prefixed Authorization;Os_SSo_Sid/RMKEY;sms_codeclearing;Checklist / 检查清单
/ 我已阅读 CONTRIBUTING。
/ 我确认此贡献符合仓库许可证、贡献规范和行为准则。
gofmt,go fmt, orprettierwhere applicable./ 我已按适用情况使用
gofmt、go fmt或prettier格式化变更代码。/ 我已在适用情况下请求相关维护者或代码所有者审查。
AI Disclosure / AI 使用声明
/ 此 PR 包含 AI 辅助内容。
Tools used / 使用工具:
Usage scope / 使用范围:
Code generation / 代码生成
Refactoring / 重构
Documentation / 文档
Tests / 测试
Translation / 翻译
Review assistance / 审查辅助
I have reviewed and validated all AI-assisted content included in this PR.
/ 我已审核并验证此 PR 中的所有 AI 辅助内容。
I have ensured that all AI-assisted commits include
Co-Authored-Byattribution./ 我已确保所有 AI 辅助提交都包含
Co-Authored-By归属信息。I can reproduce all AI-assisted content included in this PR without any AI tools.
/ 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。