接入 Gmail OAuth2:一套流程,两家服务商
我们在 v1.2.0 里发布 Microsoft OAuth2 时,目标很清楚:让用户用现有的 Microsoft 账户登录,而不必去生成一个应用专用密码。它在 Outlook、Hotmail 和 M365 账户上表现良好。自然的下一步是 Gmail — 全世界最流行的邮件服务商。
OAuth2 为什么重要
Google 收紧 IMAP 访问已经好几年了。如果你开了双重验证(你应该开),用第三方邮件客户端就需要一个应用密码。应用密码是能用,但它藏得深、容易忘,而且感觉就像个变通办法。OAuth2 则让用户点一下“使用 Google 登录”,在浏览器里完成验证,再回到应用 — 不用复制密码,也不用满设置页找选项。
实现过程
MailVault 本来就有一套可用的 Microsoft OAuth2 PKCE 流程,是用 Rust 写的。这套架构分三部分:一个跑在 localhost:19876 上的本地 TCP 回调服务,用来接收浏览器登录后的跳转;一个用授权码换取访问令牌/刷新令牌的令牌交换函数;以及供 IMAP 和 SMTP 使用的 XOAUTH2 SASL 认证。
加入 Google 意味着要把这一整套做成与服务商无关的实现。我们没有把 Microsoft 的端点写死,而是重构了 Rust 的 OAuth2 模块,让它在运行时接受服务商配置 — 授权 URL、令牌 URL、作用域和客户端 ID 全部由前端在发起流程时传入。
客户端 ID 方面,我们采用了和 Microsoft 那边一样的做法:用一个众所周知的公共客户端 ID。Mozilla 的开源邮件客户端 Thunderbird 在 Google 和 Microsoft 两边都注册了公共 OAuth2 客户端。MailVault 使用 Thunderbird 的 Google 客户端 ID(406964657835-aq8lmia8j95dhl1a2bvharmfk3t1hgqj.apps.googleusercontent.com),搭配 https://mail.google.com/ 这个 scope,它授予完整的 IMAP 和 SMTP 访问权限。
代码里改了什么
Rust 那边需要一个新的 oauth2_start 命令,接受随服务商而异的参数(授权 URL、令牌 URL、scope、客户端 ID),而不是写死成 Microsoft。回调服务和 PKCE 逻辑原样不动 — OAuth2 就是 OAuth2,跟是哪家服务商无关。
前端这边,AccountModal 组件现在会为 Gmail 账户显示一个“使用 Google 登录”按钮(旁边保留原来的“改用应用密码”作为兜底)。这个按钮触发的是同一套 OAuth2 流程,只是把 Microsoft 的端点和 scope 换成了 Google 的。验证完成后,访问令牌会通过 XOAUTH2 SASL 同时用于 IMAP(imap.gmail.com)和 SMTP(smtp.gmail.com)。
令牌刷新的方式与 Microsoft 完全相同:当访问令牌过期(通常是一小时后),MailVault 会用保存的刷新令牌自动刷新它。除非用户在 Google 账户设置里撤销授权,否则永远不需要重新认证。
结果
Gmail 用户现在只需点一个按钮,在 Google 标准的登录页面完成登录,就能立刻开始使用 MailVault。不用应用专用密码,不用找 IMAP 设置,也没有「不够安全的应用」开关。它在两步验证、Google Workspace 和个人 Gmail 账户上都能用。
同一套 OAuth2 基础设施现在也为将来任何支持标准 OAuth2 的服务商做好了准备 — 这个 Rust 模块完全与服务商无关。