Skip to content

Commit 37fe507

Browse files
committed
Use gomail library for sending emails
agarwal-nitesh@3b88177
1 parent 2137d8e commit 37fe507

File tree

4 files changed

+64
-87
lines changed

4 files changed

+64
-87
lines changed

server/email/email.go

Lines changed: 15 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
package email
22

33
import (
4-
"bytes"
5-
"fmt"
4+
"crypto/tls"
65
"log"
7-
"mime/quotedprintable"
8-
"net/smtp"
9-
"strings"
6+
"strconv"
107

118
"github.com/authorizerdev/authorizer/server/constants"
9+
gomail "gopkg.in/mail.v2"
1210
)
1311

14-
/**
15-
Using: https://github.com/tangingw/go_smtp/blob/master/send_mail.go
16-
For gmail add instruction to enable less security
17-
// https://myaccount.google.com/u/0/lesssecureapps
18-
// https://www.google.com/settings/security/lesssecureapps
19-
// https://stackoverflow.com/questions/19877246/nodemailer-with-gmail-and-nodejs
20-
**/
21-
22-
// TODO -> try using gomail.v2
23-
2412
type Sender struct {
2513
User string
2614
Password string
@@ -30,60 +18,20 @@ func NewSender() Sender {
3018
return Sender{User: constants.SMTP_USERNAME, Password: constants.SMTP_PASSWORD}
3119
}
3220

33-
func (sender Sender) SendMail(Dest []string, Subject, bodyMessage string) error {
34-
msg := "From: " + constants.SENDER_EMAIL + "\n" +
35-
"To: " + strings.Join(Dest, ",") + "\n" +
36-
"Subject: " + Subject + "\n" + bodyMessage
37-
38-
err := smtp.SendMail(constants.SMTP_HOST+":"+constants.SMTP_PORT,
39-
smtp.PlainAuth("", sender.User, sender.Password, constants.SMTP_HOST),
40-
constants.SENDER_EMAIL, Dest, []byte(msg))
41-
if err != nil {
21+
func (sender Sender) SendMail(to []string, Subject, bodyMessage string) error {
22+
m := gomail.NewMessage()
23+
m.SetHeader("From", constants.SENDER_EMAIL)
24+
m.SetHeader("To", to...)
25+
m.SetHeader("Subject", Subject)
26+
m.SetBody("text/html", bodyMessage)
27+
port, _ := strconv.Atoi(constants.SMTP_PORT)
28+
d := gomail.NewDialer(constants.SMTP_HOST, port, constants.SMTP_USERNAME, constants.SMTP_PASSWORD)
29+
if constants.ENV == "development" {
30+
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
31+
}
32+
if err := d.DialAndSend(m); err != nil {
4233
log.Printf("smtp error: %s", err)
4334
return err
4435
}
45-
4636
return nil
4737
}
48-
49-
func (sender Sender) WriteEmail(dest []string, contentType, subject, bodyMessage string) string {
50-
header := make(map[string]string)
51-
header["From"] = sender.User
52-
53-
receipient := ""
54-
55-
for _, user := range dest {
56-
receipient = receipient + user
57-
}
58-
59-
header["To"] = receipient
60-
header["Subject"] = subject
61-
header["MIME-Version"] = "1.0"
62-
header["Content-Type"] = fmt.Sprintf("%s; charset=\"utf-8\"", contentType)
63-
header["Content-Transfer-Encoding"] = "quoted-printable"
64-
header["Content-Disposition"] = "inline"
65-
66-
message := ""
67-
68-
for key, value := range header {
69-
message += fmt.Sprintf("%s: %s\r\n", key, value)
70-
}
71-
72-
var encodedMessage bytes.Buffer
73-
74-
finalMessage := quotedprintable.NewWriter(&encodedMessage)
75-
finalMessage.Write([]byte(bodyMessage))
76-
finalMessage.Close()
77-
78-
message += "\r\n" + encodedMessage.String()
79-
80-
return message
81-
}
82-
83-
func (sender *Sender) WriteHTMLEmail(dest []string, subject, bodyMessage string) string {
84-
return sender.WriteEmail(dest, "text/html", subject, bodyMessage)
85-
}
86-
87-
func (sender *Sender) WritePlainEmail(dest []string, subject, bodyMessage string) string {
88-
return sender.WriteEmail(dest, "text/plain", subject, bodyMessage)
89-
}

server/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ require (
2929
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
3030
google.golang.org/appengine v1.6.7 // indirect
3131
google.golang.org/protobuf v1.27.1 // indirect
32+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
33+
gopkg.in/mail.v2 v2.3.1 // indirect
3234
gopkg.in/yaml.v2 v2.4.0 // indirect
3335
gorm.io/driver/mysql v1.2.1
3436
gorm.io/driver/postgres v1.2.3

server/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,13 +672,17 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
672672
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
673673
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
674674
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
675+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
676+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
675677
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
676678
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
677679
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
678680
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
679681
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
680682
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
681683
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
684+
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
685+
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
682686
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
683687
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
684688
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=

server/utils/email.go

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package utils
22

33
import (
4-
"fmt"
4+
"bytes"
5+
"encoding/json"
6+
"html/template"
57

68
"github.com/authorizerdev/authorizer/server/constants"
79
"github.com/authorizerdev/authorizer/server/email"
@@ -15,10 +17,9 @@ func SendVerificationMail(toEmail, token string) error {
1517
Receiver := []string{toEmail}
1618

1719
Subject := "Please verify your email"
18-
message := fmt.Sprintf(`
20+
message := `
1921
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2022
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
21-
2223
<head>
2324
<meta charset="UTF-8">
2425
<meta content="width=device-width, initial-scale=1" name="viewport">
@@ -41,7 +42,6 @@ func SendVerificationMail(toEmail, token string) error {
4142
</xml>
4243
<![endif]-->
4344
</head>
44-
4545
<body style="font-family: sans-serif;">
4646
<div class="es-wrapper-color">
4747
<!--[if gte mso 9]>
@@ -68,14 +68,15 @@ func SendVerificationMail(toEmail, token string) error {
6868
<table width="100%%" cellspacing="0" cellpadding="0">
6969
<tbody>
7070
<tr>
71-
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank"><img src="%s" alt="icon" style="display: block;" title="icon" width="30"></a></td>
71+
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.OrgLogo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
7272
</tr>
7373
7474
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
7575
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
7676
<p>Hey there 👋</p>
77-
<p>We received a request to sign-up / login for <b>%s</b>. If this is correct, please confirm your email address by clicking the button below.</p> <br/>
78-
<a href="%s" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Confirm Email</a>
77+
<p>We received a request to sign-up / login for <b>{{.OrgName}}</b>. If this is correct, please confirm your email address by clicking the button below.</p> <br/>
78+
<a
79+
clicktracking="off" href="{{.AuthUrl}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Confirm Email</a>
7980
</td>
8081
</tr>
8182
</tbody>
@@ -100,10 +101,15 @@ func SendVerificationMail(toEmail, token string) error {
100101
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
101102
</body>
102103
</html>
103-
`, constants.ORGANIZATION_LOGO, constants.ORGANIZATION_NAME, constants.AUTHORIZER_URL+"/verify_email"+"?token="+token)
104-
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
105-
106-
return sender.SendMail(Receiver, Subject, bodyMessage)
104+
`
105+
data := make(map[string]interface{}, 3)
106+
data["OrgLogo"] = constants.ORGANIZATION_LOGO
107+
data["OrgName"] = constants.ORGANIZATION_NAME
108+
data["AuthUrl"] = constants.AUTHORIZER_URL + "/verify_email?token=" + token
109+
message = AddEmailTemplate(message, data, "verify_email.tmpl")
110+
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
111+
112+
return sender.SendMail(Receiver, Subject, message)
107113
}
108114

109115
// SendForgotPasswordMail to send verification email
@@ -119,10 +125,9 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
119125

120126
Subject := "Reset Password"
121127

122-
message := fmt.Sprintf(`
128+
message := `
123129
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
124130
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
125-
126131
<head>
127132
<meta charset="UTF-8">
128133
<meta content="width=device-width, initial-scale=1" name="viewport">
@@ -145,7 +150,6 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
145150
</xml>
146151
<![endif]-->
147152
</head>
148-
149153
<body style="font-family: sans-serif;">
150154
<div class="es-wrapper-color">
151155
<!--[if gte mso 9]>
@@ -172,14 +176,14 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
172176
<table width="100%%" cellspacing="0" cellpadding="0">
173177
<tbody>
174178
<tr>
175-
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank"><img src="%s" alt="icon" style="display: block;" title="icon" width="30"></a></td>
179+
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.OrgLogo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
176180
</tr>
177181
178182
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
179183
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
180184
<p>Hey there 👋</p>
181-
<p>We received a request to reset password for email: <b>%s</b>. If this is correct, please reset the password clicking the button below.</p> <br/>
182-
<a href="%s" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Reset Password</a>
185+
<p>We received a request to reset password for email: <b>{{.ToEmail}}</b>. If this is correct, please reset the password clicking the button below.</p> <br/>
186+
<a clicktracking="off" href="{{.AuthUrl}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Reset Password</a>
183187
</td>
184188
</tr>
185189
</tbody>
@@ -204,9 +208,28 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
204208
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
205209
</body>
206210
</html>
207-
`, constants.ORGANIZATION_LOGO, toEmail, constants.RESET_PASSWORD_URL+"?token="+token)
211+
`
208212

209-
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
213+
data := make(map[string]interface{}, 3)
214+
data["OrgLogo"] = constants.ORGANIZATION_LOGO
215+
data["ToEmail"] = constants.ORGANIZATION_NAME
216+
data["AuthUrl"] = constants.RESET_PASSWORD_URL + "?token=" + token
217+
message = AddEmailTemplate(message, data, "reset_password_email.tmpl")
210218

211-
return sender.SendMail(Receiver, Subject, bodyMessage)
219+
return sender.SendMail(Receiver, Subject, message)
220+
}
221+
222+
func AddEmailTemplate(a string, b map[string]interface{}, templateName string) string {
223+
tmpl, err := template.New(templateName).Parse(a)
224+
if err != nil {
225+
output, _ := json.Marshal(b)
226+
return string(output)
227+
}
228+
buf := &bytes.Buffer{}
229+
err = tmpl.Execute(buf, b)
230+
if err != nil {
231+
panic(err)
232+
}
233+
s := buf.String()
234+
return s
212235
}

0 commit comments

Comments
 (0)