Skip to content

Commit 898014c

Browse files
committed
Update template email
1 parent 8c05651 commit 898014c

File tree

4 files changed

+100
-29
lines changed

4 files changed

+100
-29
lines changed

cli/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
992992
)
993993
if experiments.Enabled(codersdk.ExperimentNotifications) {
994994
cfg := options.DeploymentValues.Notifications
995+
accessUrl := options.DeploymentValues.AccessURL.Value().String()
995996
metrics := notifications.NewMetrics(options.PrometheusRegistry)
996997

997998
// The enqueuer is responsible for enqueueing notifications to the given store.
@@ -1004,7 +1005,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
10041005
// The notification manager is responsible for:
10051006
// - creating notifiers and managing their lifecycles (notifiers are responsible for dequeueing/sending notifications)
10061007
// - keeping the store updated with status updates
1007-
notificationsManager, err = notifications.NewManager(cfg, options.Database, metrics, logger.Named("notifications.manager"))
1008+
notificationsManager, err = notifications.NewManager(cfg, options.Database, accessUrl, metrics, logger.Named("notifications.manager"))
10081009
if err != nil {
10091010
return xerrors.Errorf("failed to instantiate notification manager: %w", err)
10101011
}

coderd/notifications/dispatch/smtp.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ var (
4949
// NOTE: auth and TLS is currently *not* enabled in this initial thin slice.
5050
// TODO: implement DKIM/SPF/DMARC? https://github.com/emersion/go-msgauth
5151
type SMTPHandler struct {
52-
cfg codersdk.NotificationsEmailConfig
53-
log slog.Logger
52+
cfg codersdk.NotificationsEmailConfig
53+
log slog.Logger
54+
accessURL string
5455

5556
loginWarnOnce sync.Once
5657
}
5758

58-
func NewSMTPHandler(cfg codersdk.NotificationsEmailConfig, log slog.Logger) *SMTPHandler {
59-
return &SMTPHandler{cfg: cfg, log: log}
59+
func NewSMTPHandler(cfg codersdk.NotificationsEmailConfig, accessURL string, log slog.Logger) *SMTPHandler {
60+
return &SMTPHandler{cfg: cfg, accessURL: accessURL, log: log}
6061
}
6162

6263
func (s *SMTPHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTmpl string) (DeliveryFunc, error) {
@@ -75,6 +76,8 @@ func (s *SMTPHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTm
7576
// Then, reuse these strings in the HTML & plain body templates.
7677
payload.Labels["_subject"] = subject
7778
payload.Labels["_body"] = htmlBody
79+
payload.Labels["_year"] = time.Now().Format("2006")
80+
payload.Labels["_accessURL"] = s.accessURL
7881
htmlBody, err = render.GoTemplate(htmlTemplate, payload, nil)
7982
if err != nil {
8083
return nil, xerrors.Errorf("render full html template: %w", err)
Lines changed: 87 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,94 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>{{ .Labels._subject }}</title>
7-
</head>
8-
<body style="font-family: Arial, sans-serif; background-color: #1d1d20; margin: 0; padding: 0;">
9-
<div style="max-width: 600px; margin: 20px auto; background-color: #3f556d; border: 1px solid #34495E; padding: 20px; border-radius: 8px;">
10-
<div style="text-align: center; padding: 20px 0; border-bottom: 1px solid #34495E;">
11-
<img width="215" height="47" src="https://coder.com/logo-wide-white.png"/>
12-
</div>
13-
<div style="padding: 20px; color: #ECF0F1; line-height: 1.6;">
14-
<h1 style="color: #ECF0F1;">{{ .Labels._subject }}</h1>
15-
{{ .Labels._body }}
7+
<style type="text/css">
8+
body {
9+
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI",
10+
"Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
11+
"Helvetica Neue", sans-serif;
12+
margin: 0;
13+
padding: 0;
14+
color: #000;
15+
}
16+
17+
.card {
18+
max-width: 600px;
19+
margin: 20px auto;
20+
border: 1px solid #eaeaea;
21+
padding: 60px;
22+
border-radius: 8px;
23+
line-height: 1.5;
24+
font-size: 14px;
25+
}
26+
27+
.logo {
28+
width: 60px;
29+
}
30+
31+
.title {
32+
text-align: center;
33+
font-weight: 400;
34+
font-size: 24px;
35+
margin: 8px 0 32px;
36+
line-height: 1.5;
37+
}
38+
39+
.actions {
40+
display: flex;
41+
align-items: center;
42+
justify-content: center;
43+
gap: 8px;
44+
margin-top: 32px;
45+
}
1646

47+
.action {
48+
display: inline-block;
49+
padding: 13px 24px;
50+
background-color: #000;
51+
color: #ffffff;
52+
text-decoration: none;
53+
border-radius: 8px;
54+
}
55+
56+
.footer {
57+
border-top: 1px solid #eaeaea;
58+
color: #666;
59+
font-size: 12px;
60+
margin-top: 64px;
61+
padding-top: 24px;
62+
line-height: 1.6;
63+
}
64+
65+
.link {
66+
color: #067df7;
67+
text-decoration: none;
68+
}
69+
</style>
70+
</head>
71+
<body>
72+
<div class="card">
73+
<img class="logo" src="https://coder.com/coder-logo-300x300.png" />
74+
<h1 class="title">{{ .Labels._subject }}</h1>
75+
{{ .Labels._body }}
76+
77+
<div class="actions">
1778
{{ range $action := .Actions }}
18-
<a href="{{ $action.URL }}" style="display: inline-block; padding: 10px 20px; background-color: #3D74DB; color: #ffffff; text-decoration: none; border-radius: 4px; margin-top: 20px;">{{ $action.Label }}</a><br>
79+
<a href="{{ $action.URL }}" class="action">{{ $action.Label }}</a>
1980
{{ end }}
20-
</div>
21-
<div style="text-align: center; padding: 10px 0; border-top: 1px solid #34495E; margin-top: 20px; color: #BDC3C7;">
81+
</div>
82+
83+
<div class="footer">
2284
<!-- TODO: dynamic copyright -->
23-
&copy; 2024 Coder. All rights reserved.
85+
<p>&copy; 2024 Coder. All rights reserved.</p>
86+
<p>
87+
<a href="" class="link"
88+
>Click here to manage your notification settings</a
89+
>
90+
</p>
91+
</div>
2492
</div>
25-
</div>
26-
</body>
27-
</html>
93+
</body>
94+
</html>

coderd/notifications/manager.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type Manager struct {
5959
//
6060
// helpers is a map of template helpers which are used to customize notification messages to use global settings like
6161
// access URL etc.
62-
func NewManager(cfg codersdk.NotificationsConfig, store Store, metrics *Metrics, log slog.Logger) (*Manager, error) {
62+
func NewManager(cfg codersdk.NotificationsConfig, store Store, host string, metrics *Metrics, log slog.Logger) (*Manager, error) {
6363
// TODO(dannyk): add the ability to use multiple notification methods.
6464
var method database.NotificationMethod
6565
if err := method.Scan(cfg.Method.String()); err != nil {
@@ -93,14 +93,14 @@ func NewManager(cfg codersdk.NotificationsConfig, store Store, metrics *Metrics,
9393
stop: make(chan any),
9494
done: make(chan any),
9595

96-
handlers: defaultHandlers(cfg, log),
96+
handlers: defaultHandlers(cfg, host, log),
9797
}, nil
9898
}
9999

100100
// defaultHandlers builds a set of known handlers; panics if any error occurs as these handlers should be valid at compile time.
101-
func defaultHandlers(cfg codersdk.NotificationsConfig, log slog.Logger) map[database.NotificationMethod]Handler {
101+
func defaultHandlers(cfg codersdk.NotificationsConfig, accessURL string, log slog.Logger) map[database.NotificationMethod]Handler {
102102
return map[database.NotificationMethod]Handler{
103-
database.NotificationMethodSmtp: dispatch.NewSMTPHandler(cfg.SMTP, log.Named("dispatcher.smtp")),
103+
database.NotificationMethodSmtp: dispatch.NewSMTPHandler(cfg.SMTP, accessURL, log.Named("dispatcher.smtp")),
104104
database.NotificationMethodWebhook: dispatch.NewWebhookHandler(cfg.Webhook, log.Named("dispatcher.webhook")),
105105
}
106106
}

0 commit comments

Comments
 (0)