iris/mail/service.go

108 lines
2.6 KiB
Go

package mail
import (
"encoding/base64"
"fmt"
"net/mail"
"net/smtp"
"strings"
"github.com/kataras/iris/config"
"github.com/kataras/iris/utils"
)
var buf = utils.NewBufferPool(64)
type (
// Service is the interface which mail sender should implement
Service interface {
// Send sends a mail to recipients
// the body can be html also
Send(to []string, subject, body string) error
}
mailer struct {
config config.Mail
fromAddr mail.Address
auth smtp.Auth
authenticated bool
}
)
// New creates and returns a new Service
func New(cfg config.Mail) Service {
m := &mailer{config: cfg}
if cfg.FromAlias == "" {
if !cfg.UseCommand && cfg.Username != "" && strings.Contains(cfg.Username, "@") {
m.fromAddr = mail.Address{cfg.Username[0:strings.IndexByte(cfg.Username, '@')], cfg.Username}
}
} else {
m.fromAddr = mail.Address{cfg.FromAlias, cfg.Username}
}
return m
}
// Send sends a mail to recipients
// the body can be html also
func (m *mailer) Send(to []string, subject, body string) error {
if m.config.UseCommand {
return m.sendCmd(to, subject, body)
}
return m.sendSMTP(to, subject, body)
}
func (m *mailer) sendSMTP(to []string, subject, body string) error {
buffer := buf.Get()
defer buf.Put(buffer)
if !m.authenticated {
if m.config.Username == "" || m.config.Password == "" || m.config.Host == "" || m.config.Port <= 0 {
return fmt.Errorf("Username, Password, Host & Port cannot be empty when using SMTP!")
}
m.auth = smtp.PlainAuth("", m.config.Username, m.config.Password, m.config.Host)
m.authenticated = true
}
fullhost := fmt.Sprintf("%s:%d", m.config.Host, m.config.Port)
/* START: This one helped me https://gist.github.com/andelf/5004821 */
header := make(map[string]string)
header["From"] = m.fromAddr.String()
header["To"] = strings.Join(to, ",")
header["Subject"] = subject
header["MIME-Version"] = "1.0"
header["Content-Type"] = "text/html; charset=\"utf-8\""
header["Content-Transfer-Encoding"] = "base64"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
/* END */
return smtp.SendMail(
fmt.Sprintf(fullhost),
m.auth,
m.config.Username,
to,
[]byte(message),
)
}
func (m *mailer) sendCmd(to []string, subject, body string) error {
buffer := buf.Get()
defer buf.Put(buffer)
cmd := utils.CommandBuilder("mail", "-s", subject, strings.Join(to, ","))
cmd.AppendArguments("-a", "Content-type: text/html") //always html on
cmd.Stdin = buffer
_, err := cmd.Output()
return err
}