Skip to content

Commit d8bcc57

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
improve email template further
1 parent 90bcc82 commit d8bcc57

File tree

1 file changed

+20
-23
lines changed

1 file changed

+20
-23
lines changed

email/templates.go

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,39 @@ import (
1212
func (s *Sender) formatNotificationBody(sub *notifier.Subscription, thread *notifier.Thread, posts []*notifier.Post) string {
1313
var b strings.Builder
1414

15-
b.WriteString("<!DOCTYPE html>\n<html>\n<head>\n")
15+
b.WriteString("<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n")
1616
b.WriteString("<meta charset=\"utf-8\">\n")
17+
b.WriteString("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n")
1718
b.WriteString("<style>\n")
1819
b.WriteString("body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 0 auto; padding: 20px; }\n")
19-
b.WriteString(".header { border-bottom: 2px solid #e67e22; padding-bottom: 10px; margin-bottom: 20px; }\n")
20-
b.WriteString(".post { margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid #ecf0f1; }\n")
21-
b.WriteString(".post:last-of-type { border-bottom: none; }\n")
20+
b.WriteString(".post { margin-bottom: 30px; padding-bottom: 30px; border-bottom: 2px solid #e67e22; }\n")
21+
b.WriteString(".post:last-of-type { border-bottom: none; padding-bottom: 0; }\n")
22+
b.WriteString(".post:first-of-type { padding-top: 0; }\n")
23+
b.WriteString(".meta { margin-bottom: 12px; }\n")
24+
b.WriteString(".post-number { color: #7f8c8d; font-weight: 500; font-size: 1.1em; text-decoration: none; }\n")
25+
b.WriteString(".post-number:hover { text-decoration: underline; }\n")
2226
b.WriteString(".author { color: #e67e22; font-weight: 600; font-size: 1.2em; }\n")
2327
b.WriteString(".timestamp { color: #7f8c8d; font-size: 0.9em; }\n")
24-
b.WriteString(".content { background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 15px 0; }\n")
28+
b.WriteString(".content { margin: 15px 0; }\n")
2529
b.WriteString(".content img { max-width: 100%; height: auto; margin: 10px 0; display: block; }\n")
26-
b.WriteString(".footer { margin-top: 20px; padding-top: 10px; border-top: 2px solid #ecf0f1; color: #7f8c8d; font-size: 0.9em; }\n")
30+
b.WriteString(".content blockquote { border-left: 3px solid #ddd; padding-left: 15px; margin: 10px 0; color: #666; font-size: 0.95em; }\n")
31+
b.WriteString(".footer { margin-top: 30px; padding-top: 15px; border-top: 1px solid #ddd; font-size: 0.9em; color: #7f8c8d; }\n")
32+
b.WriteString(".footer a { color: #7f8c8d; text-decoration: underline; margin: 0 8px; }\n")
33+
b.WriteString(".footer a:first-child { margin-left: 0; }\n")
2734
b.WriteString("a { color: #e67e22; text-decoration: none; }\n")
2835
b.WriteString("a:hover { text-decoration: underline; }\n")
29-
b.WriteString(".view-post { display: inline-block; margin-top: 10px; font-size: 0.9em; }\n")
3036
b.WriteString("</style>\n</head>\n<body>\n")
3137

32-
b.WriteString("<div class=\"header\">\n")
33-
if len(posts) == 1 {
34-
b.WriteString("<h2>New ADVRider Post</h2>\n")
35-
} else {
36-
b.WriteString(fmt.Sprintf("<h2>%d New ADVRider Posts</h2>\n", len(posts)))
37-
}
38-
b.WriteString("</div>\n")
39-
40-
// Render each post
38+
// Render each post - no redundant header
4139
for _, post := range posts {
4240
b.WriteString("<div class=\"post\">\n")
4341
b.WriteString("<div class=\"meta\">\n")
44-
b.WriteString(fmt.Sprintf("<span class=\"author\">%s</span>\n", escapeHTML(post.Author)))
42+
b.WriteString(fmt.Sprintf("<a href=\"%s\" class=\"post-number\">#%s</a>\n", escapeHTML(post.URL), escapeHTML(post.ID)))
43+
b.WriteString(fmt.Sprintf("<span class=\"author\"> &bull; %s</span>\n", escapeHTML(post.Author)))
4544
if post.Timestamp != "" {
4645
t, err := time.Parse(time.RFC3339, post.Timestamp)
4746
if err == nil {
48-
b.WriteString(fmt.Sprintf("<span class=\"timestamp\"> &bull; %s</span>\n", t.Format("Jan 2, 2006 at 3:04 PM")))
47+
b.WriteString(fmt.Sprintf("<span class=\"timestamp\"> &bull; %s UTC</span>\n", t.Format("Jan 2, 2006 at 3:04 PM")))
4948
}
5049
}
5150
b.WriteString("</div>\n")
@@ -59,16 +58,14 @@ func (s *Sender) formatNotificationBody(sub *notifier.Subscription, thread *noti
5958
}
6059
b.WriteString("</div>\n")
6160

62-
b.WriteString(fmt.Sprintf("<a href=\"%s\" class=\"view-post\">View this post on ADVRider</a>\n", escapeHTML(post.URL)))
6361
b.WriteString("</div>\n")
6462
}
6563

64+
// Footer with thread link and manage link
6665
b.WriteString("<div class=\"footer\">\n")
67-
b.WriteString(fmt.Sprintf("<a href=\"%s\">View full thread on ADVRider</a>\n", escapeHTML(thread.ThreadURL)))
68-
b.WriteString(" &bull; \n")
69-
// Use secure token in manage link
66+
b.WriteString(fmt.Sprintf("<a href=\"%s\">View thread</a>\n", escapeHTML(thread.ThreadURL)))
7067
manageURL := fmt.Sprintf("%s/manage?token=%s", s.baseURL, url.QueryEscape(sub.Token))
71-
b.WriteString(fmt.Sprintf("<a href=\"%s\">Manage Subscriptions</a>\n", escapeHTML(manageURL)))
68+
b.WriteString(fmt.Sprintf("<a href=\"%s\">Manage</a>\n", escapeHTML(manageURL)))
7269
b.WriteString("</div>\n")
7370

7471
b.WriteString("</body>\n</html>")

0 commit comments

Comments
 (0)