Files
doc_ai_backed/pkg/email/template.go
yoge 876e64366b feat: upgrade verification code email with bilingual HTML template
- Chinese domains (qq.com, 163.com, etc.) receive a Chinese email
- All other domains receive an English email
- Prominent code display: 40px monospace with wide letter-spacing
- Clean OpenAI-inspired layout with dark header and card design

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 14:44:17 +08:00

167 lines
6.0 KiB
Go

package email
import "fmt"
// BuildVerifyCodeEmail returns a locale-appropriate subject and HTML body for
// the verification code email. Chinese domains get a Chinese email; all others
// get an English one.
func BuildVerifyCodeEmail(toEmail, code string) (subject, body string) {
domain := toEmail[lastIndex(toEmail, '@')+1:]
if chineseDomainRe.MatchString(domain) {
return buildVerifyCodeZH(code)
}
return buildVerifyCodeEN(code)
}
func buildVerifyCodeZH(code string) (subject, body string) {
subject = "您的验证码"
body = fmt.Sprintf(`<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>验证码</title>
</head>
<body style="margin:0;padding:0;background:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
<table width="100%%" cellpadding="0" cellspacing="0" style="background:#f4f4f5;padding:40px 0;">
<tr>
<td align="center">
<table width="480" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:12px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.08);">
<!-- Header -->
<tr>
<td style="background:#0a0a0a;padding:32px 40px;">
<span style="color:#ffffff;font-size:20px;font-weight:700;letter-spacing:-0.3px;">TexPixel</span>
</td>
</tr>
<!-- Body -->
<tr>
<td style="padding:40px 40px 32px;">
<p style="margin:0 0 8px;font-size:24px;font-weight:700;color:#0a0a0a;line-height:1.3;">验证您的邮箱</p>
<p style="margin:0 0 32px;font-size:15px;color:#6b7280;line-height:1.6;">
请使用以下验证码完成注册。验证码仅对您本人有效,请勿分享给他人。
</p>
<!-- Code block -->
<table width="100%%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;padding:28px 0;">
<span style="font-size:40px;font-weight:700;letter-spacing:12px;color:#0a0a0a;font-family:'Courier New',Courier,monospace;">%s</span>
</td>
</tr>
</table>
<p style="margin:24px 0 0;font-size:13px;color:#9ca3af;text-align:center;">
验证码 <strong>10 分钟</strong>内有效,请尽快使用
</p>
</td>
</tr>
<!-- Divider -->
<tr>
<td style="padding:0 40px;">
<div style="height:1px;background:#f3f4f6;"></div>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:24px 40px 32px;">
<p style="margin:0;font-size:12px;color:#9ca3af;line-height:1.7;">
如果您没有请求此验证码,可以忽略本邮件,您的账户仍然安全。<br/>
&copy; 2025 TexPixel. 保留所有权利。
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>`, code)
return
}
func buildVerifyCodeEN(code string) (subject, body string) {
subject = "Your verification code"
body = fmt.Sprintf(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Verification Code</title>
</head>
<body style="margin:0;padding:0;background:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
<table width="100%%" cellpadding="0" cellspacing="0" style="background:#f4f4f5;padding:40px 0;">
<tr>
<td align="center">
<table width="480" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:12px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.08);">
<!-- Header -->
<tr>
<td style="background:#0a0a0a;padding:32px 40px;">
<span style="color:#ffffff;font-size:20px;font-weight:700;letter-spacing:-0.3px;">TexPixel</span>
</td>
</tr>
<!-- Body -->
<tr>
<td style="padding:40px 40px 32px;">
<p style="margin:0 0 8px;font-size:24px;font-weight:700;color:#0a0a0a;line-height:1.3;">Verify your email address</p>
<p style="margin:0 0 32px;font-size:15px;color:#6b7280;line-height:1.6;">
Use the verification code below to complete your registration. Never share this code with anyone.
</p>
<!-- Code block -->
<table width="100%%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;padding:28px 0;">
<span style="font-size:40px;font-weight:700;letter-spacing:12px;color:#0a0a0a;font-family:'Courier New',Courier,monospace;">%s</span>
</td>
</tr>
</table>
<p style="margin:24px 0 0;font-size:13px;color:#9ca3af;text-align:center;">
This code expires in <strong>10 minutes</strong>
</p>
</td>
</tr>
<!-- Divider -->
<tr>
<td style="padding:0 40px;">
<div style="height:1px;background:#f3f4f6;"></div>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:24px 40px 32px;">
<p style="margin:0;font-size:12px;color:#9ca3af;line-height:1.7;">
If you didn&rsquo;t request this code, you can safely ignore this email. Your account is still secure.<br/>
&copy; 2025 TexPixel. All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>`, code)
return
}
// lastIndex returns the last index of sep in s, or -1.
func lastIndex(s string, sep byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == sep {
return i
}
}
return -1
}