来源
2026-09-28 cloud 本地全链路验收(cloud 96eb092f,framework pin bdea10a1)。注册一个新用户,读取控制库 sys_email 里的验证邮件。对照 objectstack main 后确认,问题代码仍在。
现象
验证邮件的纯文本部分里,链接被 HTML 转义了:
http://localhost:4600/api/v1/auth/verify-email?token=eyJ…&callbackURL=%2F
HTML 部分的 href 是正确的 &callbackURL=。但只显示纯文本的客户端,或者用户复制文本里的链接时,拿到的查询参数是 amp;callbackURL:token 仍能被解析,callbackURL 却丢了。这会把验证后应该跳转的去向(比如接受邀请页)打回默认的 /。
机制
packages/plugins/plugin-email/src/templates/auth-templates.ts 的 bodyText 用的是 {{verificationUrl}}(双花括号,按 template-engine.ts 默认会做 HTML 转义)。HTML 部分的 href 用的是 {{{verificationUrl}}}。纯文本本来就不该做 HTML 转义。所有 locale 变体(AUTH_VERIFY_EMAIL_TEMPLATE_*)都一样,其他带 URL 的 auth 模板(重置密码、邀请等)大概率也有同样的问题。
修复方向
要么纯文本模板里的 URL 统一改用 {{{…}}},要么让模板引擎在渲染 bodyText 时整体不做 HTML 转义。后者更稳,能一次覆盖所有模板。
验收
- 验证、重置、邀请这几类邮件的
body_text 里,链接中的 & 都是字面量。
- 单测:渲染含
& 的 URL 时,纯文本部分不出现 &。
相关
来源
2026-09-28 cloud 本地全链路验收(cloud
96eb092f,framework pinbdea10a1)。注册一个新用户,读取控制库sys_email里的验证邮件。对照 objectstackmain后确认,问题代码仍在。现象
验证邮件的纯文本部分里,链接被 HTML 转义了:
HTML 部分的
href是正确的&callbackURL=。但只显示纯文本的客户端,或者用户复制文本里的链接时,拿到的查询参数是amp;callbackURL:token 仍能被解析,callbackURL却丢了。这会把验证后应该跳转的去向(比如接受邀请页)打回默认的/。机制
packages/plugins/plugin-email/src/templates/auth-templates.ts的bodyText用的是{{verificationUrl}}(双花括号,按template-engine.ts默认会做 HTML 转义)。HTML 部分的href用的是{{{verificationUrl}}}。纯文本本来就不该做 HTML 转义。所有 locale 变体(AUTH_VERIFY_EMAIL_TEMPLATE_*)都一样,其他带 URL 的 auth 模板(重置密码、邀请等)大概率也有同样的问题。修复方向
要么纯文本模板里的 URL 统一改用
{{{…}}},要么让模板引擎在渲染bodyText时整体不做 HTML 转义。后者更稳,能一次覆盖所有模板。验收
body_text里,链接中的&都是字面量。&的 URL 时,纯文本部分不出现&。相关