mirror of
https://github.com/grafana/grafana.git
synced 2024-12-01 13:09:22 -06:00
b2ab57d14b
* remove result field from notifications * fix test
310 lines
9.0 KiB
Go
310 lines
9.0 KiB
Go
package notifications
|
|
|
|
import (
|
|
"context"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
func newBus(t *testing.T) bus.Bus {
|
|
t.Helper()
|
|
tracer := tracing.InitializeTracerForTest()
|
|
return bus.ProvideBus(tracer)
|
|
}
|
|
|
|
func TestProvideService(t *testing.T) {
|
|
bus := newBus(t)
|
|
|
|
t.Run("When invalid from_address in configuration", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.FromAddress = "@notanemail@"
|
|
_, _, err := createSutWithConfig(t, bus, cfg)
|
|
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("When all template_patterns fail to parse", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.TemplatesPatterns = []string{"/usr/not-a-dir/**", "/usr/also-not-a-dir/**"}
|
|
_, _, err := createSutWithConfig(t, bus, cfg)
|
|
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("When some template_patterns fail to parse", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.TemplatesPatterns = append(cfg.Smtp.TemplatesPatterns, "/usr/not-a-dir/**")
|
|
_, _, err := createSutWithConfig(t, bus, cfg)
|
|
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestSendEmailSync(t *testing.T) {
|
|
bus := newBus(t)
|
|
|
|
t.Run("When sending emails synchronously", func(t *testing.T) {
|
|
ns, mailer := createSut(t, bus)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"asdf@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
err := ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, mailer.Sent)
|
|
sent := mailer.Sent[len(mailer.Sent)-1]
|
|
require.Equal(t, "subject", sent.Subject)
|
|
require.Equal(t, []string{"asdf@grafana.com"}, sent.To)
|
|
})
|
|
|
|
t.Run("When using Single Email mode with multiple recipients", func(t *testing.T) {
|
|
ns, mailer := createSut(t, bus)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: true,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
|
|
err := ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, mailer.Sent, 1)
|
|
})
|
|
|
|
t.Run("When using Multi Email mode with multiple recipients", func(t *testing.T) {
|
|
ns, mailer := createSut(t, bus)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
|
|
err := ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, mailer.Sent, 3)
|
|
})
|
|
|
|
t.Run("When attaching files 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",
|
|
AttachedFiles: []*SendEmailAttachFile{
|
|
{
|
|
Name: "attachment.txt",
|
|
Content: []byte("text file 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.AttachedFiles, 1)
|
|
file := sent.AttachedFiles[len(sent.AttachedFiles)-1]
|
|
require.Equal(t, "attachment.txt", file.Name)
|
|
require.Equal(t, []byte("text file content"), file.Content)
|
|
})
|
|
|
|
t.Run("When SMTP disabled in configuration", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.Enabled = false
|
|
ns, mailer, err := createSutWithConfig(t, bus, cfg)
|
|
require.NoError(t, err)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: true,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
|
|
err = ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
|
|
require.ErrorIs(t, err, ErrSmtpNotEnabled)
|
|
require.Empty(t, mailer.Sent)
|
|
})
|
|
|
|
t.Run("When invalid content type in configuration", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.ContentTypes = append(cfg.Smtp.ContentTypes, "multipart/form-data")
|
|
ns, mailer, err := createSutWithConfig(t, bus, cfg)
|
|
require.NoError(t, err)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
|
|
err = ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
|
|
require.Error(t, err)
|
|
require.Empty(t, mailer.Sent)
|
|
})
|
|
|
|
t.Run("When SMTP dialer is disconnected", func(t *testing.T) {
|
|
ns := createDisconnectedSut(t, bus)
|
|
cmd := &SendEmailCommandSync{
|
|
SendEmailCommand: SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
},
|
|
}
|
|
|
|
err := ns.SendEmailCommandHandlerSync(context.Background(), cmd)
|
|
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestSendEmailAsync(t *testing.T) {
|
|
bus := newBus(t)
|
|
|
|
t.Run("When sending reset email password", func(t *testing.T) {
|
|
sut, _ := createSut(t, bus)
|
|
testuser := user.User{Email: "asd@asd.com", Login: "asd@asd.com"}
|
|
err := sut.SendResetPasswordEmail(context.Background(), &SendResetPasswordEmailCommand{User: &testuser})
|
|
|
|
require.NoError(t, err)
|
|
|
|
sentMsg := <-sut.mailQueue
|
|
assert.Contains(t, sentMsg.Body["text/html"], "body")
|
|
assert.NotContains(t, sentMsg.Body["text/plain"], "body")
|
|
assert.Equal(t, "Reset your Grafana password - asd@asd.com", sentMsg.Subject)
|
|
assert.NotContains(t, sentMsg.Body["text/html"], "Subject")
|
|
assert.NotContains(t, sentMsg.Body["text/plain"], "Subject")
|
|
|
|
// find code in mail
|
|
r, _ := regexp.Compile(`code=(\w+)`)
|
|
match := r.FindString(sentMsg.Body["text/plain"])
|
|
code := match[len("code="):]
|
|
|
|
// verify code
|
|
query := ValidateResetPasswordCodeQuery{Code: code}
|
|
getUserByLogin := func(ctx context.Context, login string) (*user.User, error) {
|
|
return &testuser, nil
|
|
}
|
|
_, err = sut.ValidateResetPasswordCode(context.Background(), &query, getUserByLogin)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("When SMTP disabled in configuration", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.Enabled = false
|
|
ns, mailer, err := createSutWithConfig(t, bus, cfg)
|
|
require.NoError(t, err)
|
|
cmd := &SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: true,
|
|
Template: "welcome_on_signup",
|
|
}
|
|
|
|
err = ns.SendEmailCommandHandler(context.Background(), cmd)
|
|
|
|
require.ErrorIs(t, err, ErrSmtpNotEnabled)
|
|
require.Empty(t, mailer.Sent)
|
|
})
|
|
|
|
t.Run("When invalid content type in configuration", func(t *testing.T) {
|
|
cfg := createSmtpConfig()
|
|
cfg.Smtp.ContentTypes = append(cfg.Smtp.ContentTypes, "multipart/form-data")
|
|
ns, mailer, err := createSutWithConfig(t, bus, cfg)
|
|
require.NoError(t, err)
|
|
cmd := &SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
}
|
|
|
|
err = ns.SendEmailCommandHandler(context.Background(), cmd)
|
|
|
|
require.Error(t, err)
|
|
require.Empty(t, mailer.Sent)
|
|
})
|
|
|
|
t.Run("When SMTP dialer is disconnected", func(t *testing.T) {
|
|
ns := createDisconnectedSut(t, bus)
|
|
cmd := &SendEmailCommand{
|
|
Subject: "subject",
|
|
To: []string{"1@grafana.com", "2@grafana.com", "3@grafana.com"},
|
|
SingleEmail: false,
|
|
Template: "welcome_on_signup",
|
|
}
|
|
|
|
err := ns.SendEmailCommandHandler(context.Background(), cmd)
|
|
|
|
// The async version should not surface connection errors via Bus. It should only log them.
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func createSut(t *testing.T, bus bus.Bus) (*NotificationService, *FakeMailer) {
|
|
t.Helper()
|
|
|
|
cfg := createSmtpConfig()
|
|
ns, fm, err := createSutWithConfig(t, bus, cfg)
|
|
require.NoError(t, err)
|
|
return ns, fm
|
|
}
|
|
|
|
func createSutWithConfig(t *testing.T, bus bus.Bus, cfg *setting.Cfg) (*NotificationService, *FakeMailer, error) {
|
|
smtp := NewFakeMailer()
|
|
ns, err := ProvideService(bus, cfg, smtp, nil)
|
|
return ns, smtp, err
|
|
}
|
|
|
|
func createDisconnectedSut(t *testing.T, bus bus.Bus) *NotificationService {
|
|
t.Helper()
|
|
|
|
cfg := createSmtpConfig()
|
|
smtp := NewFakeDisconnectedMailer()
|
|
ns, err := ProvideService(bus, cfg, smtp, nil)
|
|
require.NoError(t, err)
|
|
return ns
|
|
}
|
|
|
|
func createSmtpConfig() *setting.Cfg {
|
|
cfg := setting.NewCfg()
|
|
cfg.StaticRootPath = "../../../public/"
|
|
cfg.Smtp.Enabled = true
|
|
cfg.Smtp.TemplatesPatterns = []string{"emails/*.html", "emails/*.txt"}
|
|
cfg.Smtp.FromAddress = "from@address.com"
|
|
cfg.Smtp.FromName = "Grafana Admin"
|
|
cfg.Smtp.ContentTypes = []string{"text/html", "text/plain"}
|
|
return cfg
|
|
}
|