From 9d5b0784755c45912b1e0e8fc82c549308b6e598 Mon Sep 17 00:00:00 2001 From: RuisPipe Date: Tue, 15 Jun 2021 16:50:36 +0200 Subject: [PATCH] init project --- config.toml | 11 +++ go.mod | 9 ++ go.sum | 35 +++++++ main.go | 27 ++++++ modules/config/config.go | 30 ++++++ modules/mailer/mailer.go | 153 +++++++++++++++++++++++++++++++ routers/api/mail/mail.go | 38 ++++++++ routers/router/router.go | 11 +++ templates/accountActivation.html | 25 +++++ templates/templates.json | 33 +++++++ 10 files changed, 372 insertions(+) create mode 100644 config.toml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 modules/config/config.go create mode 100644 modules/mailer/mailer.go create mode 100644 routers/api/mail/mail.go create mode 100644 routers/router/router.go create mode 100644 templates/accountActivation.html create mode 100644 templates/templates.json diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..e04d198 --- /dev/null +++ b/config.toml @@ -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 " +templatePath = "./templates/" \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5a72d7b --- /dev/null +++ b/go.mod @@ -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 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b317c78 --- /dev/null +++ b/go.sum @@ -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= diff --git a/main.go b/main.go new file mode 100644 index 0000000..371163b --- /dev/null +++ b/main.go @@ -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) +} diff --git a/modules/config/config.go b/modules/config/config.go new file mode 100644 index 0000000..5bebc6a --- /dev/null +++ b/modules/config/config.go @@ -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) +} diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go new file mode 100644 index 0000000..4928aa0 --- /dev/null +++ b/modules/mailer/mailer.go @@ -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 +} diff --git a/routers/api/mail/mail.go b/routers/api/mail/mail.go new file mode 100644 index 0000000..4fd5677 --- /dev/null +++ b/routers/api/mail/mail.go @@ -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) +} diff --git a/routers/router/router.go b/routers/router/router.go new file mode 100644 index 0000000..eebee3e --- /dev/null +++ b/routers/router/router.go @@ -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) +} diff --git a/templates/accountActivation.html b/templates/accountActivation.html new file mode 100644 index 0000000..8cea383 --- /dev/null +++ b/templates/accountActivation.html @@ -0,0 +1,25 @@ + + + +

%header%

+

%text%

+ + %buttonText% + +

Or use this Url: {{.url}}

+ + diff --git a/templates/templates.json b/templates/templates.json new file mode 100644 index 0000000..940a2c2 --- /dev/null +++ b/templates/templates.json @@ -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" + } + ] + } + ] +}