Commit edd7c4f4d70a4a883d03a5e53fe677c8d98e1660
1 parent
c99e4944e5
Exists in
master
new email interface
Showing
1 changed file
with
31 additions
and
11 deletions
Show diff stats
email.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | // TODO(markO): test test test test test (and open source?) | 3 | // TODO(markO): test test test test test (and open source?) |
4 | 4 | ||
5 | import ( | 5 | import ( |
6 | "crypto/tls" | 6 | "crypto/tls" |
7 | "errors" | 7 | "errors" |
8 | "fmt" | 8 | "fmt" |
9 | "net/smtp" | 9 | "net/smtp" |
10 | "strings" | 10 | "strings" |
11 | ) | 11 | ) |
12 | 12 | ||
13 | type Email struct { | 13 | type Email struct { |
14 | To []string | 14 | To []string |
15 | From string | 15 | From string |
16 | Subject string | 16 | Subject string |
17 | Body string | 17 | Body string |
18 | |||
19 | config *EmailConfig | ||
18 | } | 20 | } |
19 | 21 | ||
20 | func NewEmail(to []string, from, subject, body string) *Email { | 22 | func NewEmail() *Email { |
21 | return &Email{ | 23 | return &Email{ |
22 | To: to, | 24 | To: nil, |
23 | From: from, | 25 | From: "", |
24 | Subject: subject, | 26 | Subject: "", |
25 | Body: body, | 27 | Body: "", |
28 | config: nil, | ||
26 | } | 29 | } |
27 | } | 30 | } |
28 | 31 | ||
32 | func (e *Email) Config(cfg *EmailConfig) { | ||
33 | e.config = cfg | ||
34 | } | ||
35 | |||
36 | func (e *Email) SetFrom(from string) { | ||
37 | e.From = from | ||
38 | } | ||
39 | |||
40 | func (e *Email) SetTo(to []string) { | ||
41 | e.To = to | ||
42 | } | ||
43 | |||
44 | func (e *Email) SetSubject(sub string) { | ||
45 | e.Subject = sub | ||
46 | } | ||
47 | |||
48 | func (e *Email) SetBody(body string) { | ||
49 | e.Body = body | ||
50 | } | ||
51 | |||
29 | func (e *Email) String() string { | 52 | func (e *Email) String() string { |
30 | var str strings.Builder | 53 | var str strings.Builder |
31 | 54 | ||
32 | str.WriteString("From:" + e.From + "\r\n") | 55 | str.WriteString("From:" + e.From + "\r\n") |
33 | 56 | ||
34 | str.WriteString("To:") | 57 | str.WriteString("To:") |
35 | for i, _ := range e.To { | 58 | for i, _ := range e.To { |
36 | if i > 0 { | 59 | if i > 0 { |
37 | str.WriteString(",") | 60 | str.WriteString(",") |
38 | } | 61 | } |
39 | str.WriteString(e.To[i]) | 62 | str.WriteString(e.To[i]) |
40 | } | 63 | } |
41 | str.WriteString("\r\n") | 64 | str.WriteString("\r\n") |
42 | 65 | ||
43 | str.WriteString("Subject:" + e.Subject + "\r\n") | 66 | str.WriteString("Subject:" + e.Subject + "\r\n") |
44 | 67 | ||
45 | // body | 68 | // body |
46 | str.WriteString("\r\n" + e.Body + "\r\n") | 69 | str.WriteString("\r\n" + e.Body + "\r\n") |
47 | 70 | ||
48 | return str.String() | 71 | return str.String() |
49 | } | 72 | } |
50 | 73 | ||
51 | func (e *Email) Bytes() []byte { | 74 | func (e *Email) Bytes() []byte { |
52 | return []byte(e.String()) | 75 | return []byte(e.String()) |
53 | } | 76 | } |
54 | 77 | ||
55 | func SendEmail(email *Email, conf *EmailConfig) error { | 78 | func (email *Email) Send() error { |
56 | if email == nil { | 79 | if email.config == nil { |
57 | return errors.New("no email to send") | ||
58 | } | ||
59 | |||
60 | if conf == nil { | ||
61 | return errors.New("email configuration not provided") | 80 | return errors.New("email configuration not provided") |
62 | } | 81 | } |
82 | conf := email.config | ||
63 | 83 | ||
64 | c, err := smtp.Dial(conf.ServerName) | 84 | c, err := smtp.Dial(conf.ServerName) |
65 | if err != nil { | 85 | if err != nil { |
66 | return err | 86 | return err |
67 | } | 87 | } |
68 | defer c.Close() | 88 | defer c.Close() |
69 | 89 | ||
70 | // not sure if this is needed | 90 | // not sure if this is needed |
71 | //if err = c.Hello(conf.ServerName); err != nil { | 91 | //if err = c.Hello(conf.ServerName); err != nil { |
72 | // return err | 92 | // return err |
73 | //} | 93 | //} |
74 | 94 | ||
75 | if ok, _ := c.Extension("STARTTLS"); ok { | 95 | if ok, _ := c.Extension("STARTTLS"); ok { |
76 | // disable stupid tls check for self-signed certificates | 96 | // disable stupid tls check for self-signed certificates |
77 | config := &tls.Config{ | 97 | config := &tls.Config{ |
78 | ServerName: conf.ServerName, | 98 | ServerName: conf.ServerName, |
79 | InsecureSkipVerify: true, | 99 | InsecureSkipVerify: true, |
80 | } | 100 | } |
81 | // for golang testing | 101 | // for golang testing |
82 | //if testHookStartTLS != nil { | 102 | //if testHookStartTLS != nil { |
83 | // testHookStartTLS(config) | 103 | // testHookStartTLS(config) |
84 | //} | 104 | //} |
85 | if err = c.StartTLS(config); err != nil { | 105 | if err = c.StartTLS(config); err != nil { |
86 | return err | 106 | return err |
87 | } | 107 | } |
88 | } | 108 | } |
89 | 109 | ||
90 | /* | 110 | /* |
91 | // don't know what to do with this | 111 | // don't know what to do with this |
92 | if a != nil && c.ext != nil { | 112 | if a != nil && c.ext != nil { |
93 | if _, ok := c.ext["AUTH"]; !ok { | 113 | if _, ok := c.ext["AUTH"]; !ok { |
94 | return errors.New("smtp: server doesn't support AUTH") | 114 | return errors.New("smtp: server doesn't support AUTH") |
95 | } | 115 | } |
96 | if err = c.Auth(a); err != nil { | 116 | if err = c.Auth(a); err != nil { |
97 | return err | 117 | return err |
98 | } | 118 | } |
99 | } | 119 | } |
100 | */ | 120 | */ |
101 | 121 | ||
102 | // Set up authentication information. | 122 | // Set up authentication information. |
103 | auth := smtp.PlainAuth(conf.Identity, conf.Username, conf.Password, conf.Host) | 123 | auth := smtp.PlainAuth(conf.Identity, conf.Username, conf.Password, conf.Host) |
104 | if err = c.Auth(auth); err != nil { | 124 | if err = c.Auth(auth); err != nil { |
105 | return err | 125 | return err |
106 | } | 126 | } |
107 | 127 | ||
108 | if err = c.Mail(email.From); err != nil { | 128 | if err = c.Mail(email.From); err != nil { |
109 | return err | 129 | return err |
110 | } | 130 | } |
111 | 131 | ||
112 | for _, addr := range email.To { | 132 | for _, addr := range email.To { |
113 | if err = c.Rcpt(addr); err != nil { | 133 | if err = c.Rcpt(addr); err != nil { |
114 | return err | 134 | return err |
115 | } | 135 | } |
116 | } | 136 | } |
117 | 137 | ||
118 | w, err := c.Data() | 138 | w, err := c.Data() |
119 | if err != nil { | 139 | if err != nil { |
120 | return err | 140 | return err |
121 | } | 141 | } |
122 | 142 | ||
123 | _, err = w.Write(email.Bytes()) | 143 | _, err = w.Write(email.Bytes()) |
124 | if err != nil { | 144 | if err != nil { |
125 | return err | 145 | return err |
126 | } | 146 | } |
127 | 147 | ||
128 | err = w.Close() | 148 | err = w.Close() |
129 | if err != nil { | 149 | if err != nil { |
130 | return err | 150 | return err |
131 | } | 151 | } |
132 | 152 | ||
133 | return c.Quit() | 153 | return c.Quit() |
134 | } | 154 | } |
135 | 155 | ||
136 | type EmailConfig struct { | 156 | type EmailConfig struct { |
137 | ServerName string `json:"-"` | 157 | ServerName string `json:"-"` |
138 | Identity string `json:"-"` | 158 | Identity string `json:"-"` |
139 | Username string `json:"username"` | 159 | Username string `json:"username"` |
140 | Password string `json:"password"` | 160 | Password string `json:"password"` |
141 | Host string `json:"host"` | 161 | Host string `json:"host"` |
142 | Port int `json:"port"` | 162 | Port int `json:"port"` |
143 | } | 163 | } |
144 | 164 | ||
145 | func NewEmailConfig(ident, uname, pword, host string, port int) *EmailConfig { | 165 | func NewEmailConfig(ident, uname, pword, host string, port int) *EmailConfig { |
146 | return &EmailConfig{ | 166 | return &EmailConfig{ |
147 | ServerName: host + fmt.Sprintf(":%d", port), | 167 | ServerName: host + fmt.Sprintf(":%d", port), |
148 | Identity: ident, | 168 | Identity: ident, |
149 | Username: uname, | 169 | Username: uname, |
150 | Password: pword, | 170 | Password: pword, |
151 | Host: host, | 171 | Host: host, |