Commit c5bca405 by Oleg Gaidarenko Committed by GitHub

Email: add reply-to and direct attachment (#18715)

* Add support for `Reply-To` header

* Allow direct attachment

Don't have tests yet, but they will follow
parent e5e7bd31
......@@ -5,15 +5,25 @@ import "errors"
var ErrInvalidEmailCode = errors.New("Invalid or expired email code")
var ErrSmtpNotEnabled = errors.New("SMTP not configured, check your grafana.ini config file's [smtp] section")
// SendEmailAttachFile is a definition of the attached files without path
type SendEmailAttachFile struct {
Name string
Content []byte
}
// SendEmailCommand is command for sending emails
type SendEmailCommand struct {
To []string
Template string
Subject string
Data map[string]interface{}
Info string
ReplyTo []string
EmbededFiles []string
AttachedFiles []*SendEmailAttachFile
}
// SendEmailCommandSync is command for sending emails in sync
type SendEmailCommandSync struct {
SendEmailCommand
}
......
......@@ -5,13 +5,22 @@ import (
"github.com/grafana/grafana/pkg/setting"
)
// AttachedFile is struct representating email attached files
type AttachedFile struct {
Name string
Content []byte
}
// Message is representation of the email message
type Message struct {
To []string
From string
Subject string
Body string
Info string
ReplyTo []string
EmbededFiles []string
AttachedFiles []*AttachedFile
}
func setDefaultTemplateData(data map[string]interface{}, u *m.User) {
......
......@@ -9,13 +9,15 @@ import (
"crypto/tls"
"fmt"
"html/template"
"io"
"net"
"strconv"
gomail "gopkg.in/mail.v2"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
gomail "gopkg.in/mail.v2"
)
func (ns *NotificationService) send(msg *Message) (int, error) {
......@@ -30,8 +32,11 @@ func (ns *NotificationService) send(msg *Message) (int, error) {
m.SetHeader("From", msg.From)
m.SetHeader("To", address)
m.SetHeader("Subject", msg.Subject)
for _, file := range msg.EmbededFiles {
m.Embed(file)
ns.setFiles(m, msg)
for _, replyTo := range msg.ReplyTo {
m.SetAddressHeader("Reply-To", replyTo, "")
}
m.SetBody("text/html", msg.Body)
......@@ -48,6 +53,23 @@ func (ns *NotificationService) send(msg *Message) (int, error) {
return num, err
}
// setFiles attaches files in various forms
func (ns *NotificationService) setFiles(
m *gomail.Message,
msg *Message,
) {
for _, file := range msg.EmbededFiles {
m.Embed(file)
}
for _, file := range msg.AttachedFiles {
m.Attach(file.Name, gomail.SetCopyFunc(func(writer io.Writer) error {
_, err := writer.Write(file.Content)
return err
}))
}
}
func (ns *NotificationService) createDialer() (*gomail.Dialer, error) {
host, port, err := net.SplitHostPort(ns.Cfg.Smtp.Host)
......@@ -132,5 +154,22 @@ func (ns *NotificationService) buildEmailMessage(cmd *models.SendEmailCommand) (
Subject: subject,
Body: buffer.String(),
EmbededFiles: cmd.EmbededFiles,
AttachedFiles: buildAttachedFiles(cmd.AttachedFiles),
}, nil
}
// buildAttachedFiles build attached files
func buildAttachedFiles(
attached []*models.SendEmailAttachFile,
) []*AttachedFile {
result := make([]*AttachedFile, 0)
for _, file := range attached {
result = append(result, &AttachedFile{
Name: file.Name,
Content: file.Content,
})
}
return result
}
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