@@ -2,46 +2,54 @@ package email
22
33import (
44 "bytes"
5+ "crypto/tls"
56 "fmt"
67 "html/template"
78 "net/mail"
89 "net/smtp"
910
11+ "net"
12+
13+ "time"
14+
1015 "github.com/labstack/gommon/random"
1116)
1217
1318type (
1419 Email struct {
1520 Auth smtp.Auth
21+ Header map [string ]string
1622 Template * template.Template
1723 smtpAddress string
1824 }
1925
2026 Message struct {
21- From string
22- To string
23- CC string
24- Subject string
25- Text string
26- HTML string
27- TemplateName string
28- TemplateData interface {}
29- Inlines []* File
30- Attachments []* File
27+ ID string `json:"id"`
28+ From string `json:"from"`
29+ To string `json:"to"`
30+ CC string `json:"cc"`
31+ Subject string `json:"subject"`
32+ Text string `json:"text"`
33+ HTML string `json:"html"`
34+ TemplateName string `json:"template_name"`
35+ TemplateData interface {} `json:"template_data"`
36+ Inlines []* File `json:"inlines"`
37+ Attachments []* File `json:"attachments"`
3138 buffer * bytes.Buffer
3239 boundary string
3340 }
3441
3542 File struct {
36- Name string
37- Type string
38- Content string
43+ Name string `json:"name"`
44+ Type string `json:"type"`
45+ Content string `json:"content"`
3946 }
4047)
4148
4249func New (smtpAddress string ) * Email {
4350 return & Email {
4451 smtpAddress : smtpAddress ,
52+ Header : map [string ]string {},
4553 }
4654}
4755
@@ -62,20 +70,33 @@ func (m *Message) writeFile(f *File, disposition string) {
6270 m .buffer .WriteString (f .Content + "\r \n " )
6371}
6472
65- func (e * Email ) Send (m * Message ) error {
73+ func (e * Email ) Send (m * Message ) (err error ) {
74+ // Message header
6675 m .buffer = new (bytes.Buffer )
6776 m .boundary = random .String (16 )
6877 m .buffer .WriteString ("MIME-Version: 1.0\r \n " )
69- m .buffer .WriteString (fmt .Sprintf ("CC: %s\r \n " , m .CC ))
70- m .buffer .WriteString (fmt .Sprintf ("Subject: %s\r \n " , m .Subject ))
78+ m .buffer .WriteString (fmt .Sprintf ("Message-Id: %s\r \n " , m .ID ))
79+ m .buffer .WriteString (fmt .Sprintf ("Date: %s\r \n " , time .Now ().Format (time .RFC1123Z )))
80+ m .buffer .WriteString (fmt .Sprintf ("From: %s\r \n " , m .From ))
81+ m .buffer .WriteString (fmt .Sprintf ("To: %s\r \n " , m .From ))
82+ if m .CC != "" {
83+ m .buffer .WriteString (fmt .Sprintf ("CC: %s\r \n " , m .CC ))
84+ }
85+ if m .Subject != "" {
86+ m .buffer .WriteString (fmt .Sprintf ("Subject: %s\r \n " , m .Subject ))
87+ }
88+ // Extra
89+ for k , v := range e .Header {
90+ m .buffer .WriteString (fmt .Sprintf ("%s: %s\r \n " , k , v ))
91+ }
7192 m .buffer .WriteString (fmt .Sprintf ("Content-Type: multipart/mixed; boundary=%s\r \n " , m .boundary ))
7293 m .buffer .WriteString ("\r \n " )
7394
7495 // Message body
7596 if m .TemplateName != "" {
7697 buf := new (bytes.Buffer )
77- if err : = e .Template .ExecuteTemplate (buf , m .TemplateName , m .TemplateData ); err != nil {
78- return err
98+ if err = e .Template .ExecuteTemplate (buf , m .TemplateName , m .TemplateData ); err != nil {
99+ return
79100 }
80101 m .writeText (buf .String (), "text/html" )
81102 } else if m .Text != "" {
@@ -96,39 +117,51 @@ func (e *Email) Send(m *Message) error {
96117 m .buffer .WriteString ("\r \n " )
97118 m .buffer .WriteString ("--" + m .boundary + "--" )
98119
99- // Send message
120+ // Dial
100121 c , err := smtp .Dial (e .smtpAddress )
101- if e .Auth != nil {
102- // Authenticate
103- if err := c .Auth (e .Auth ); err != nil {
122+ if err != nil {
123+ return
124+ }
125+ defer c .Close ()
126+
127+ // Check if TLS is required
128+ if ok , _ := c .Extension ("STARTTLS" ); ok {
129+ host , _ , _ := net .SplitHostPort (e .smtpAddress )
130+ config := & tls.Config {ServerName : host }
131+ if err = c .StartTLS (config ); err != nil {
104132 return err
105133 }
106134 }
107- if err != nil {
108- return err
135+
136+ // Authenticate
137+ if e .Auth != nil {
138+ if err = c .Auth (e .Auth ); err != nil {
139+ return
140+ }
109141 }
110- defer c .Close ()
142+
143+ // Send message
111144 from , err := mail .ParseAddress (m .From )
112145 if err != nil {
113- return err
146+ return
114147 }
115148 if err = c .Mail (from .Address ); err != nil {
116- return err
149+ return
117150 }
118151 to , err := mail .ParseAddressList (m .To )
119152 if err != nil {
120- return err
153+ return
121154 }
122155 for _ , a := range to {
123156 if err = c .Rcpt (a .Address ); err != nil {
124- return err
157+ return
125158 }
126159 }
127160 wc , err := c .Data ()
128161 if err != nil {
129- return err
162+ return
130163 }
131164 defer wc .Close ()
132165 _ , err = m .buffer .WriteTo (wc )
133- return err
166+ return
134167}
0 commit comments