3877b23894
Swap the net/smtp mailer for go-mail behind the existing Mailer seam: the Message struct now carries a text + HTML body, TLS mode is chosen from the port (implicit TLS on 465, else mandatory STARTTLS), a dial timeout bounds the synchronous send, and no client certificate is needed. Add a branded, image-free, mobile-friendly ru/en HTML template (with a plain-text alternative) rendering a large readable code and an ignore-notice footer with a landing link. Add BACKEND_PUBLIC_BASE_URL config (the canonical origin for the email footer link, never the request Host — anti-injection), required when a relay is configured. Fix the email-login address squat: ProvisionEmail creates the account flagged is_guest until the code is confirmed, so an abandoned login is reaped like any guest and its address freed; confirming (login or link) clears the flag. Seed the new account's language from the client, plumbed through the email-login request. The confirm deeplink, its transport surface and the send rate-limit land in follow-up work.
53 lines
1.9 KiB
Go
53 lines
1.9 KiB
Go
package account
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestRenderConfirmationEmail checks that each (purpose, locale) renders a localised
|
|
// subject, embeds the code and the one-tap deeplink in both bodies, and produces HTML.
|
|
func TestRenderConfirmationEmail(t *testing.T) {
|
|
const deeplink = "https://erudit-game.ru/app/#/confirm/tok123"
|
|
cases := []struct {
|
|
name, purpose, locale, subjectSub string
|
|
}{
|
|
{"login ru", purposeLogin, "ru", "вход"},
|
|
{"login en", purposeLogin, "en", "sign-in"},
|
|
{"link ru", purposeLink, "ru", "подтвержд"},
|
|
{"link en", purposeLink, "en", "confirmation"},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
msg, err := renderConfirmationEmail(c.purpose, "123456", deeplink, "https://erudit-game.ru", c.locale)
|
|
if err != nil {
|
|
t.Fatalf("render: %v", err)
|
|
}
|
|
if !strings.Contains(strings.ToLower(msg.Subject), c.subjectSub) {
|
|
t.Errorf("subject %q does not contain %q", msg.Subject, c.subjectSub)
|
|
}
|
|
if !strings.Contains(msg.Text, "123456") || !strings.Contains(msg.HTML, "123456") {
|
|
t.Error("code missing from a body")
|
|
}
|
|
if !strings.Contains(msg.Text, deeplink) || !strings.Contains(msg.HTML, "confirm/tok123") {
|
|
t.Error("deeplink missing from a body")
|
|
}
|
|
if !strings.Contains(msg.HTML, "<html") {
|
|
t.Error("HTML body is not HTML")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestRenderConfirmationEmailUnknownLocaleDefaultsEnglish falls back to English for an
|
|
// unsupported locale rather than erroring or emitting an empty subject.
|
|
func TestRenderConfirmationEmailUnknownLocaleDefaultsEnglish(t *testing.T) {
|
|
msg, err := renderConfirmationEmail(purposeLogin, "000000", "", "https://erudit-game.ru", "de")
|
|
if err != nil {
|
|
t.Fatalf("render: %v", err)
|
|
}
|
|
if !strings.Contains(strings.ToLower(msg.Subject), "sign-in") {
|
|
t.Errorf("unknown locale should default to English, got subject %q", msg.Subject)
|
|
}
|
|
}
|