mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(coderd): add company logo when available for email notifications (#14935)
This PR aims to close #14253 We keep the default behavior using the Coder logo if there's no logo set. Otherwise we want to use the logo based on the URL set in appearance. --------- Co-authored-by: defelmnq <yvincent@coder.com>
This commit is contained in:
co-authored by
defelmnq
parent
c42f487668
commit
297089e944
@@ -55,15 +55,13 @@ type SMTPHandler struct {
|
||||
|
||||
noAuthWarnOnce sync.Once
|
||||
loginWarnOnce sync.Once
|
||||
|
||||
helpers template.FuncMap
|
||||
}
|
||||
|
||||
func NewSMTPHandler(cfg codersdk.NotificationsEmailConfig, helpers template.FuncMap, log slog.Logger) *SMTPHandler {
|
||||
return &SMTPHandler{cfg: cfg, helpers: helpers, log: log}
|
||||
func NewSMTPHandler(cfg codersdk.NotificationsEmailConfig, log slog.Logger) *SMTPHandler {
|
||||
return &SMTPHandler{cfg: cfg, log: log}
|
||||
}
|
||||
|
||||
func (s *SMTPHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTmpl string) (DeliveryFunc, error) {
|
||||
func (s *SMTPHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTmpl string, helpers template.FuncMap) (DeliveryFunc, error) {
|
||||
// First render the subject & body into their own discrete strings.
|
||||
subject, err := markdown.PlaintextFromMarkdown(titleTmpl)
|
||||
if err != nil {
|
||||
@@ -79,12 +77,12 @@ func (s *SMTPHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTm
|
||||
// Then, reuse these strings in the HTML & plain body templates.
|
||||
payload.Labels["_subject"] = subject
|
||||
payload.Labels["_body"] = htmlBody
|
||||
htmlBody, err = render.GoTemplate(htmlTemplate, payload, s.helpers)
|
||||
htmlBody, err = render.GoTemplate(htmlTemplate, payload, helpers)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("render full html template: %w", err)
|
||||
}
|
||||
payload.Labels["_body"] = plainBody
|
||||
plainBody, err = render.GoTemplate(plainTemplate, payload, s.helpers)
|
||||
plainBody, err = render.GoTemplate(plainTemplate, payload, helpers)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("render full plaintext template: %w", err)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<body style="margin: 0; padding: 0; font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; color: #020617; background: #f8fafc;">
|
||||
<div style="max-width: 600px; margin: 20px auto; padding: 60px; border: 1px solid #e2e8f0; border-radius: 8px; background-color: #fff; text-align: left; font-size: 14px; line-height: 1.5;">
|
||||
<div style="text-align: center;">
|
||||
<img src="https://coder.com/coder-logo-horizontal.png" alt="Coder Logo" style="height: 40px;" />
|
||||
<img src="{{ logo_url }}" alt="{{ app_name }} Logo" style="height: 40px;" />
|
||||
</div>
|
||||
<h1 style="text-align: center; font-size: 24px; font-weight: 400; margin: 8px 0 32px; line-height: 1.5;">
|
||||
{{ .Labels._subject }}
|
||||
|
||||
@@ -442,11 +442,7 @@ func TestSMTP(t *testing.T) {
|
||||
require.NoError(t, hp.Set(listen.Addr().String()))
|
||||
tc.cfg.Smarthost = hp
|
||||
|
||||
helpers := map[string]any{
|
||||
"base_url": func() string { return "http://test.com" },
|
||||
"current_year": func() string { return "2024" },
|
||||
}
|
||||
handler := dispatch.NewSMTPHandler(tc.cfg, helpers, logger.Named("smtp"))
|
||||
handler := dispatch.NewSMTPHandler(tc.cfg, logger.Named("smtp"))
|
||||
|
||||
// Start mock SMTP server in the background.
|
||||
var wg sync.WaitGroup
|
||||
@@ -484,7 +480,7 @@ func TestSMTP(t *testing.T) {
|
||||
Labels: make(map[string]string),
|
||||
}
|
||||
|
||||
dispatchFn, err := handler.Dispatcher(payload, subject, body)
|
||||
dispatchFn, err := handler.Dispatcher(payload, subject, body, helpers())
|
||||
require.NoError(t, err)
|
||||
|
||||
msgID := uuid.New()
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package dispatch_test
|
||||
|
||||
func helpers() map[string]any {
|
||||
return map[string]any{
|
||||
"base_url": func() string { return "http://test.com" },
|
||||
"current_year": func() string { return "2024" },
|
||||
"logo_url": func() string { return "https://coder.com/coder-logo-horizontal.png" },
|
||||
"app_name": func() string { return "Coder" },
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"text/template"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -41,7 +42,7 @@ func NewWebhookHandler(cfg codersdk.NotificationsWebhookConfig, log slog.Logger)
|
||||
return &WebhookHandler{cfg: cfg, log: log, cl: &http.Client{}}
|
||||
}
|
||||
|
||||
func (w *WebhookHandler) Dispatcher(payload types.MessagePayload, titleMarkdown, bodyMarkdown string) (DeliveryFunc, error) {
|
||||
func (w *WebhookHandler) Dispatcher(payload types.MessagePayload, titleMarkdown, bodyMarkdown string, _ template.FuncMap) (DeliveryFunc, error) {
|
||||
if w.cfg.Endpoint.String() == "" {
|
||||
return nil, xerrors.New("webhook endpoint not defined")
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ func TestWebhook(t *testing.T) {
|
||||
Endpoint: *serpent.URLOf(endpoint),
|
||||
}
|
||||
handler := dispatch.NewWebhookHandler(cfg, logger.With(slog.F("test", tc.name)))
|
||||
deliveryFn, err := handler.Dispatcher(msgPayload, titleMarkdown, bodyMarkdown)
|
||||
deliveryFn, err := handler.Dispatcher(msgPayload, titleMarkdown, bodyMarkdown, helpers())
|
||||
require.NoError(t, err)
|
||||
|
||||
retryable, err := deliveryFn(ctx, msgID)
|
||||
|
||||
Reference in New Issue
Block a user