interface EmailTemplateInput { siteName: string; title: string; intro: string; actionLabel: string; actionUrl: string; note?: string; closing?: string; } function escapeHtml(value: string) { return value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """); } export function renderActionEmail({ siteName, title, intro, actionLabel, actionUrl, note, closing = "如果这不是你的操作,可以忽略这封邮件。", }: EmailTemplateInput) { const safeSiteName = escapeHtml(siteName); const safeTitle = escapeHtml(title); const safeIntro = escapeHtml(intro); const safeActionLabel = escapeHtml(actionLabel); const safeActionUrl = escapeHtml(actionUrl); const safeNote = note ? escapeHtml(note) : ""; const safeClosing = escapeHtml(closing); const text = [ `${siteName} - ${title}`, intro, `${actionLabel}: ${actionUrl}`, note, closing, ].filter(Boolean).join("\n\n"); const html = ` ${safeTitle}
${safeIntro}
S ${safeSiteName}

${safeTitle}

${safeIntro}

如果按钮无法打开,请复制下面的链接到浏览器:

${safeActionUrl}

${safeNote ? `

${safeNote}

` : ""}

${safeClosing}

`; return { html, text }; } export function renderRegistrationEmail(siteName: string, actionUrl: string) { return renderActionEmail({ siteName, title: "验证你的邮箱", intro: "欢迎来到 J-Board Lite。点击下方按钮完成邮箱验证,验证后即可使用你的账户。", actionLabel: "完成邮箱验证", actionUrl, note: "链接 30 分钟内有效。为了账户安全,请不要转发这封邮件。", }); } export function renderPasswordResetEmail(siteName: string, actionUrl: string) { return renderActionEmail({ siteName, title: "重设账户密码", intro: "我们收到了你的密码重设请求。点击下方按钮设置一个新密码。", actionLabel: "重设密码", actionUrl, note: "链接 20 分钟内有效。如果不是你本人发起,请忽略这封邮件。", }); } export function renderEmailChangeEmail(siteName: string, actionUrl: string) { return renderActionEmail({ siteName, title: "确认新的登录邮箱", intro: "你正在把 J-Board Lite 账户绑定到这个邮箱。点击下方按钮确认变更。", actionLabel: "确认邮箱变更", actionUrl, note: "链接 30 分钟内有效。确认后,新邮箱会成为你的登录邮箱。", }); } export function renderSmtpTestEmail(siteName: string) { return renderActionEmail({ siteName, title: "SMTP 测试邮件", intro: "这是一封来自 J-Board Lite 的测试邮件。收到它说明当前 SMTP 配置可以正常发信。", actionLabel: "返回 J-Board Lite", actionUrl: "https://github.com/JetSprow/J-Board", note: "你可以回到后台继续配置邮箱验证、密码找回和账户邮箱变更流程。", closing: "测试完成后,无需回复这封邮件。", }); }