Handling SMTP TLS via email.SendWithTLS

pull/146/head
Jordan Wright 2016-02-12 21:24:05 -06:00
parent 80333a93ec
commit 26577bc3c3
1 changed files with 25 additions and 87 deletions

View File

@ -3,9 +3,9 @@ package worker
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"log"
"net"
"net/mail"
"net/smtp"
"os"
@ -54,6 +54,10 @@ func processCampaign(c *models.Campaign) {
if c.SMTP.Username != "" && c.SMTP.Password != "" {
auth = smtp.PlainAuth("", c.SMTP.Username, c.SMTP.Password, strings.Split(c.SMTP.Host, ":")[0])
}
tc := &tls.Config{
ServerName: c.SMTP.Host,
InsecureSkipVerify: c.SMTP.IgnoreCertErrors,
}
f, err := mail.ParseAddress(c.SMTP.FromAddress)
if err != nil {
Logger.Println(err)
@ -110,14 +114,23 @@ func processCampaign(c *models.Campaign) {
Logger.Println("Creating email using template")
e.To = []string{t.Email}
Logger.Printf("Sending Email to %s\n", t.Email)
err = e.Send(c.SMTP.Host, auth)
err = e.SendWithTLS(c.SMTP.Host, auth, tc)
if err != nil {
Logger.Println(err)
es := struct {
Error string `json:"error"`
}{
Error: err.Error(),
}
ej, err := json.Marshal(es)
if err != nil {
Logger.Println(err)
}
err = t.UpdateStatus(models.ERROR)
if err != nil {
Logger.Println(err)
}
err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR})
err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR, Details: string(ej)})
if err != nil {
Logger.Println(err)
}
@ -143,6 +156,14 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
Subject: s.Template.Subject,
From: s.SMTP.FromAddress,
}
var auth smtp.Auth
if s.SMTP.Username != "" && s.SMTP.Password != "" {
auth = smtp.PlainAuth("", s.SMTP.Username, s.SMTP.Password, strings.Split(s.SMTP.Host, ":")[0])
}
t := &tls.Config{
ServerName: s.SMTP.Host,
InsecureSkipVerify: s.SMTP.IgnoreCertErrors,
}
f, err := mail.ParseAddress(s.SMTP.FromAddress)
if err != nil {
Logger.Println(err)
@ -186,7 +207,7 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
e.Subject = string(subjBuff.Bytes())
e.To = []string{s.Email}
Logger.Printf("Sending Email to %s\n", s.Email)
err = sendMail(e, s.SMTP)
err = e.SendWithTLS(s.SMTP.Host, auth, t)
if err != nil {
Logger.Println(err)
// For now, let's split the error and return
@ -196,86 +217,3 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
}
return err
}
// sendEmail is a copy of the net/smtp#SendMail function
// that has the option to ignore TLS errors
// TODO: Find a more elegant way (maybe in the email lib?) to do this
func sendMail(e email.Email, s models.SMTP) error {
var auth smtp.Auth
if s.Username != "" && s.Password != "" {
auth = smtp.PlainAuth("", s.Username, s.Password, strings.Split(s.Host, ":")[0])
}
// Taken from the email library
// Merge the To, Cc, and Bcc fields
to := make([]string, 0, len(e.To)+len(e.Cc)+len(e.Bcc))
to = append(append(append(to, e.To...), e.Cc...), e.Bcc...)
for i := 0; i < len(to); i++ {
addr, err := mail.ParseAddress(to[i])
if err != nil {
return err
}
to[i] = addr.Address
}
// Check to make sure there is at least one recipient and one "From" address
if e.From == "" || len(to) == 0 {
return errors.New("Must specify at least one From address and one To address")
}
from, err := mail.ParseAddress(e.From)
if err != nil {
return err
}
msg, err := e.Bytes()
if err != nil {
return err
}
// Taken from the standard library
// https://github.com/golang/go/blob/master/src/net/smtp/smtp.go#L300
c, err := smtp.Dial(s.Host)
if err != nil {
return err
}
defer c.Close()
if err = c.Hello("localhost"); err != nil {
return err
}
// Use TLS if available
if ok, _ := c.Extension("STARTTLS"); ok {
host, _, _ := net.SplitHostPort(s.Host)
config := &tls.Config{
ServerName: host,
InsecureSkipVerify: s.IgnoreCertErrors,
}
if err = c.StartTLS(config); err != nil {
return err
}
}
if auth != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(auth); err != nil {
return err
}
}
}
if err = c.Mail(from.Address); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
_, err = w.Write(msg)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
}