Просмотр исходного кода

Simplified emailing system and combined mailer and notifications packages

Torkel Ödegaard 10 лет назад
Родитель
Сommit
42fc68baa5

+ 0 - 2
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)

+ 5 - 23
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,
-	}
-}

+ 13 - 9
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
 }

+ 7 - 13
pkg/services/mailer/mailer.go → 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

+ 23 - 12
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
-
-	mailTemplates.ExecuteTemplate(&buffer, tmplResetPassword, data)
+	setDefaultTemplateData(data, nil)
+	mailTemplates.ExecuteTemplate(&buffer, cmd.Template, 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 == "" {

+ 6 - 7
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")
 		})
 	})