Explorar o código

Email: tls support

Signed-off-by: Vishal Rana <vr@labstack.com>
Vishal Rana %!s(int64=8) %!d(string=hai) anos
pai
achega
79a1921bbe
Modificáronse 1 ficheiros con 64 adicións e 31 borrados
  1. 64 31
      email/email.go

+ 64 - 31
email/email.go

@@ -2,46 +2,54 @@ package email
 
 import (
 	"bytes"
+	"crypto/tls"
 	"fmt"
 	"html/template"
 	"net/mail"
 	"net/smtp"
 
+	"net"
+
+	"time"
+
 	"github.com/labstack/gommon/random"
 )
 
 type (
 	Email struct {
 		Auth        smtp.Auth
+		Header      map[string]string
 		Template    *template.Template
 		smtpAddress string
 	}
 
 	Message struct {
-		From         string
-		To           string
-		CC           string
-		Subject      string
-		Text         string
-		HTML         string
-		TemplateName string
-		TemplateData interface{}
-		Inlines      []*File
-		Attachments  []*File
+		ID           string      `json:"id"`
+		From         string      `json:"from"`
+		To           string      `json:"to"`
+		CC           string      `json:"cc"`
+		Subject      string      `json:"subject"`
+		Text         string      `json:"text"`
+		HTML         string      `json:"html"`
+		TemplateName string      `json:"template_name"`
+		TemplateData interface{} `json:"template_data"`
+		Inlines      []*File     `json:"inlines"`
+		Attachments  []*File     `json:"attachments"`
 		buffer       *bytes.Buffer
 		boundary     string
 	}
 
 	File struct {
-		Name    string
-		Type    string
-		Content string
+		Name    string `json:"name"`
+		Type    string `json:"type"`
+		Content string `json:"content"`
 	}
 )
 
 func New(smtpAddress string) *Email {
 	return &Email{
 		smtpAddress: smtpAddress,
+		Header:      map[string]string{},
 	}
 }
 
@@ -62,20 +70,33 @@ func (m *Message) writeFile(f *File, disposition string) {
 	m.buffer.WriteString(f.Content + "\r\n")
 }
 
-func (e *Email) Send(m *Message) error {
+func (e *Email) Send(m *Message) (err error) {
+	// Message header
 	m.buffer = new(bytes.Buffer)
 	m.boundary = random.String(16)
 	m.buffer.WriteString("MIME-Version: 1.0\r\n")
-	m.buffer.WriteString(fmt.Sprintf("CC: %s\r\n", m.CC))
-	m.buffer.WriteString(fmt.Sprintf("Subject: %s\r\n", m.Subject))
+	m.buffer.WriteString(fmt.Sprintf("Message-Id: %s\r\n", m.ID))
+	m.buffer.WriteString(fmt.Sprintf("Date: %s\r\n", time.Now().Format(time.RFC1123Z)))
+	m.buffer.WriteString(fmt.Sprintf("From: %s\r\n", m.From))
+	m.buffer.WriteString(fmt.Sprintf("To: %s\r\n", m.From))
+	if m.CC != "" {
+		m.buffer.WriteString(fmt.Sprintf("CC: %s\r\n", m.CC))
+	}
+	if m.Subject != "" {
+		m.buffer.WriteString(fmt.Sprintf("Subject: %s\r\n", m.Subject))
+	}
+	// Extra
+	for k, v := range e.Header {
+		m.buffer.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
+	}
 	m.buffer.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\r\n", m.boundary))
 	m.buffer.WriteString("\r\n")
 
 	// Message body
 	if m.TemplateName != "" {
 		buf := new(bytes.Buffer)
-		if err := e.Template.ExecuteTemplate(buf, m.TemplateName, m.TemplateData); err != nil {
-			return err
+		if err = e.Template.ExecuteTemplate(buf, m.TemplateName, m.TemplateData); err != nil {
+			return
 		}
 		m.writeText(buf.String(), "text/html")
 	} else if m.Text != "" {
@@ -96,39 +117,51 @@ func (e *Email) Send(m *Message) error {
 	m.buffer.WriteString("\r\n")
 	m.buffer.WriteString("--" + m.boundary + "--")
 
-	// Send message
+	// Dial
 	c, err := smtp.Dial(e.smtpAddress)
-	if e.Auth != nil {
-		// Authenticate
-		if err := c.Auth(e.Auth); err != nil {
+	if err != nil {
+		return
+	}
+	defer c.Close()
+
+	// Check if TLS is required
+	if ok, _ := c.Extension("STARTTLS"); ok {
+		host, _, _ := net.SplitHostPort(e.smtpAddress)
+		config := &tls.Config{ServerName: host}
+		if err = c.StartTLS(config); err != nil {
 			return err
 		}
 	}
-	if err != nil {
-		return err
+
+	// Authenticate
+	if e.Auth != nil {
+		if err = c.Auth(e.Auth); err != nil {
+			return
+		}
 	}
-	defer c.Close()
+
+	// Send message
 	from, err := mail.ParseAddress(m.From)
 	if err != nil {
-		return err
+		return
 	}
 	if err = c.Mail(from.Address); err != nil {
-		return err
+		return
 	}
 	to, err := mail.ParseAddressList(m.To)
 	if err != nil {
-		return err
+		return
 	}
 	for _, a := range to {
 		if err = c.Rcpt(a.Address); err != nil {
-			return err
+			return
 		}
 	}
 	wc, err := c.Data()
 	if err != nil {
-		return err
+		return
 	}
 	defer wc.Close()
 	_, err = m.buffer.WriteTo(wc)
-	return err
+	return
 }