From 42fc68baa5cfc56d9758c9bf4c3dcc343fa40142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 8 Jun 2015 16:51:25 +0200 Subject: [PATCH] Simplified emailing system and combined mailer and notifications packages --- main.go | 2 -- pkg/models/emails.go | 28 +++------------ pkg/services/notifications/email.go | 22 +++++++----- .../{mailer => notifications}/mailer.go | 20 ++++------- pkg/services/notifications/notifications.go | 35 ++++++++++++------- .../notifications/notifications_test.go | 13 ++++--- 6 files changed, 54 insertions(+), 66 deletions(-) rename pkg/services/{mailer => notifications}/mailer.go (90%) diff --git a/main.go b/main.go index e49ec8b4fa9..a732e1a166f 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,6 @@ import ( "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/eventpublisher" - "github.com/grafana/grafana/pkg/services/mailer" "github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" @@ -58,7 +57,6 @@ func main() { social.NewOAuthService() eventpublisher.Init() plugins.Init() - mailer.Init() if err := notifications.Init(); err != nil { log.Fatal(3, "Notification service failed to initialize", err) diff --git a/pkg/models/emails.go b/pkg/models/emails.go index b7812e756f4..74da180f7d8 100644 --- a/pkg/models/emails.go +++ b/pkg/models/emails.go @@ -5,12 +5,11 @@ import "errors" var ErrInvalidEmailCode = errors.New("Invalid or expired email code") type SendEmailCommand struct { - To []string - From string - Subject string - Body string - Massive bool - Info string + To []string + Template string + Data map[string]interface{} + Massive bool + Info string } type SendResetPasswordEmailCommand struct { @@ -21,20 +20,3 @@ type ValidateResetPasswordCodeQuery struct { Code string Result *User } - -// create mail content -func (m *SendEmailCommand) Content() string { - contentType := "text/html; charset=UTF-8" - content := "From: " + m.From + "\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body - return content -} - -// Create html mail command -func NewSendEmailCommand(To []string, From, Subject, Body string) SendEmailCommand { - return SendEmailCommand{ - To: To, - From: From, - Subject: Subject, - Body: Body, - } -} diff --git a/pkg/services/notifications/email.go b/pkg/services/notifications/email.go index 299b6315f17..f81f3e1007b 100644 --- a/pkg/services/notifications/email.go +++ b/pkg/services/notifications/email.go @@ -5,18 +5,23 @@ import ( "github.com/grafana/grafana/pkg/setting" ) -// Create New mail message use MailFrom and MailUser -func newMailMessageFrom(To []string, from, subject, body string) m.SendEmailCommand { - return m.NewSendEmailCommand(To, from, subject, body) +type Message struct { + To []string + From string + Subject string + Body string + Massive bool + Info string } -// Create New mail message use MailFrom and MailUser -func newMailMessage(To string, subject, body string) m.SendEmailCommand { - return newMailMessageFrom([]string{To}, setting.Smtp.FromAddress, subject, body) +// create mail content +func (m *Message) Content() string { + contentType := "text/html; charset=UTF-8" + content := "From: " + m.From + "\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body + return content } -func getMailTmplData(u *m.User) map[interface{}]interface{} { - data := make(map[interface{}]interface{}, 10) +func setDefaultTemplateData(data map[string]interface{}, u *m.User) { data["AppUrl"] = setting.AppUrl data["BuildVersion"] = setting.BuildVersion data["BuildStamp"] = setting.BuildStamp @@ -25,5 +30,4 @@ func getMailTmplData(u *m.User) map[interface{}]interface{} { if u != nil { data["Name"] = u.NameOrFallback() } - return data } diff --git a/pkg/services/mailer/mailer.go b/pkg/services/notifications/mailer.go similarity index 90% rename from pkg/services/mailer/mailer.go rename to pkg/services/notifications/mailer.go index c3a1fe3ce63..597b536dca1 100644 --- a/pkg/services/mailer/mailer.go +++ b/pkg/services/notifications/mailer.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package mailer +package notifications import ( "crypto/tls" @@ -13,18 +13,14 @@ import ( "os" "strings" - "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" - m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) -var mailQueue chan *m.SendEmailCommand +var mailQueue chan *Message -func Init() { - bus.AddHandler("email", handleEmailCommand) - - mailQueue = make(chan *m.SendEmailCommand, 10) +func initMailQueue() { + mailQueue = make(chan *Message, 10) setting.Smtp = setting.SmtpSettings{ Host: "smtp.gmail.com:587", @@ -55,10 +51,8 @@ func processMailQueue() { } } -func handleEmailCommand(cmd *m.SendEmailCommand) error { - log.Info("Sending on queue") - mailQueue <- cmd - return nil +var addToMailQueue = func(msg *Message) { + mailQueue <- msg } func sendToSmtpServer(recipients []string, msgContent []byte) error { @@ -162,7 +156,7 @@ func sendToSmtpServer(recipients []string, msgContent []byte) error { return client.Quit() } -func buildAndSend(msg *m.SendEmailCommand) (int, error) { +func buildAndSend(msg *Message) (int, error) { log.Trace("Sending mails to: %s", strings.Join(msg.To, "; ")) // get message body diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go index 8a162455248..c78a6dd1350 100644 --- a/pkg/services/notifications/notifications.go +++ b/pkg/services/notifications/notifications.go @@ -16,8 +16,11 @@ var mailTemplates *template.Template var tmplResetPassword = "reset_password.html" func Init() error { + initMailQueue() + bus.AddHandler("email", sendResetPasswordEmail) bus.AddHandler("email", validateResetPasswordCode) + bus.AddHandler("email", sendEmailCommandHandler) mailTemplates = template.New("name") mailTemplates.Funcs(template.FuncMap{ @@ -41,26 +44,23 @@ func Init() error { return nil } -var dispatchMail = func(cmd *m.SendEmailCommand) error { - return bus.Dispatch(cmd) -} - func subjectTemplateFunc(obj map[string]interface{}, value string) string { obj["value"] = value return "" } -func sendResetPasswordEmail(cmd *m.SendResetPasswordEmailCommand) error { +func sendEmailCommandHandler(cmd *m.SendEmailCommand) error { var buffer bytes.Buffer + data := cmd.Data + if data == nil { + data = make(map[string]interface{}, 10) + } - var data = getMailTmplData(cmd.User) - code := createUserEmailCode(cmd.User, nil) - data["Code"] = code + setDefaultTemplateData(data, nil) + mailTemplates.ExecuteTemplate(&buffer, cmd.Template, data) - mailTemplates.ExecuteTemplate(&buffer, tmplResetPassword, data) - - dispatchMail(&m.SendEmailCommand{ - To: []string{cmd.User.Email}, + addToMailQueue(&Message{ + To: cmd.To, From: setting.Smtp.FromAddress, Subject: data["Subject"].(map[string]interface{})["value"].(string), Body: buffer.String(), @@ -69,6 +69,17 @@ func sendResetPasswordEmail(cmd *m.SendResetPasswordEmailCommand) error { return nil } +func sendResetPasswordEmail(cmd *m.SendResetPasswordEmailCommand) error { + return sendEmailCommandHandler(&m.SendEmailCommand{ + To: []string{cmd.User.Email}, + Template: tmplResetPassword, + Data: map[string]interface{}{ + "Code": createUserEmailCode(cmd.User, nil), + "Name": cmd.User.NameOrFallback(), + }, + }) +} + func validateResetPasswordCode(query *m.ValidateResetPasswordCodeQuery) error { login := getLoginForEmailCode(query.Code) if login == "" { diff --git a/pkg/services/notifications/notifications_test.go b/pkg/services/notifications/notifications_test.go index 8470aa06b83..ef600b63126 100644 --- a/pkg/services/notifications/notifications_test.go +++ b/pkg/services/notifications/notifications_test.go @@ -20,17 +20,16 @@ func TestNotifications(t *testing.T) { err := Init() So(err, ShouldBeNil) - var sentMail *m.SendEmailCommand - dispatchMail = func(cmd *m.SendEmailCommand) error { - sentMail = cmd - return nil + var sentMsg *Message + addToMailQueue = func(msg *Message) { + sentMsg = msg } Convey("When sending reset email password", func() { sendResetPasswordEmail(&m.SendResetPasswordEmailCommand{User: &m.User{Email: "asd@asd.com"}}) - So(sentMail.Body, ShouldContainSubstring, "body") - So(sentMail.Subject, ShouldEqual, "Reset your Grafana password") - So(sentMail.Body, ShouldNotContainSubstring, "Subject") + So(sentMsg.Body, ShouldContainSubstring, "body") + So(sentMsg.Subject, ShouldEqual, "Reset your Grafana password") + So(sentMsg.Body, ShouldNotContainSubstring, "Subject") }) })