@@ -2,46 +2,54 @@ package email
2
2
3
3
import (
4
4
"bytes"
5
+ "crypto/tls"
5
6
"fmt"
6
7
"html/template"
7
8
"net/mail"
8
9
"net/smtp"
9
10
11
+ "net"
12
+
13
+ "time"
14
+
10
15
"github.com/labstack/gommon/random"
11
16
)
12
17
13
18
type (
14
19
Email struct {
15
20
Auth smtp.Auth
21
+ Header map [string ]string
16
22
Template * template.Template
17
23
smtpAddress string
18
24
}
19
25
20
26
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"`
31
38
buffer * bytes.Buffer
32
39
boundary string
33
40
}
34
41
35
42
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"`
39
46
}
40
47
)
41
48
42
49
func New (smtpAddress string ) * Email {
43
50
return & Email {
44
51
smtpAddress : smtpAddress ,
52
+ Header : map [string ]string {},
45
53
}
46
54
}
47
55
@@ -62,20 +70,33 @@ func (m *Message) writeFile(f *File, disposition string) {
62
70
m .buffer .WriteString (f .Content + "\r \n " )
63
71
}
64
72
65
- func (e * Email ) Send (m * Message ) error {
73
+ func (e * Email ) Send (m * Message ) (err error ) {
74
+ // Message header
66
75
m .buffer = new (bytes.Buffer )
67
76
m .boundary = random .String (16 )
68
77
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
+ }
71
92
m .buffer .WriteString (fmt .Sprintf ("Content-Type: multipart/mixed; boundary=%s\r \n " , m .boundary ))
72
93
m .buffer .WriteString ("\r \n " )
73
94
74
95
// Message body
75
96
if m .TemplateName != "" {
76
97
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
79
100
}
80
101
m .writeText (buf .String (), "text/html" )
81
102
} else if m .Text != "" {
@@ -96,39 +117,51 @@ func (e *Email) Send(m *Message) error {
96
117
m .buffer .WriteString ("\r \n " )
97
118
m .buffer .WriteString ("--" + m .boundary + "--" )
98
119
99
- // Send message
120
+ // Dial
100
121
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 {
104
132
return err
105
133
}
106
134
}
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
+ }
109
141
}
110
- defer c .Close ()
142
+
143
+ // Send message
111
144
from , err := mail .ParseAddress (m .From )
112
145
if err != nil {
113
- return err
146
+ return
114
147
}
115
148
if err = c .Mail (from .Address ); err != nil {
116
- return err
149
+ return
117
150
}
118
151
to , err := mail .ParseAddressList (m .To )
119
152
if err != nil {
120
- return err
153
+ return
121
154
}
122
155
for _ , a := range to {
123
156
if err = c .Rcpt (a .Address ); err != nil {
124
- return err
157
+ return
125
158
}
126
159
}
127
160
wc , err := c .Data ()
128
161
if err != nil {
129
- return err
162
+ return
130
163
}
131
164
defer wc .Close ()
132
165
_ , err = m .buffer .WriteTo (wc )
133
- return err
166
+ return
134
167
}
0 commit comments