diff --git a/pkg/services/ngalert/notifier/channels/email.go b/pkg/services/ngalert/notifier/channels/email.go index 01e6e745569..ebf7dac61b8 100644 --- a/pkg/services/ngalert/notifier/channels/email.go +++ b/pkg/services/ngalert/notifier/channels/email.go @@ -89,12 +89,11 @@ func NewEmailNotifier(config *EmailConfig, ns notifications.EmailSender, images } // Notify sends the alert notification. -func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { +func (en *EmailNotifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, error) { var tmplErr error - tmpl, data := TmplText(ctx, en.tmpl, as, en.log, &tmplErr) + tmpl, data := TmplText(ctx, en.tmpl, alerts, en.log, &tmplErr) subject := tmpl(en.Subject) - alertPageURL := en.tmpl.ExternalURL.String() ruleURL := en.tmpl.ExternalURL.String() u, err := url.Parse(en.tmpl.ExternalURL.String()) @@ -108,6 +107,26 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, en.log.Debug("failed to parse external URL", "url", en.tmpl.ExternalURL.String(), "err", err.Error()) } + // Extend alerts data with images, if available. + var embeddedFiles []string + _ = withStoredImages(ctx, en.log, en.images, + func(index int, image *ngmodels.Image) error { + if image != nil { + if len(image.URL) != 0 { + data.Alerts[index].ImageURL = image.URL + } else if len(image.Path) != 0 { + _, err := os.Stat(image.Path) + if err == nil { + data.Alerts[index].EmbeddedImage = path.Base(image.Path) + embeddedFiles = append(embeddedFiles, image.Path) + } else { + en.log.Warn("failed to get image file for email attachment", "file", image.Path, "err", err) + } + } + } + return nil + }, alerts...) + cmd := &models.SendEmailCommandSync{ SendEmailCommand: models.SendEmailCommand{ Subject: subject, @@ -123,34 +142,13 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, "RuleUrl": ruleURL, "AlertPageUrl": alertPageURL, }, - To: en.Addresses, - SingleEmail: en.SingleEmail, - Template: "ng_alert_notification", + EmbeddedFiles: embeddedFiles, + To: en.Addresses, + SingleEmail: en.SingleEmail, + Template: "ng_alert_notification", }, } - // TODO: modify the email sender code to support multiple file or image URL - // fields. We cannot use images from every alert yet. - _ = withStoredImage(ctx, en.log, en.images, - func(index int, image *ngmodels.Image) error { - if image == nil { - return nil - } - - if len(image.URL) != 0 { - cmd.Data["ImageLink"] = image.URL - } else if len(image.Path) != 0 { - file, err := os.Stat(image.Path) - if err == nil { - cmd.EmbeddedFiles = []string{image.Path} - cmd.Data["EmbeddedImage"] = file.Name() - } else { - en.log.Warn("failed to access email notification image attachment data", "err", err) - } - } - return nil - }, 0, as...) - if tmplErr != nil { en.log.Warn("failed to template email message", "err", tmplErr.Error()) } diff --git a/pkg/services/ngalert/notifier/channels/template_data.go b/pkg/services/ngalert/notifier/channels/template_data.go index 93490f2c4c8..c021d8ecc37 100644 --- a/pkg/services/ngalert/notifier/channels/template_data.go +++ b/pkg/services/ngalert/notifier/channels/template_data.go @@ -18,18 +18,19 @@ import ( ) type ExtendedAlert struct { - Status string `json:"status"` - Labels template.KV `json:"labels"` - Annotations template.KV `json:"annotations"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` - GeneratorURL string `json:"generatorURL"` - Fingerprint string `json:"fingerprint"` - SilenceURL string `json:"silenceURL"` - DashboardURL string `json:"dashboardURL"` - PanelURL string `json:"panelURL"` - ValueString string `json:"valueString"` - ImageURL string `json:"imageURL,omitempty"` + Status string `json:"status"` + Labels template.KV `json:"labels"` + Annotations template.KV `json:"annotations"` + StartsAt time.Time `json:"startsAt"` + EndsAt time.Time `json:"endsAt"` + GeneratorURL string `json:"generatorURL"` + Fingerprint string `json:"fingerprint"` + SilenceURL string `json:"silenceURL"` + DashboardURL string `json:"dashboardURL"` + PanelURL string `json:"panelURL"` + ValueString string `json:"valueString"` + ImageURL string `json:"imageURL,omitempty"` + EmbeddedImage string `json:"embeddedImage,omitempty"` } type ExtendedAlerts []ExtendedAlert diff --git a/public/emails/ng_alert_notification.html b/public/emails/ng_alert_notification.html index 6c0e96c2f69..23ea84f08f0 100644 --- a/public/emails/ng_alert_notification.html +++ b/public/emails/ng_alert_notification.html @@ -210,6 +210,21 @@ text-decoration: underline; {{Subject .Subject "{{.Title}}"}} {{ define "alert" }} + + {{if ne .ImageURL "" }} + + + Alerting Panel + + + {{end}} + {{if ne .EmbeddedImage "" }} + + + Alerting Chart Attached Below + + + {{end}} Value: {{ .ValueString }}