generated from VLADIMIR/template
try fix email
This commit is contained in:
@@ -42,15 +42,15 @@ func welcomePlain(username, email, password, loginURL string) string {
|
||||
// welcomeHTML возвращает HTML-версию письма о регистрации.
|
||||
func welcomeHTML(username, email, password, loginURL string) string {
|
||||
var content strings.Builder
|
||||
content.WriteString("<p style=\"color:#211a14;\">Привет, <strong>")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14;\">Привет, <strong>")
|
||||
content.WriteString(html.EscapeString(username))
|
||||
content.WriteString("</strong>!</p>\n")
|
||||
content.WriteString("<p style=\"color:#211a14;\">Твоя регистрация в «Вечернем детективе» прошла. Данные для входа:</p>\n")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14;\">Твоя регистрация в «Вечернем детективе» прошла. Данные для входа:</p>\n")
|
||||
content.WriteString(credentialsBlockHTML(email, password))
|
||||
if loginURL != "" {
|
||||
content.WriteString(buttonHTML(loginURL, "Войти в игру"))
|
||||
}
|
||||
content.WriteString("<p style=\"color:#211a14; font-size:13px;\">Если ты не регистрировался — просто проигнорируй это письмо.</p>")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14; font-size:13px;\">Если ты не регистрировался — просто проигнорируй это письмо.</p>")
|
||||
return wrapHTML(content.String(), loginURL)
|
||||
}
|
||||
|
||||
@@ -80,16 +80,16 @@ func resetPlain(username, email, password, loginURL string) string {
|
||||
// resetHTML возвращает HTML-версию письма о сбросе пароля.
|
||||
func resetHTML(username, email, password, loginURL string) string {
|
||||
var content strings.Builder
|
||||
content.WriteString("<p style=\"color:#211a14;\">Привет, <strong>")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14;\">Привет, <strong>")
|
||||
content.WriteString(html.EscapeString(username))
|
||||
content.WriteString("</strong>!</p>\n")
|
||||
content.WriteString("<p style=\"color:#211a14;\">Ты запросил сброс пароля в «Вечернем детективе». Новый пароль для входа:</p>\n")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14;\">Ты запросил сброс пароля в «Вечернем детективе». Новый пароль для входа:</p>\n")
|
||||
content.WriteString(credentialsBlockHTML(email, password))
|
||||
if loginURL != "" {
|
||||
content.WriteString(buttonHTML(loginURL, "Войти в игру"))
|
||||
}
|
||||
content.WriteString("<p style=\"color:#211a14;\">Никому не сообщай пароль и не пересылай это письмо.</p>\n")
|
||||
content.WriteString("<p style=\"color:#211a14; font-size:13px;\">Если это был не ты — ответь на это письмо: мы поможем защитить аккаунт.</p>")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14;\">Никому не сообщай пароль и не пересылай это письмо.</p>\n")
|
||||
content.WriteString("<p class=\"paper-text\" style=\"color:#211a14; -webkit-text-fill-color:#211a14; font-size:13px;\">Если это был не ты — ответь на это письмо: мы поможем защитить аккаунт.</p>")
|
||||
return wrapHTML(content.String(), loginURL)
|
||||
}
|
||||
|
||||
@@ -107,10 +107,10 @@ func greeting(username string) string {
|
||||
// совместимой с Gmail.
|
||||
func credentialsBlockHTML(email, password string) string {
|
||||
return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:24px 0; border-top:1px dashed black; border-bottom:1px dashed black; table-layout:fixed;">
|
||||
<tr><td style="padding:16px 0 4px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#211a14;">Логин</td></tr>
|
||||
<tr><td style="padding:0 0 16px; font-size:16px; color:#211a14; overflow-wrap:anywhere; word-break:break-all;">` + html.EscapeString(email) + `</td></tr>
|
||||
<tr><td style="padding:16px 0 4px; border-top:1px dashed black; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#211a14;">Пароль</td></tr>
|
||||
<tr><td style="padding:0 0 16px; font-size:20px; color:#211a14; overflow-wrap:anywhere; word-break:break-all;"><strong>` + html.EscapeString(password) + `</strong></td></tr>
|
||||
<tr><td class="paper-text" style="padding:16px 0 4px; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#211a14; -webkit-text-fill-color:#211a14;">Логин</td></tr>
|
||||
<tr><td class="paper-text" style="padding:0 0 16px; font-size:16px; color:#211a14; -webkit-text-fill-color:#211a14; overflow-wrap:anywhere; word-break:break-all;">` + html.EscapeString(email) + `</td></tr>
|
||||
<tr><td class="paper-text" style="padding:16px 0 4px; border-top:1px dashed black; font-family:Arial,Helvetica,sans-serif; font-size:12px; color:#211a14; -webkit-text-fill-color:#211a14;">Пароль</td></tr>
|
||||
<tr><td class="paper-text" style="padding:0 0 16px; font-size:20px; color:#211a14; -webkit-text-fill-color:#211a14; overflow-wrap:anywhere; word-break:break-all;"><strong>` + html.EscapeString(password) + `</strong></td></tr>
|
||||
</table>`
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func buttonHTML(link, label string) string {
|
||||
return `<table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px 0;">
|
||||
<tr>
|
||||
<td style="border-radius:5px; background-color:#222; background-image:url('` + emailAssetURL(link, "belt.png") + `'); background-size:cover;">
|
||||
<a href="` + html.EscapeString(link) + `" style="display:inline-block; padding:8px 16px; color:#bfa07d; font-family:'font_old_typer','Courier New',serif; font-weight:400; text-decoration:none; font-size:18px; line-height:24px; border-radius:5px;">` + html.EscapeString(label) + `</a>
|
||||
<a href="` + html.EscapeString(link) + `" style="display:inline-block; padding:8px 16px; color:#bfa07d; -webkit-text-fill-color:#bfa07d; font-family:'font_old_typer','Courier New',serif; font-weight:400; text-decoration:none; font-size:18px; line-height:24px; border-radius:5px;">` + html.EscapeString(label) + `</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>`
|
||||
@@ -139,25 +139,56 @@ func wrapHTML(content, baseURL string) string {
|
||||
<style>
|
||||
:root { color-scheme:light; supported-color-schemes:light; }
|
||||
@font-face { font-family:'font_old_typer'; src:url('` + emailAssetURL(baseURL, "a_OldTyper.ttf") + `') format('truetype'); }
|
||||
a:hover { color:#63e2b7 !important; }
|
||||
/* Apple Mail, Samsung Email and other clients that expose the theme. */
|
||||
@media (prefers-color-scheme:dark) {
|
||||
.paper { background-color:#f4e4cc !important; }
|
||||
.paper-text, .paper-text strong, .paper-text a { color:#211a14 !important; -webkit-text-fill-color:#211a14 !important; }
|
||||
}
|
||||
/* Outlook web/mobile: attributes may be on the element itself or a parent. */
|
||||
[data-ogsb] .paper, .paper[data-ogsb] { background-color:#f4e4cc !important; }
|
||||
[data-ogsc] .paper-text, .paper-text[data-ogsc], [data-ogsc] .paper-text strong, [data-ogsc] .paper-text a {
|
||||
color:#211a14 !important; -webkit-text-fill-color:#211a14 !important;
|
||||
}
|
||||
/* Gmail iOS: paint letters with a gradient that survives color inversion.
|
||||
https://emailmatrix.ru/blog/gmail-ios-dark-mode/ */
|
||||
@media only screen and (max-width:480px) {
|
||||
u + .email-body .paper-text {
|
||||
background-image:linear-gradient(#211a14,#211a14);
|
||||
background-clip:text;
|
||||
color:transparent !important;
|
||||
-webkit-text-fill-color:transparent !important;
|
||||
}
|
||||
u + .email-body .paper-text strong, u + .email-body .paper-text a {
|
||||
color:inherit !important; -webkit-text-fill-color:inherit !important;
|
||||
}
|
||||
/* Gmail Android cannot clip the gradient to text. Keep background and
|
||||
text together so its automatic recoloring preserves contrast. */
|
||||
div > u + .email-body .paper-text {
|
||||
background-image:none;
|
||||
background-clip:border-box;
|
||||
background-color:#f4e4cc;
|
||||
color:#211a14 !important;
|
||||
-webkit-text-fill-color:currentcolor !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="margin:0; padding:0; background-color:#111; font-family:Arial, Helvetica, sans-serif;">
|
||||
<body class="email-body" style="margin:0; padding:0; background-color:#111; font-family:Arial, Helvetica, sans-serif;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#111; padding:24px 12px;">
|
||||
<tr><td align="center">
|
||||
<table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width:600px; width:100%;">
|
||||
<tr>
|
||||
<td style="padding:16px 0 24px;">
|
||||
<span style="color:#bfa07d; font-family:'font_old_typer','Courier New',serif; font-size:22px; line-height:1.4; font-weight:normal;">ВЕЧЕРНИЙ ДЕТЕКТИВ</span>
|
||||
<span style="color:#bfa07d; -webkit-text-fill-color:#bfa07d; font-family:'font_old_typer','Courier New',serif; font-size:22px; line-height:1.4; font-weight:normal;">ВЕЧЕРНИЙ ДЕТЕКТИВ</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#f4e4cc" style="padding:16px; background-color:#f4e4cc; background-image:url('` + emailAssetURL(baseURL, "paper.jpg") + `'); background-size:cover; border-radius:5px; box-shadow:0 0 5px black; color:#211a14; font-family:'font_old_typer','Courier New',serif; font-size:18px; line-height:1.5; font-weight:400;">
|
||||
<td class="paper" bgcolor="#f4e4cc" style="padding:16px; background-color:#f4e4cc; background-image:url('` + emailAssetURL(baseURL, "paper.jpg") + `'); background-image:url('` + emailAssetURL(baseURL, "paper.jpg") + `'),linear-gradient(#f4e4cc,#f4e4cc); background-size:cover; border-radius:5px; box-shadow:0 0 5px black; color:#211a14; font-family:'font_old_typer','Courier New',serif; font-size:18px; line-height:1.5; font-weight:400;">
|
||||
` + content + `
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:24px 0; color:#aaa; font-size:12px; line-height:1.6;">
|
||||
<td style="padding:24px 0; color:#aaa; -webkit-text-fill-color:#aaa; font-size:12px; line-height:1.6;">
|
||||
Это автоматическое письмо сервиса «Вечерний детектив».<br>
|
||||
Если ты получил его по ошибке — просто ответь на это письмо.
|
||||
</td>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package users_service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func TestEmailPaperText(t *testing.T) {
|
||||
for name, render := range map[string]func(string, string, string, string) string{
|
||||
"welcome": welcomeHTML,
|
||||
"reset": resetHTML,
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
body := render("<Detective>", "user@example.com", "<&secret>", "https://example.com")
|
||||
doc, err := html.Parse(strings.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var text strings.Builder
|
||||
var walk func(*html.Node, bool, bool)
|
||||
walk = func(n *html.Node, paper, protected bool) {
|
||||
for _, a := range n.Attr {
|
||||
if a.Key == "class" && a.Val == "paper" {
|
||||
paper = true
|
||||
}
|
||||
if a.Key == "class" && a.Val == "paper-text" {
|
||||
protected = true
|
||||
}
|
||||
}
|
||||
if n.Type == html.ElementNode && n.Data == "a" {
|
||||
protected = true // The button has its own dark background and light label.
|
||||
}
|
||||
if paper && n.Type == html.TextNode && strings.TrimSpace(n.Data) != "" {
|
||||
if !protected {
|
||||
t.Errorf("text without dark-mode protection: %q", n.Data)
|
||||
}
|
||||
text.WriteString(n.Data)
|
||||
}
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
walk(c, paper, protected)
|
||||
}
|
||||
}
|
||||
walk(doc, false, false)
|
||||
for _, want := range []string{"<Detective>", "user@example.com", "<&secret>", "Войти в игру"} {
|
||||
if !strings.Contains(text.String(), want) {
|
||||
t.Errorf("missing readable text %q", want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user