init project

master
RuisPipe 2021-06-15 16:50:36 +02:00
commit 9d5b078475
10 changed files with 372 additions and 0 deletions

11
config.toml Normal file
View File

@ -0,0 +1,11 @@
[server]
debug = true
host = "127.0.0.1:3001"
[mail]
host = "cmail02.mailhost24.de"
port = "25"
user = "no-reply@roese.dev"
password = "mhtWMUn049o25xYTLUpfplX5Ze3jRfqh"
from = "App <no-reply@roese.dev>"
templatePath = "./templates/"

9
go.mod Normal file
View File

@ -0,0 +1,9 @@
module git.umbach.dev/app-idea/mailer
go 1.16
require (
github.com/BurntSushi/toml v0.3.1
github.com/gofiber/fiber/v2 v2.12.0
github.com/sirupsen/logrus v1.8.1
)

35
go.sum Normal file
View File

@ -0,0 +1,35 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gofiber/fiber/v2 v2.12.0 h1:R7FVMs9mtMREjfCzCioh2j8RHwhz0/H+X0rH6BpBkJ4=
github.com/gofiber/fiber/v2 v2.12.0/go.mod h1:oZTLWqYnqpMMuF922SjGbsYZsdpE1MCfh416HNdweIM=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.26.0 h1:k5Tooi31zPG/g8yS6o2RffRO2C9B9Kah9SY8j/S7058=
github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

27
main.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
"git.umbach.dev/app-idea/mailer/modules/config"
"git.umbach.dev/app-idea/mailer/modules/mailer"
"git.umbach.dev/app-idea/mailer/routers/router"
"github.com/gofiber/fiber/v2"
log "github.com/sirupsen/logrus"
)
func main() {
app := fiber.New()
config.LoadConfig()
cfg := &config.Cfg.Server
if cfg.Debug {
log.SetLevel(log.DebugLevel)
}
mailer.InitMailer()
router.SetupRoutes(app)
app.Listen(cfg.Host)
}

30
modules/config/config.go Normal file
View File

@ -0,0 +1,30 @@
package config
import (
"github.com/BurntSushi/toml"
)
var Cfg Config
type Config struct {
Server server
Mail mail
}
type server struct {
Debug bool
Host string
}
type mail struct {
Host string
Port string
User string
Password string
From string
TemplatePath string
}
func LoadConfig() {
toml.DecodeFile("./config.toml", &Cfg)
}

153
modules/mailer/mailer.go Normal file
View File

