Commit 5bf5ed68 by bergquist

tech(notifications): replace internal email code

parent f7779983
......@@ -8,7 +8,6 @@ type SendEmailCommand struct {
To []string
Template string
Data map[string]interface{}
Massive bool
Info string
EmbededFiles []string
}
......
......@@ -10,18 +10,10 @@ type Message struct {
From string
Subject string
Body string
Massive bool
Info string
EmbededFiles []string
}
// 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 setDefaultTemplateData(data map[string]interface{}, u *m.User) {
data["AppUrl"] = setting.AppUrl
data["BuildVersion"] = setting.BuildVersion
......
......@@ -11,12 +11,8 @@ import (
"fmt"
"html/template"
"net"
"net/mail"
"net/smtp"
"os"
"strconv"
"strings"
"time"
"github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models"
......@@ -35,7 +31,7 @@ func processMailQueue() {
for {
select {
case msg := <-mailQueue:
num, err := buildAndSend(msg)
num, err := send(msg)
tos := strings.Join(msg.To, "; ")
info := ""
if err != nil {
......@@ -54,130 +50,42 @@ var addToMailQueue = func(msg *Message) {
mailQueue <- msg
}
func sendToSmtpServer(recipients []string, msgContent []byte) error {
host, port, err := net.SplitHostPort(setting.Smtp.Host)
func send(msg *Message) (int, error) {
dialer, err := createDialer()
if err != nil {
return err
}
tlsconfig := &tls.Config{
InsecureSkipVerify: setting.Smtp.SkipVerify,
ServerName: host,
}
if setting.Smtp.CertFile != "" {
cert, err := tls.LoadX509KeyPair(setting.Smtp.CertFile, setting.Smtp.KeyFile)
if err != nil {
return err
}
tlsconfig.Certificates = []tls.Certificate{cert}
}
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), time.Second*10)
if err != nil {
return err
}
defer conn.Close()
isSecureConn := false
// Start TLS directly if the port ends with 465 (SMTPS protocol)
if strings.HasSuffix(port, "465") {
conn = tls.Client(conn, tlsconfig)
isSecureConn = true
}
client, err := smtp.NewClient(conn, host)
if err != nil {
return err
}
hostname, err := os.Hostname()
if err != nil {
return err
}
if err = client.Hello(hostname); err != nil {
return err
}
// If not using SMTPS, alway use STARTTLS if available
hasStartTLS, _ := client.Extension("STARTTLS")
if !isSecureConn && hasStartTLS {
if err = client.StartTLS(tlsconfig); err != nil {
return err
}
return 0, err
}
canAuth, options := client.Extension("AUTH")
if canAuth && len(setting.Smtp.User) > 0 {
var auth smtp.Auth
if strings.Contains(options, "CRAM-MD5") {
auth = smtp.CRAMMD5Auth(setting.Smtp.User, setting.Smtp.Password)
} else if strings.Contains(options, "PLAIN") {
auth = smtp.PlainAuth("", setting.Smtp.User, setting.Smtp.Password, host)
for _, address := range msg.To {
m := gomail.NewMessage()
m.SetHeader("From", msg.From)
m.SetHeader("To", address)
m.SetHeader("Subject", msg.Subject)
for _, file := range msg.EmbededFiles {
m.Embed(file)
}
if auth != nil {
if err = client.Auth(auth); err != nil {
return err
}
}
}
if fromAddress, err := mail.ParseAddress(setting.Smtp.FromAddress); err != nil {
return err
} else {
if err = client.Mail(fromAddress.Address); err != nil {
return err
}
}
m.SetBody("text/html", msg.Body)
for _, rec := range recipients {
if err = client.Rcpt(rec); err != nil {
return err
if err := dialer.DialAndSend(m); err != nil {
return 0, err
}
}
w, err := client.Data()
if err != nil {
return err
}
if _, err = w.Write([]byte(msgContent)); err != nil {
return err
}
if err = w.Close(); err != nil {
return err
}
return client.Quit()
return len(msg.To), nil
}
func buildAndSend(msg *Message) (int, error) {
m := gomail.NewMessage()
m.SetHeader("From", msg.From)
m.SetHeader("To", msg.To[0])
m.SetHeader("Subject", msg.Subject)
for _, file := range msg.EmbededFiles {
m.Embed(file)
}
m.SetBody("text/html", msg.Body)
func createDialer() (*gomail.Dialer, error) {
host, port, err := net.SplitHostPort(setting.Smtp.Host)
if err != nil {
return 0, err
return nil, err
}
iPort, err := strconv.Atoi(port)
if err != nil {
return 0, err
return nil, err
}
d := gomail.NewPlainDialer(host, iPort, setting.Smtp.User, setting.Smtp.Password)
tlsconfig := &tls.Config{
InsecureSkipVerify: setting.Smtp.SkipVerify,
ServerName: host,
......@@ -186,72 +94,14 @@ func buildAndSend(msg *Message) (int, error) {
if setting.Smtp.CertFile != "" {
cert, err := tls.LoadX509KeyPair(setting.Smtp.CertFile, setting.Smtp.KeyFile)
if err != nil {
return 0, err
return nil, err
}
tlsconfig.Certificates = []tls.Certificate{cert}
}
d := gomail.NewPlainDialer(host, iPort, setting.Smtp.User, setting.Smtp.Password)
d.TLSConfig = tlsconfig
if err := d.DialAndSend(m); err != nil {
return 0, err
}
return 0, nil
/*
m := email.NewHTMLMessage(msg.Subject, msg.Body)
m.From = mail.Address{Name: "From", Address: "alerting@grafana.org"}
m.To = msg.To
log.Info2("Attaching file", "file", msg.Attachment)
if err := m.Attach(msg.Attachment); err != nil {
return 0, err
}
// send it
host, _, _ := net.SplitHostPort(setting.Smtp.Host)
auth := smtp.PlainAuth("", setting.Smtp.User, setting.Smtp.Password, host)
if err := email.Send(setting.Smtp.Host, auth, m); err != nil {
return 0, err
}
return 0, nil
log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
// get message body
content := msg.Content()
if len(msg.To) == 0 {
return 0, fmt.Errorf("empty receive emails")
} else if len(msg.Body) == 0 {
return 0, fmt.Errorf("empty email body")
}
if msg.Massive {
// send mail to multiple emails one by one
num := 0
for _, to := range msg.To {
body := []byte("To: " + to + "\r\n" + content)
err := sendToSmtpServer([]string{to}, body)
if err != nil {
return num, err
}
num++
}
return num, nil
} else {
body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content)
// send to multiple emails in one message
err := sendToSmtpServer(msg.To, body)
if err != nil {
return 0, err
} else {
return 1, nil
}
}
*/
return d, nil
}
func buildEmailMessage(cmd *m.SendEmailCommand) (*Message, error) {
......
......@@ -90,7 +90,6 @@ func sendEmailCommandHandlerSync(ctx context.Context, cmd *m.SendEmailCommandSyn
message, err := buildEmailMessage(&m.SendEmailCommand{
Data: cmd.Data,
Info: cmd.Info,
Massive: cmd.Massive,
Template: cmd.Template,
To: cmd.To,
EmbededFiles: cmd.EmbededFiles,
......@@ -100,7 +99,7 @@ func sendEmailCommandHandlerSync(ctx context.Context, cmd *m.SendEmailCommandSyn
return err
}
_, err = buildAndSend(message)
_, err = send(message)
return err
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment