-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 03143df
Showing
20 changed files
with
549 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
JWT_ALGORITHM=<jwt algorithm encrypted> | ||
JWT_PUBLIC_KEY=<jwt public key not path> | ||
|
||
RABBITMQ_URL=<rabbitmq host with format "amqp://{username}:{password}@{host}:{port}/"> | ||
RABBITMQ_QUEUE_NAME=<rabbitmq queue name> | ||
|
||
SMTP_HOST={smtp host } | ||
SMTP_PORT={ smtp port } | ||
SMTP_USER={ smtp username } | ||
SMTP_PASS={ smtp password } | ||
SMTP_SENDER_EMAIL={ smtp sender email } | ||
SMTP_SENDER_NAME={ smttp sender name } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# ======> MAILER SERVICE <======== | ||
golang project provided to handle mailer service and has been integrated with `rabbitmq`, on channel `mailer_queue` and templateing with file `.html`, for provider sending email using smtp2go for the testing with template of `.env` is ready on this project, | ||
|
||
the project using `enqueue` concept that set in file `rabbitmq/rabbitmq.go` will be automatically send `message` after consumming message from channel set on file `.env` | ||
|
||
for example of list template email to send you can see in file `templates/*_template.html` for the lsit of template that will using message with variable `tag` on the message from channel for list of `tag` you can see at the file `handlers/handlers.go` and here this of list the `tag` | ||
|
||
1. login | ||
2. send_code | ||
3. reset_password | ||
4. api_key | ||
|
||
that must be the same name on file `templates/*_template.html`, and if you want to customize the project you can update the file list | ||
|
||
1. handlers -> file to handle tag of message from consuming message from queue | ||
2. interfaces -> file to handling interfaces message like all variable they have | ||
3. mailes -> file to handling send mail with configuration template from message | ||
4. rabbitmq -> file to handling configuration of queue and subcribe to channel has been declared on rabbitmq queue | ||
5. templates -> file to handling templating style to show for user | ||
6. token -> file to handling decrypted message jwt from queue channel | ||
|
||
flow of system on this project just like this : | ||
|
||
the flow of system is started from your project | ||
|
||
``` | ||
-> publish message json to rabbitmq channel when has been encrypted with jwt private key (example of json you see after this) | ||
-> mailer service subcribe to channel and consume the message | ||
-> message will decrypted first to check the tag | ||
-> system will generate template of message with using json message after decryption | ||
-> system will send message to target email | ||
``` | ||
|
||
project will using dual decrypted when `first decrypted` is for to get `tag` group that using `Record` interfaces and then project will decrypt again using file in `interfaces` to get list of json messages `when is suitable on tag and handlers` | ||
|
||
``` | ||
example of json data | ||
{ | ||
record: { | ||
email: string, // email address user | ||
tag: string, // tag is for description to generate file | ||
subject: string // subject of message to subject on email send | ||
}, | ||
iss: 'name_project', | ||
iat: <Time on Integer>, | ||
exp: <Time on Integer>, | ||
jti: SecureRandom.hex(10) | ||
} | ||
``` | ||
|
||
## ======> SETUP <======== | ||
Setup for this project is simple, you must prepare the configuration on file `.env`, configuration channel on the `rabbitmq`, the list of configuration you must following the step : | ||
|
||
1. RabbitMQ | ||
|
||
configuration rabbitmq you can follow this link `https://www.rabbitmq.com/download.html` | ||
|
||
or you want to easly install RabbitMQ configuration you can running command on your terminal using | ||
|
||
```bash | ||
$ cd config && docker-compose up -Vd | ||
``` | ||
after your config for rabbitmq installation don't forget to update sthe file `.env` on variable `RABBITMQ_HOST` with host to your `rabbitmq` has `installed` | ||
|
||
2. Channel configuration | ||
|
||
Channel configration you can using file in `config/rabbitmq_channel.yaml` on your project because this project just for consuming from config channel when you set in rabbitmq | ||
you can create channel in rabbitmq in `exchange` and `queue` and don't forget to set the `queue_name` when you has been config in file `.env` | ||
|
||
3. SMTP | ||
|
||
Mailer using `github.com/go-mail/mail` for the package and for the configuration you can set in file `.env` on list variable in below | ||
``` | ||
SMTP_HOST={smtp host } | ||
SMTP_PORT={ smtp port } | ||
SMTP_USER={ smtp username } | ||
SMTP_PASS={ smtp password } | ||
SMTP_SENDER_EMAIL={ smtp sender email } | ||
SMTP_SENDER_NAME={ smttp sender name } | ||
``` | ||
don't forget to change that `smtp configuration` with your smtp mailer you have, but on `sender email` must using `activated email` like `[email protected]` or something else, if you want to customize that configuration you can change in file `mailers/mailers.go` | ||
|
||
4. JWT | ||
|
||
configuration jwt is easy, you just need to `generate` the `jwt_public_key` and `jwt_private_key` and set the `algorithm` on file `.env`, you can follow the step : | ||
|
||
- Generate Private Key | ||
```bash | ||
$ openssl genpkey -algorithm RSA -out private_key.pem | ||
``` | ||
|
||
- Generate Public Key | ||
```bash | ||
$ openssl rsa -in private_key.pem -pubout -out public_key.pem | ||
``` | ||
|
||
but in this project you must to convert that file output to `base64` configuration `private_key` or `public_key` | ||
- Convert private key to base64 | ||
```bash | ||
$ openssl base64 -in private_key.pem | ||
``` | ||
- Convert Public key to base64 | ||
```bash | ||
$ openssl rsa -in private_key.pem -pubout -outform DER | openssl base64 -A | ||
``` | ||
|
||
after that you can set that `private_key` on your project to protect the message from your project for executing on this `mailer-service`, and for `mailer-service` you can must to using that `public_key` to decrypted the message from your `project` after consuming channel has you declared in file `.env` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
version: '3.6' | ||
rabbitmq: | ||
image: rabbitmq:3.7.6-management | ||
restart: always | ||
ports: | ||
- "5672:5672" | ||
- "15672:15672" | ||
volumes: | ||
- rabbitmq_data:/var/lib/rabbitmq | ||
logging: | ||
driver: "json-file" | ||
options: | ||
max-size: "50m" | ||
|
||
volumes: | ||
rabbitmq_data: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
exchanges: | ||
- name: mailer_exchange | ||
type: direct | ||
durable: false | ||
auto_delete: false | ||
queues: | ||
- name: mailer_queue | ||
durable: true | ||
auto_delete: false | ||
bindings: | ||
- exchange: mailer_exchange | ||
routing_key: mailer.send_email |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module mailer | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | ||
github.com/go-mail/mail v2.3.1+incompatible // indirect | ||
github.com/joho/godotenv v1.5.1 // indirect | ||
github.com/streadway/amqp v1.1.0 // indirect | ||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | ||
github.com/go-mail/mail v2.3.1+incompatible h1:UzNOn0k5lpfVtO31cK3hn6I4VEVGhe3lX8AJBAxXExM= | ||
github.com/go-mail/mail v2.3.1+incompatible/go.mod h1:VPWjmmNyRsWXQZHVHT3g0YbIINUkSmuKOiLIDkWbL6M= | ||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | ||
github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM= | ||
github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg= | ||
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package handlers | ||
|
||
import ( | ||
"log" | ||
|
||
"mailer/token" | ||
"mailer/interfaces" | ||
) | ||
|
||
func ClaimAllRecordData(msg string, tag string) (interface{}, error) { | ||
switch tag { | ||
case "login": | ||
var interfaceData interfaces.Login | ||
record := token.DecodeToken(msg, &interfaceData) | ||
if record != nil { | ||
log.Println(record) | ||
return nil, record | ||
} | ||
|
||
return interfaceData, nil | ||
case "send_code": | ||
var interfaceData interfaces.VerifToken | ||
record := token.DecodeToken(msg, &interfaceData) | ||
if record != nil { | ||
log.Println(record) | ||
return nil, record | ||
} | ||
|
||
return interfaceData, nil | ||
case "reset_password": | ||
var interfaceData interfaces.VerifToken | ||
record := token.DecodeToken(msg, &interfaceData) | ||
if record != nil { | ||
log.Println(record) | ||
return nil, record | ||
} | ||
|
||
return interfaceData, nil | ||
case "api_key": | ||
var interfaceData interfaces.APIKey | ||
record := token.DecodeToken(msg, &interfaceData) | ||
if record != nil { | ||
log.Println(record) | ||
return nil, record | ||
} | ||
|
||
return interfaceData, nil | ||
default: | ||
log.Println("Tag not recognized") | ||
|
||
var interfaceData interfaces.Record | ||
return interfaceData, nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package interfaces | ||
|
||
type APIKey struct { | ||
Label string `json:"label"` | ||
ApiKey string `json:"api_key"` | ||
ActivationToken int `json:"activation_token"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package interfaces | ||
|
||
type Login struct { | ||
Email string `json:"email"` | ||
Device string `json:"device,omitempty"` | ||
LoginTime string `json:"login_time,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package interfaces | ||
|
||
type Record struct { | ||
Subject string `json:"subject"` | ||
Tag string `json:"tag"` | ||
Email string `json:"email"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package interfaces | ||
|
||
type VerifToken struct { | ||
Username string `json:"username"` | ||
Email string `json:"email"` | ||
GoogleID string `json:"google_id"` | ||
Role string `json:"role"` | ||
ActivationCode int `json:"email_verification_token"` | ||
ResetPasswordToken int `json:"reset_password_token"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package mailers | ||
|
||
import ( | ||
"os" | ||
"log" | ||
"bytes" | ||
"strconv" | ||
"text/template" | ||
"mailer/interfaces" | ||
|
||
"github.com/go-mail/mail" | ||
"github.com/joho/godotenv" | ||
) | ||
|
||
func SendMail(record interfaces.Record, msg interface{}){ | ||
err := godotenv.Load() | ||
if err != nil { | ||
log.Println("Error loading .env file:", err) | ||
} | ||
|
||
smtpHost := os.Getenv("SMTP_HOST") | ||
smtpPortStr := os.Getenv("SMTP_PORT") | ||
smtpUser := os.Getenv("SMTP_USER") | ||
smtpPass := os.Getenv("SMTP_PASS") | ||
senderEmail := os.Getenv("SMTP_SENDER_EMAIL") | ||
senderName := os.Getenv("SMTP_SENDER_NAME") | ||
|
||
templateName := record.Tag+"_template.html" | ||
|
||
var tmpl *template.Template | ||
|
||
tmpl, err = template.ParseFiles("templates/"+templateName) | ||
if err != nil { | ||
log.Printf("Failed to load %v template: %v\n", record.Tag, err) | ||
return | ||
} | ||
|
||
smtpPort, err := strconv.Atoi(smtpPortStr) | ||
if err != nil { | ||
log.Printf("Failed to convert SMTP port to integer: %v\n", err) | ||
return | ||
} | ||
|
||
mailer := mail.NewDialer(smtpHost, smtpPort, smtpUser, smtpPass) | ||
m := mail.NewMessage() | ||
|
||
if record.Email == "" || record.Subject == ""{ | ||
log.Printf("Invalid record: %+v\n", record) | ||
return | ||
} | ||
|
||
m.SetHeader("From", senderName+" <"+senderEmail+">") | ||
m.SetHeader("To", record.Email) | ||
m.SetHeader("Subject", record.Subject) | ||
|
||
body := &bytes.Buffer{} | ||
if err := tmpl.Execute(body, msg); err != nil { | ||
log.Printf("Failed to execute template: %v\n", err) | ||
return | ||
} | ||
|
||
m.SetBody("text/html", body.String()) | ||
if err := mailer.DialAndSend(m); err != nil { | ||
log.Printf("Failed to send email: %v\n", err) | ||
}else{ | ||
log.Printf("Sent email Successfully") | ||
} | ||
} |
Oops, something went wrong.