Alerting: Add EmbeddedContents as alternative embedding in smtp (#99937)

Adds support for embedding []byte in SmtpClient instead of filenames. This is backwards compatible as it uses a new field EmbeddedContents to add an alternative to the existing EmbeddedFiles which takes filenames.
This commit is contained in:
Matthew Jacobson 2025-02-05 11:12:30 -05:00 committed by GitHub
parent 0ca1febb77
commit a93664ff3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 77 additions and 35 deletions

View File

@ -11,17 +11,24 @@ type AttachedFile struct {
Content []byte
}
// EmbeddedContent struct represents an embedded file.
type EmbeddedContent struct {
Name string
Content []byte
}
// Message is representation of the email message.
type Message struct {
To []string
SingleEmail bool
From string
Subject string
Body map[string]string
Info string
ReplyTo []string
EmbeddedFiles []string
AttachedFiles []*AttachedFile
To []string
SingleEmail bool
From string
Subject string
Body map[string]string
Info string
ReplyTo []string
EmbeddedFiles []string
EmbeddedContents []EmbeddedContent
AttachedFiles []*AttachedFile
}
func setDefaultTemplateData(cfg *setting.Cfg, data map[string]any, u *user.User) {

View File

@ -112,14 +112,15 @@ func (ns *NotificationService) buildEmailMessage(cmd *SendEmailCommand) (*Messag
addr := mail.Address{Name: ns.Cfg.Smtp.FromName, Address: ns.Cfg.Smtp.FromAddress}
return &Message{
To: cmd.To,
SingleEmail: cmd.SingleEmail,
From: addr.String(),
Subject: subject,
Body: body,
EmbeddedFiles: cmd.EmbeddedFiles,
AttachedFiles: buildAttachedFiles(cmd.AttachedFiles),
ReplyTo: cmd.ReplyTo,
To: cmd.To,
SingleEmail: cmd.SingleEmail,
From: addr.String(),
Subject: subject,
Body: body,
EmbeddedFiles: cmd.EmbeddedFiles,
EmbeddedContents: cmd.EmbeddedContents,
AttachedFiles: buildAttachedFiles(cmd.AttachedFiles),
ReplyTo: cmd.ReplyTo,
}, nil
}

View File

@ -18,15 +18,16 @@ type SendEmailAttachFile struct {
// SendEmailCommand is the command for sending emails
type SendEmailCommand struct {
To []string
SingleEmail bool
Template string
Subject string
Data map[string]any
Info string
ReplyTo []string
EmbeddedFiles []string
AttachedFiles []*SendEmailAttachFile
To []string
SingleEmail bool
Template string
Subject string
Data map[string]any
Info string
ReplyTo []string
EmbeddedFiles []string
EmbeddedContents []EmbeddedContent
AttachedFiles []*SendEmailAttachFile
}
// SendEmailCommandSync is the command for sending emails synchronously

View File

@ -201,15 +201,16 @@ func __dangerouslyInjectHTML(s string) template.HTML {
func (ns *NotificationService) SendEmailCommandHandlerSync(ctx context.Context, cmd *SendEmailCommandSync) error {
message, err := ns.buildEmailMessage(&SendEmailCommand{
Data: cmd.Data,
Info: cmd.Info,
Template: cmd.Template,
To: cmd.To,
SingleEmail: cmd.SingleEmail,
EmbeddedFiles: cmd.EmbeddedFiles,
AttachedFiles: cmd.AttachedFiles,
Subject: cmd.Subject,
ReplyTo: cmd.ReplyTo,
Data: cmd.Data,
Info: cmd.Info,
Template: cmd.Template,
To: cmd.To,
SingleEmail: cmd.SingleEmail,
EmbeddedFiles: cmd.EmbeddedFiles,
EmbeddedContents: cmd.EmbeddedContents,
AttachedFiles: cmd.AttachedFiles,
Subject: cmd.Subject,
ReplyTo: cmd.ReplyTo,
})
if err != nil {
return err

View File

@ -132,6 +132,31 @@ func TestSendEmailSync(t *testing.T) {
require.Equal(t, []byte("text file content"), file.Content)
})
t.Run("When embedding readers to emails", func(t *testing.T) {
ns, mailer := createSut(t, bus)
cmd := &SendEmailCommandSync{
SendEmailCommand: SendEmailCommand{
Subject: "subject",
To: []string{"asdf@grafana.com"},
SingleEmail: true,
Template: "welcome_on_signup",
EmbeddedContents: []EmbeddedContent{
{Name: "embed.jpg", Content: []byte("image content")},
},
},
}
err := ns.SendEmailCommandHandlerSync(context.Background(), cmd)
require.NoError(t, err)
require.NotEmpty(t, mailer.Sent)
sent := mailer.Sent[len(mailer.Sent)-1]
require.Len(t, sent.EmbeddedContents, 1)
f := sent.EmbeddedContents[0]
require.Equal(t, "embed.jpg", f.Name)
require.Equal(t, "image content", string(f.Content))
})
t.Run("When SMTP disabled in configuration", func(t *testing.T) {
cfg := createSmtpConfig()
cfg.Smtp.Enabled = false

View File

@ -142,6 +142,13 @@ func (sc *SmtpClient) setFiles(
m.Embed(file)
}
for _, file := range msg.EmbeddedContents {
m.Embed(file.Name, gomail.SetCopyFunc(func(writer io.Writer) error {
_, err := writer.Write(file.Content)
return err
}))
}
for _, file := range msg.AttachedFiles {
file := file
m.Attach(file.Name, gomail.SetCopyFunc(func(writer io.Writer) error {