Skip to content

fix(mail): SMTP send retry (2x2s) + 502 on verification-code send failure (rant 2026-08-21T23:52:17) - #112

Merged
argszero merged 1 commit into
mainfrom
fix/smtp-retry
Aug 21, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/smtp-retry

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Fault tolerance for the verification-code email path per host rant 2026-08-21T23:52:17 (project=aitokenpool). Gmail (and similar providers) intermittently and silently drop connections from datacenter IPs (Alibaba/Tencent Cloud etc.) — TCP/TLS succeed but the SMTP banner never arrives, lettre times out after 15s, HTTP 500. This is external-service unreliability, so the fix is app-level:

  • SMTP send retry (src/mail.rs): new send_with_retry helper — 1 initial attempt + up to 2 retries with a fixed 2s delay, fresh transport per attempt (new TCP+TLS connection, matching the observed transient-drop pattern). Errors only after all 3 attempts fail.
  • Semi-registration fallback (src/routes/mod.rs send_code): on final SMTP failure, the verification record is cleared (releases the 60s resend rate limit, so the user can resend immediately instead of being stuck) and the API returns 502 + 「验证码发送失败,请重试」 (was 500) — register/resend/forgot-password all benefit.

Related Issue

Host rant 2026-08-21T23:52:17.109049+08:00 (project=aitokenpool), verbatim:

SMTP 发送验证码间歇性超时 + 半注册账号卡死问题(线上 dev 实测)

建议修复

  1. SMTP 发送加重试(核心):发送失败(Connection/TimedOut 类错误)后延迟 2-3s 重试,最多 2 次;重试仍失败才报错返回;重试间隔用固定 2s 即可
  2. 半注册账号兜底(连带问题):注册时验证码发送失败 → 建议:注册接口发送失败时返回明确错误(如 502 + 「验证码发送失败,请重试」),并允许该邮箱重新注册/重发;检查 resend-code 对 verified=0 账号是否已有 60s 限频(若有,失败后的重发不要被限频卡住)
  3. 测试:模拟 SMTP 连接失败 → 断言重试后成功;mock 恒失败 → 断言最终报错且不无限重试

Changes

  • SMTP retry: up to 2 retries × fixed 2s delay, fresh transport per attempt
  • 502 + clear error on final send failure (was 500)
  • Verification record cleared on failure → resend not blocked by the 60s rate limit
  • Tests: retry succeeds after transient failures / no infinite retry / last-error propagated (3 unit tests) + register-smtp-failure → 502 integration test (resend right after is not rate-limited)

Tests

  • cargo test — 136/136 passed (132 + 4 new)
  • cargo fmt --check — clean
  • cargo clippy --all-targets -- -D warnings — clean

Checklist

  • Branch name follows convention (fix/smtp-retry)
  • Commit message uses Conventional Commits
  • Single responsibility, minimal change

…lure (rant 2026-08-21T23:52:17)

- mail.rs: send_with_retry helper (1 initial + 2 retries, fixed 2s delay,
  fresh transport per attempt — Gmail silently drops datacenter IPs
  intermittently; app-level fault tolerance)
- routes send_code: on final SMTP failure, clear the verification record
  (releases the 60s resend rate limit so the user can retry immediately)
  and return 502 + clear actionable error instead of 500
- tests: 3 retry unit tests (success after failures / no infinite retry /
  last-error returned) + register_smtp_failure_502 integration test
  (unreachable SMTP → 502; resend right after is not rate-limited)
- 136/136 tests + fmt + clippy clean
@argszero
argszero merged commit 19869d2 into main Aug 21, 2026
1 check passed
@argszero
argszero deleted the fix/smtp-retry branch August 21, 2026 22:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant