thread-master/apps/backend/internal/module/notification/domain/hermes_template.go

138 lines
4.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package domain
import (
"fmt"
"github.com/matcornic/hermes/v2"
)
// BuildHermesHTML renders a hermes email skeleton (same stack as stand-alone notification).
func BuildHermesHTML(brand Brand, body hermes.Body) (string, error) {
if brand.Name == "" {
brand.Name = "Harbor Desk"
}
h := hermes.Hermes{
Product: hermes.Product{
Name: brand.Name,
Link: brand.Link,
Logo: brand.LogoURL,
Copyright: brand.Copyright,
},
// Default theme is clean table layout suitable for most clients.
}
return h.GenerateHTML(hermes.Email{Body: body})
}
// GenerateTemplate builds subject + HTML for a kind/lang with placeholders still present
// ({{.Username}}, {{.VerifyCode}}, {{.ResetURL}} filled later by text/template).
func GenerateTemplate(kind TemplateKind, lang Language, brand Brand) (*EmailTemplate, error) {
lang = NormalizeLanguage(string(lang))
switch kind {
case TemplateEmailVerify:
return generateEmailVerify(lang, brand)
case TemplatePasswordReset:
return generatePasswordReset(lang, brand)
default:
return nil, fmt.Errorf("unknown template kind: %s", kind)
}
}
func generateEmailVerify(lang Language, brand Brand) (*EmailTemplate, error) {
var subject string
var intros, outros []string
var instr string
if lang == LangEnUS {
subject = "[Harbor Desk] Verify your email"
intros = []string{
"You received this email because we need to verify your email address.",
}
instr = "Copy this verification code and enter it on the verify page (valid for 30 minutes):"
outros = []string{
"If you did not create an account, you can ignore this email.",
"This is an automated message — please do not reply.",
}
} else {
subject = "【Harbor Desk】信箱驗證碼"
intros = []string{
"您收到此信是因為需要驗證您的電子信箱。",
}
instr = "請複製下方驗證碼,於 30 分鐘內到驗證頁完成確認:"
outros = []string{
"若您並未註冊帳號,可忽略本信。",
"此為系統自動發出,請勿直接回覆。",
}
}
html, err := BuildHermesHTML(brand, hermes.Body{
Name: "{{.Username}}",
Intros: intros,
Actions: []hermes.Action{
{
Instructions: instr,
InviteCode: "{{.VerifyCode}}",
},
},
Outros: outros,
Signature: " ",
})
if err != nil {
return nil, err
}
return &EmailTemplate{Subject: subject, Body: html}, nil
}
func generatePasswordReset(lang Language, brand Brand) (*EmailTemplate, error) {
var subject, instr, btnText string
var intros, outros []string
if lang == LangEnUS {
subject = "[Harbor Desk] Reset your password"
intros = []string{
"You received this email because a password reset was requested for your account.",
}
instr = "Copy this code, or open the reset page with the button below (valid for 30 minutes):"
btnText = "Open reset page"
outros = []string{
"If you did not request a password reset, no further action is required.",
"This is an automated message — please do not reply.",
}
} else {
subject = "【Harbor Desk】重設密碼"
intros = []string{
"您收到此信是因為有人申請重設您的帳戶密碼。",
}
instr = "請複製下方驗證碼或點擊按鈕開啟重設頁30 分鐘內有效):"
btnText = "開啟重設密碼頁"
outros = []string{
"若您並未申請重設密碼,可忽略本信,帳號不會有任何變更。",
"此為系統自動發出,請勿直接回覆。",
}
}
actions := []hermes.Action{
{
Instructions: instr,
InviteCode: "{{.VerifyCode}}",
},
}
// Button only when ResetURL placeholder present after render — always include;
// empty href is avoided by filling ResetURL before send.
actions = append(actions, hermes.Action{
Button: hermes.Button{
Color: "#0f172a",
Text: btnText,
Link: "{{.ResetURL}}",
},
})
html, err := BuildHermesHTML(brand, hermes.Body{
Name: "{{.Username}}",
Intros: intros,
Actions: actions,
Outros: outros,
Signature: " ",
})
if err != nil {
return nil, err
}
return &EmailTemplate{Subject: subject, Body: html}, nil
}