7
7
"fmt"
8
8
"github.com/domodwyer/mailyak/v3"
9
9
"github.com/joho/godotenv"
10
+ log "github.com/sirupsen/logrus"
10
11
"gopkg.in/square/go-jose.v2/jwt"
11
- "log"
12
12
"net/http"
13
13
"net/smtp"
14
14
"os"
@@ -24,6 +24,17 @@ curl -k -X POST -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: applicatio
24
24
25
25
*/
26
26
27
+ const (
28
+ emailParallel = 1
29
+ )
30
+
31
+ var (
32
+ opts * Opts
33
+ jwtKey []byte
34
+ debug = false
35
+ queue chan * EmailRequest
36
+ )
37
+
27
38
type TokenClaims struct {
28
39
MailFrom string `json:"mail_from,omitempty"`
29
40
MailTo string `json:"mail_to,omitempty"`
@@ -39,74 +50,47 @@ type Opts struct {
39
50
SmtpPort int
40
51
}
41
52
42
- var (
43
- opts * Opts
44
- jwtKey []byte
45
- debug = false
46
- )
47
-
48
53
type EmailRequest struct {
49
54
MailTo string `json:"mail_to,omitempty"`
50
55
Subject string `json:"subject"`
51
56
TextMessage string `json:"text_message"`
52
57
HtmlMessage string `json:"html_message"`
58
+ claims * TokenClaims
53
59
}
54
60
55
61
func mailer (w http.ResponseWriter , r * http.Request , claims * TokenClaims ) {
56
62
if r .Method != "POST" {
57
- writeErr (w , http .StatusBadRequest , "ERR-07 , only POST supported: %v" , r .Method )
63
+ writeErr (w , http .StatusBadRequest , "mailer , only POST supported: %v" , r .Method )
58
64
return
59
65
}
60
66
61
67
var email EmailRequest
62
68
err := json .NewDecoder (r .Body ).Decode (& email )
63
69
if err != nil {
64
- writeErr (w , http .StatusBadRequest , "ERR-08, could not decode request: %v" , err )
65
- return
66
- }
67
-
68
- mail := mailyak .New (opts .SmtpHost + ":" + strconv .Itoa (opts .SmtpPort ), smtp .PlainAuth ("" , claims .MailFrom , opts .SmtpPassword , opts .SmtpHost ))
69
- var to string
70
- if claims .MailTo != "" {
71
- to = claims .MailTo
72
- } else {
73
- to = email .MailTo
74
- }
75
- mail .To (to )
76
- mail .From (claims .MailFrom )
77
- mail .Subject (email .Subject )
78
- if email .TextMessage != "" {
79
- mail .Plain ().Set (email .TextMessage )
80
- }
81
- if email .HtmlMessage != "" {
82
- mail .HTML ().Set (email .HtmlMessage )
83
- }
84
-
85
- err = mail .Send ()
86
- if err != nil {
87
- writeErr (w , http .StatusBadRequest , "ERR-09, could not send email: %v" , err )
70
+ writeErr (w , http .StatusBadRequest , "mailer, could not decode request: %v" , err )
88
71
return
89
72
}
90
- log .Printf ("Email sent from [%s] to [%v], subject: [%v]\n " , claims .MailFrom , to , email .Subject )
73
+ email .claims = claims
74
+ queue <- & email
91
75
}
92
76
93
77
func jwtAuth (next func (w http.ResponseWriter , r * http.Request , claims * TokenClaims )) func (http.ResponseWriter , * http.Request ) {
94
78
return func (w http.ResponseWriter , r * http.Request ) {
95
79
authHeader := r .Header .Get ("Authorization" )
96
80
if authHeader == "" {
97
- writeErr (w , http .StatusBadRequest , "ERR-01 , authorization header not set" )
81
+ writeErr (w , http .StatusBadRequest , "jwtAuth , authorization header not set" )
98
82
return
99
83
}
100
84
101
85
bearerToken := strings .Split (authHeader , " " )
102
86
if len (bearerToken ) != 2 {
103
- writeErr (w , http .StatusBadRequest , "ERR-02 , could not split token: %v" , bearerToken )
87
+ writeErr (w , http .StatusBadRequest , "jwtAuth , could not split token: %v" , bearerToken )
104
88
return
105
89
}
106
90
107
91
tok , err := jwt .ParseSigned (bearerToken [1 ])
108
92
if err != nil {
109
- writeErr (w , http .StatusBadRequest , "ERR-03 , could not parse token: %v" , bearerToken [1 ])
93
+ writeErr (w , http .StatusBadRequest , "jwtAuth , could not parse token: %v" , bearerToken [1 ])
110
94
return
111
95
}
112
96
@@ -115,17 +99,17 @@ func jwtAuth(next func(w http.ResponseWriter, r *http.Request, claims *TokenClai
115
99
if tok .Headers [0 ].Algorithm == "HS256" {
116
100
err = tok .Claims (jwtKey , claims )
117
101
} else {
118
- writeErr (w , http .StatusUnauthorized , "ERR-04 , unknown algorithm: %v" , tok .Headers [0 ].Algorithm )
102
+ writeErr (w , http .StatusUnauthorized , "jwtAuth , unknown algorithm: %v" , tok .Headers [0 ].Algorithm )
119
103
return
120
104
}
121
105
122
106
if err != nil {
123
- writeErr (w , http .StatusUnauthorized , "ERR-05 , could not parse claims: %v" , bearerToken [1 ])
107
+ writeErr (w , http .StatusUnauthorized , "jwtAuth , could not parse claims: %v" , bearerToken [1 ])
124
108
return
125
109
}
126
110
127
111
if claims .Expiry != nil && ! claims .Expiry .Time ().After (time .Now ()) {
128
- writeErr (w , http .StatusBadRequest , "ERR-06 , expired: %v" , claims .Expiry .Time ())
112
+ writeErr (w , http .StatusBadRequest , "jwtAuth , expired: %v" , claims .Expiry .Time ())
129
113
return
130
114
}
131
115
@@ -135,7 +119,7 @@ func jwtAuth(next func(w http.ResponseWriter, r *http.Request, claims *TokenClai
135
119
136
120
func writeErr (w http.ResponseWriter , code int , format string , a ... interface {}) {
137
121
msg := fmt .Sprintf (format , a ... )
138
- log .Printf (msg )
122
+ log .Warnf (msg )
139
123
w .Header ().Set ("Content-Type" , "application/json;charset=UTF-8" )
140
124
w .Header ().Set ("Cache-Control" , "no-store" )
141
125
w .Header ().Set ("Pragma" , "no-cache" )
@@ -213,5 +197,45 @@ func main() {
213
197
214
198
http .HandleFunc ("/" , jwtAuth (mailer ))
215
199
log .Printf ("listening on port %v..." , opts .Port )
200
+
201
+ //create a queue, and send one after the other
202
+ queue = make (chan * EmailRequest )
203
+ for i := 0 ; i < emailParallel ; i ++ {
204
+ go func () {
205
+ for {
206
+ select {
207
+ case e := <- queue :
208
+ send (e )
209
+ }
210
+ }
211
+ }()
212
+ }
213
+
216
214
http .ListenAndServe (":" + strconv .Itoa (opts .Port ), nil )
217
215
}
216
+
217
+ func send (e * EmailRequest ) {
218
+ mail := mailyak .New (opts .SmtpHost + ":" + strconv .Itoa (opts .SmtpPort ), smtp .PlainAuth ("" , e .claims .MailFrom , opts .SmtpPassword , opts .SmtpHost ))
219
+ var to string
220
+ if e .claims .MailTo != "" {
221
+ to = e .claims .MailTo
222
+ } else {
223
+ to = e .MailTo
224
+ }
225
+ mail .To (to )
226
+ mail .From (e .claims .MailFrom )
227
+ mail .Subject (e .Subject )
228
+ if e .TextMessage != "" {
229
+ mail .Plain ().Set (e .TextMessage )
230
+ }
231
+ if e .HtmlMessage != "" {
232
+ mail .HTML ().Set (e .HtmlMessage )
233
+ }
234
+
235
+ err := mail .Send ()
236
+ if err != nil {
237
+ log .Warnf ("could not send email: %v" , err )
238
+ } else {
239
+ log .Infof ("Email sent from [%s] to [%v], subject: [%v]\n " , e .claims .MailFrom , to , e .Subject )
240
+ }
241
+ }
0 commit comments