parent
2137d8ef5d
commit
37fe5071c5
|
@ -1,26 +1,14 @@
|
||||||
package email
|
package email
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"crypto/tls"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"mime/quotedprintable"
|
"strconv"
|
||||||
"net/smtp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
gomail "gopkg.in/mail.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
Using: https://github.com/tangingw/go_smtp/blob/master/send_mail.go
|
|
||||||
For gmail add instruction to enable less security
|
|
||||||
// https://myaccount.google.com/u/0/lesssecureapps
|
|
||||||
// https://www.google.com/settings/security/lesssecureapps
|
|
||||||
// https://stackoverflow.com/questions/19877246/nodemailer-with-gmail-and-nodejs
|
|
||||||
**/
|
|
||||||
|
|
||||||
// TODO -> try using gomail.v2
|
|
||||||
|
|
||||||
type Sender struct {
|
type Sender struct {
|
||||||
User string
|
User string
|
||||||
Password string
|
Password string
|
||||||
|
@ -30,60 +18,20 @@ func NewSender() Sender {
|
||||||
return Sender{User: constants.SMTP_USERNAME, Password: constants.SMTP_PASSWORD}
|
return Sender{User: constants.SMTP_USERNAME, Password: constants.SMTP_PASSWORD}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sender Sender) SendMail(Dest []string, Subject, bodyMessage string) error {
|
func (sender Sender) SendMail(to []string, Subject, bodyMessage string) error {
|
||||||
msg := "From: " + constants.SENDER_EMAIL + "\n" +
|
m := gomail.NewMessage()
|
||||||
"To: " + strings.Join(Dest, ",") + "\n" +
|
m.SetHeader("From", constants.SENDER_EMAIL)
|
||||||
"Subject: " + Subject + "\n" + bodyMessage
|
m.SetHeader("To", to...)
|
||||||
|
m.SetHeader("Subject", Subject)
|
||||||
err := smtp.SendMail(constants.SMTP_HOST+":"+constants.SMTP_PORT,
|
m.SetBody("text/html", bodyMessage)
|
||||||
smtp.PlainAuth("", sender.User, sender.Password, constants.SMTP_HOST),
|
port, _ := strconv.Atoi(constants.SMTP_PORT)
|
||||||
constants.SENDER_EMAIL, Dest, []byte(msg))
|
d := gomail.NewDialer(constants.SMTP_HOST, port, constants.SMTP_USERNAME, constants.SMTP_PASSWORD)
|
||||||
if err != nil {
|
if constants.ENV == "development" {
|
||||||
|
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
}
|
||||||
|
if err := d.DialAndSend(m); err != nil {
|
||||||
log.Printf("smtp error: %s", err)
|
log.Printf("smtp error: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sender Sender) WriteEmail(dest []string, contentType, subject, bodyMessage string) string {
|
|
||||||
header := make(map[string]string)
|
|
||||||
header["From"] = sender.User
|
|
||||||
|
|
||||||
receipient := ""
|
|
||||||
|
|
||||||
for _, user := range dest {
|
|
||||||
receipient = receipient + user
|
|
||||||
}
|
|
||||||
|
|
||||||
header["To"] = receipient
|
|
||||||
header["Subject"] = subject
|
|
||||||
header["MIME-Version"] = "1.0"
|
|
||||||
header["Content-Type"] = fmt.Sprintf("%s; charset=\"utf-8\"", contentType)
|
|
||||||
header["Content-Transfer-Encoding"] = "quoted-printable"
|
|
||||||
header["Content-Disposition"] = "inline"
|
|
||||||
|
|
||||||
message := ""
|
|
||||||
|
|
||||||
for key, value := range header {
|
|
||||||
message += fmt.Sprintf("%s: %s\r\n", key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var encodedMessage bytes.Buffer
|
|
||||||
|
|
||||||
finalMessage := quotedprintable.NewWriter(&encodedMessage)
|
|
||||||
finalMessage.Write([]byte(bodyMessage))
|
|
||||||
finalMessage.Close()
|
|
||||||
|
|
||||||
message += "\r\n" + encodedMessage.String()
|
|
||||||
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sender *Sender) WriteHTMLEmail(dest []string, subject, bodyMessage string) string {
|
|
||||||
return sender.WriteEmail(dest, "text/html", subject, bodyMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sender *Sender) WritePlainEmail(dest []string, subject, bodyMessage string) string {
|
|
||||||
return sender.WriteEmail(dest, "text/plain", subject, bodyMessage)
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ require (
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
|
gopkg.in/mail.v2 v2.3.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gorm.io/driver/mysql v1.2.1
|
gorm.io/driver/mysql v1.2.1
|
||||||
gorm.io/driver/postgres v1.2.3
|
gorm.io/driver/postgres v1.2.3
|
||||||
|
|
|
@ -672,6 +672,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
@ -679,6 +681,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
|
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||||
|
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||||
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"html/template"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
"github.com/authorizerdev/authorizer/server/email"
|
||||||
|
@ -15,10 +17,9 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
Receiver := []string{toEmail}
|
Receiver := []string{toEmail}
|
||||||
|
|
||||||
Subject := "Please verify your email"
|
Subject := "Please verify your email"
|
||||||
message := fmt.Sprintf(`
|
message := `
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||||
|
@ -41,7 +42,6 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
</xml>
|
</xml>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="font-family: sans-serif;">
|
<body style="font-family: sans-serif;">
|
||||||
<div class="es-wrapper-color">
|
<div class="es-wrapper-color">
|
||||||
<!--[if gte mso 9]>
|
<!--[if gte mso 9]>
|
||||||
|
@ -68,14 +68,15 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<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>
|
<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>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||||
<p>Hey there 👋</p>
|
<p>Hey there 👋</p>
|
||||||
<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/>
|
<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/>
|
||||||
<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>
|
<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;">Confirm Email</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -100,10 +101,15 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, constants.ORGANIZATION_LOGO, constants.ORGANIZATION_NAME, constants.AUTHORIZER_URL+"/verify_email"+"?token="+token)
|
`
|
||||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["OrgLogo"] = constants.ORGANIZATION_LOGO
|
||||||
|
data["OrgName"] = constants.ORGANIZATION_NAME
|
||||||
|
data["AuthUrl"] = constants.AUTHORIZER_URL + "/verify_email?token=" + token
|
||||||
|
message = AddEmailTemplate(message, data, "verify_email.tmpl")
|
||||||
|
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
|
||||||
return sender.SendMail(Receiver, Subject, bodyMessage)
|
return sender.SendMail(Receiver, Subject, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendForgotPasswordMail to send verification email
|
// SendForgotPasswordMail to send verification email
|
||||||
|
@ -119,10 +125,9 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
|
|
||||||
Subject := "Reset Password"
|
Subject := "Reset Password"
|
||||||
|
|
||||||
message := fmt.Sprintf(`
|
message := `
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||||
|
@ -145,7 +150,6 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
</xml>
|
</xml>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="font-family: sans-serif;">
|
<body style="font-family: sans-serif;">
|
||||||
<div class="es-wrapper-color">
|
<div class="es-wrapper-color">
|
||||||
<!--[if gte mso 9]>
|
<!--[if gte mso 9]>
|
||||||
|
@ -172,14 +176,14 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<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>
|
<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>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||||
<p>Hey there 👋</p>
|
<p>Hey there 👋</p>
|
||||||
<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/>
|
<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/>
|
||||||
<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>
|
<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>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -204,9 +208,28 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, constants.ORGANIZATION_LOGO, toEmail, constants.RESET_PASSWORD_URL+"?token="+token)
|
`
|
||||||
|
|
||||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["OrgLogo"] = constants.ORGANIZATION_LOGO
|
||||||
|
data["ToEmail"] = constants.ORGANIZATION_NAME
|
||||||
|
data["AuthUrl"] = constants.RESET_PASSWORD_URL + "?token=" + token
|
||||||
|
message = AddEmailTemplate(message, data, "reset_password_email.tmpl")
|
||||||
|
|
||||||
return sender.SendMail(Receiver, Subject, bodyMessage)
|
return sender.SendMail(Receiver, Subject, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddEmailTemplate(a string, b map[string]interface{}, templateName string) string {
|
||||||
|
tmpl, err := template.New(templateName).Parse(a)
|
||||||
|
if err != nil {
|
||||||
|
output, _ := json.Marshal(b)
|
||||||
|
return string(output)
|
||||||
|
}
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err = tmpl.Execute(buf, b)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
s := buf.String()
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user