@ -0,0 +1,153 @@
package mailer
import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"net/smtp"
"strings"
"git.umbach.dev/app-idea/mailer/modules/config"
log "github.com/sirupsen/logrus"
)
var auth smtp.Auth
var cfg = &config.Cfg.Mail
func InitMailer() {
auth = smtp.PlainAuth("", cfg.User, cfg.Password, cfg.Host)
readTemplatesConfig()
loadTemplateFiles()
}
type Mail struct {
To []string
Subject string
BodyTemplateId int
LanguageId int
BodyData interface{}
}
func NewMail(to []string, bodyTemplateId int, languageId int, bodyData interface{}) {
log.Infoln("new mail", bodyTemplateId, bodyData)
mail := Mail{
To: to,
Subject: "",
BodyTemplateId: bodyTemplateId,
LanguageId: languageId,
BodyData: bodyData,
}
body, err := mail.RenderTemplate()
log.Infoln("body", body, bodyData)
if err != nil {
log.Fatalln("error parsing", err)
}
mail.Send(body)
}
func (m *Mail) Send(body string) {
msg := "From: " + cfg.From + "\n" +
"To: " + strings.Join(m.To, ",") + "\n" +
"Subject: " + m.Subject + "\n" +
"MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n" +
body
err := smtp.SendMail(cfg.Host+":"+cfg.Port, auth, cfg.From, m.To, []byte(msg))
if err != nil {
log.Warnln("smtp error:", err)
} else {
log.Debugln("send mail")
}
}
type Templates struct {
Templates []Template `json:"templates"`
}
type Template struct {
Id int `json:"id"`
FileName string `json:"fileName"`
Body string
Languages []Languages `json:"languages"`
}
type Languages struct {
Id int `json:"id"`
Subject string `json:"subject"`
Texts map[string]interface{} `json:"texts"`
}
var templates Templates
func readTemplatesConfig() {
byteValue, err := ioutil.ReadFile("./templates/templates.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(byteValue, &templates)
if err != nil {
log.Fatal("failed unmarshal", err)
}
log.Infoln("templates", templates)
}
func loadTemplateFiles() {
for i := 0; i < len(templates.Templates); i++ {
log.Debugln("load template file id", templates.Templates[i].Id)
t := &templates.Templates[i]
data, err := ioutil.ReadFile(cfg.TemplatePath + t.FileName + ".html")
if err != nil {
log.Fatalln("read file err", err)
}
t.Body = string(data)
}
}
// https://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p
func (m *Mail) RenderTemplate() (string, error) {
// define subject form config
m.Subject = templates.Templates[0].Languages[0].Subject
body := templates.Templates[0].Body
// replace body %values% with values in templates config
for i := 0; i < len(templates.Templates[0].Languages); i++ {
for key, value := range templates.Templates[0].Languages[i].Texts {
strKey := fmt.Sprintf("%v", key)
strValue := fmt.Sprintf("%v", value)
log.Infoln("a", strKey, strValue)
body = strings.Replace(body, "%"+strKey+"%", strValue, -1)
}
}
t := template.Must(template.New("").Parse(body))
buf := new(bytes.Buffer)
log.Infoln("test")
if err := t.Execute(buf, m.BodyData); err != nil {
log.Fatalln("err execute", err)
}
return buf.String(), nil
}

38
routers/api/mail/mail.go Normal file
View File

@ -0,0 +1,38 @@
package mail
import (
"encoding/json"
"git.umbach.dev/app-idea/mailer/modules/mailer"
"github.com/gofiber/fiber/v2"
log "github.com/sirupsen/logrus"
)
type MailInput struct {
Key string `json:"k"`
Mail string `json:"m"`
BodyTemplateId int `json:"t"`
LanguageId int `json:"l"`
BodyData *json.RawMessage `json:"d"`
}
func SendMail(c *fiber.Ctx) error {
var input MailInput
if err := c.BodyParser(&input); err != nil {
log.Infoln("bodyParser failed:", err)
return c.SendStatus(fiber.StatusUnauthorized)
}
var bodyData map[string]interface{}
if err := json.Unmarshal(*input.BodyData, &bodyData); err != nil {
log.Fatal(err)
}
log.Infoln("input", input, bodyData)
mailer.NewMail([]string{"app@roese.dev"}, input.BodyTemplateId, input.LanguageId, bodyData)
return c.SendStatus(fiber.StatusOK)
}

11
routers/router/router.go Normal file
View File

@ -0,0 +1,11 @@
package router
import (
"github.com/gofiber/fiber/v2"
"git.umbach.dev/app-idea/mailer/routers/api/mail"
)
func SetupRoutes(app *fiber.App) {
app.Post("/send", mail.SendMail)
}

View File

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body>
<h1>%header%</h1>
<p>%text%</p>
<a
href="{{.url}}"
style="
padding: 8px 20px;
background-color: #4b72fa;
color: #fff;
font-weight: bolder;
font-size: 16px;
display: inline-block;
margin: 20px 0px;
margin-right: 20px;
text-decoration: none;
"
>%buttonText%</a
>
<p>Or use this Url: {{.url}}</p>
</body>
</html>

33
templates/templates.json Normal file
View File

@ -0,0 +1,33 @@
{
"templates": [
{
"id": 0,
"fileName": "accountActivation",
"languages": [
{
"id": 0,
"subject": "Konto aktivieren",
"texts": {
"header": "Hallo {{.name}},",
"text": "Vielen Dank für das erstellen eines Kontos auf Roese.dev. Um dein Konto nutzen zu können, musst du es noch aktivieren.",
"buttonText": "Account aktivieren"
}
},
{
"id": 1,
"subject": "Account activation"
}
]
},
{
"id": 1,
"fileName": "accountActivation",
"languages": [
{
"id": 0,
"subject": "Test"
}
]
}
]
}