disabled html minfiy, added some headers and new templateS
parent
bf95daba4a
commit
b8c2ec315e
1
go.mod
1
go.mod
|
@ -12,6 +12,7 @@ require (
|
|||
require (
|
||||
github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -21,6 +21,8 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
|||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"clickandjoin.app/emailserver/modules/cache"
|
||||
"clickandjoin.app/emailserver/modules/config"
|
||||
gocnjhelper "git.ex.umbach.dev/ClickandJoin/go-cnj-helper"
|
||||
"github.com/tdewolff/minify/v2/minify"
|
||||
)
|
||||
|
||||
func readTemplatesConfig() {
|
||||
|
@ -37,14 +36,16 @@ func loadTemplateFiles() {
|
|||
if err != nil {
|
||||
gocnjhelper.LogFatalf("Failed to read file, err: %s", err)
|
||||
}
|
||||
/*
|
||||
minifiedHtml, err := minify.HTML(string(data))
|
||||
|
||||
minifiedHtml, err := minify.HTML(string(data))
|
||||
if err != nil {
|
||||
gocnjhelper.LogFatalf("Failed to minify html, err: %s", err)
|
||||
} */
|
||||
|
||||
if err != nil {
|
||||
gocnjhelper.LogFatalf("Failed to minify html, err: %s", err)
|
||||
}
|
||||
// cache.BodyTemplates[templateName] = []byte(minifiedHtml)
|
||||
|
||||
cache.BodyTemplates[templateName] = []byte(minifiedHtml)
|
||||
cache.BodyTemplates[templateName] = []byte(data)
|
||||
}
|
||||
|
||||
gocnjhelper.LogDebug("FINISHED IMPORTING TEMPLATE FILES")
|
||||
|
|
|
@ -27,11 +27,12 @@ type RabbitMq struct {
|
|||
}
|
||||
|
||||
type Mail struct {
|
||||
Host string
|
||||
Username string
|
||||
Password string
|
||||
Port string
|
||||
From string
|
||||
Host string
|
||||
Username string
|
||||
Password string
|
||||
Port string
|
||||
FromName string
|
||||
FromEmail string
|
||||
}
|
||||
|
||||
type Templates struct {
|
||||
|
@ -77,11 +78,12 @@ func LoadConfig() {
|
|||
Password: os.Getenv("RABBITMQ_PASSWORD"),
|
||||
},
|
||||
Mail: Mail{
|
||||
Host: os.Getenv("MAIL_HOST"),
|
||||
Username: os.Getenv("MAIL_USERNAME"),
|
||||
Password: os.Getenv("MAIL_PASSWORD"),
|
||||
Port: os.Getenv("MAIL_PORT"),
|
||||
From: os.Getenv("MAIL_FROM"),
|
||||
Host: os.Getenv("MAIL_HOST"),
|
||||
Username: os.Getenv("MAIL_USERNAME"),
|
||||
Password: os.Getenv("MAIL_PASSWORD"),
|
||||
Port: os.Getenv("MAIL_PORT"),
|
||||
FromName: os.Getenv("MAIL_FROM_NAME"),
|
||||
FromEmail: os.Getenv("MAIL_FROM_EMAIL"),
|
||||
},
|
||||
Templates: Templates{
|
||||
FolderPath: os.Getenv("TEMPLATES_FOLDER_PATH"),
|
||||
|
|
|
@ -58,7 +58,8 @@ func MailMessagesHandling() {
|
|||
// only for testing
|
||||
if !strings.HasSuffix(mailMessage.UserMail, "@roese.dev") &&
|
||||
!strings.HasSuffix(mailMessage.UserMail, "@umbach.dev") &&
|
||||
!strings.HasSuffix(mailMessage.UserMail, "@kk-innovation.eu") {
|
||||
!strings.HasSuffix(mailMessage.UserMail, "@kk-innovation.eu") &&
|
||||
!strings.HasSuffix(mailMessage.UserMail, "@srv1.mail-tester.com") {
|
||||
mailMessage.UserMail = "myprojects@roese.dev"
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,17 @@ package structs
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"clickandjoin.app/emailserver/modules/cache"
|
||||
"clickandjoin.app/emailserver/modules/config"
|
||||
"clickandjoin.app/emailserver/modules/escaper"
|
||||
gocnjhelper "git.ex.umbach.dev/ClickandJoin/go-cnj-helper"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Mail struct {
|
||||
|
@ -24,13 +27,15 @@ type Mail struct {
|
|||
func (m *Mail) Send(body string) error {
|
||||
cfg := config.Cfg.Mail
|
||||
|
||||
msg := "From: " + cfg.From + "\n" +
|
||||
msg := "From: " + EncodeBase64(cfg.FromName) + " <" + cfg.FromEmail + ">\n" +
|
||||
"To: " + strings.Join(m.To, ",") + "\n" +
|
||||
"Subject: " + m.Subject + "\n" +
|
||||
"Date: " + time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700") + "\n" +
|
||||
"Message-ID: <" + uuid.New().String() + "@" + strings.Split(cfg.FromEmail, "@")[1] + ">\n" +
|
||||
"MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n" +
|
||||
body
|
||||
|
||||
err := smtp.SendMail(cfg.Host+":"+cfg.Port, cache.SmtpAuth, cfg.From, m.To, []byte(msg))
|
||||
err := smtp.SendMail(cfg.Host+":"+cfg.Port, cache.SmtpAuth, cfg.FromEmail, m.To, []byte(msg))
|
||||
|
||||
if err != nil {
|
||||
gocnjhelper.LogErrorf("smtp error: %s", err)
|
||||
|
@ -84,7 +89,9 @@ func (m *Mail) RenderTemplate() (string, error) {
|
|||
// The subject line of an email is an independent header and utf 8 must be set for it
|
||||
// https://ncona.com/2011/06/using-utf-8-characters-on-an-e-mail-subject/
|
||||
if m.LanguageId == "de" {
|
||||
m.Subject = "=?utf-8?B?" + base64.StdEncoding.EncodeToString([]byte(m.Subject)) + "?="
|
||||
//m.Subject = "=?utf-8?B?" + base64.StdEncoding.EncodeToString([]byte(m.Subject)) + "?="
|
||||
|
||||
m.Subject = EncodeBase64(m.Subject)
|
||||
}
|
||||
|
||||
t := template.Must(template.New("").Parse(string(body)))
|
||||
|
@ -97,3 +104,8 @@ func (m *Mail) RenderTemplate() (string, error) {
|
|||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// https://ncona.com/2011/06/using-utf-8-characters-on-an-e-mail-subject/
|
||||
func EncodeBase64(s string) string {
|
||||
return fmt.Sprintf("=?utf-8?B?%s?=", base64.StdEncoding.EncodeToString([]byte(s)))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: "Arial", sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
}
|
||||
table.content {
|
||||
width: 100%;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
color: #555;
|
||||
margin: 0 0 15px;
|
||||
}
|
||||
.verification-code {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #3498db;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.booking-details {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
|
||||
background-color: #f4f4f4;
|
||||
text-align: center;
|
||||
|
||||
border-radius: 8px;
|
||||
}
|
||||
.booking-details p {
|
||||
margin: 5px 20px;
|
||||
}
|
||||
.booking-desc {
|
||||
color: #000;
|
||||
}
|
||||
.booking-label {
|
||||
font-weight: bold;
|
||||
color: #3498db;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 20px;
|
||||
color: #777;
|
||||
font-size: 12px;
|
||||
}
|
||||
.confirm-button {
|
||||
display: inline-block;
|
||||
padding: 10px 15px;
|
||||
background-color: #3498db;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.cancel-button {
|
||||
display: inline-block;
|
||||
padding: 10px 15px;
|
||||
background-color: #e74c3c;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table class="container" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="content">
|
||||
<h1>%title%</h1>
|
||||
<p>%header%</p>
|
||||
<p>%text1%</p>
|
||||
<a href="{{.verifyURL}}" class="confirm-button">%verifyButton%</a>
|
||||
<div class="divider"></div>
|
||||
<p>%cancelText%</p>
|
||||
<a href="{{.cancelURL}}" class="cancel-button">%cancelButton%</a>
|
||||
<div class="divider"></div>
|
||||
<table class="booking-details">
|
||||
<tr>
|
||||
<td>
|
||||
<p class="booking-label">%yourAppointment%</p>
|
||||
<p class="booking-desc">%appointment1%</p>
|
||||
<p class="booking-desc">%appointment2%</p>
|
||||
<p class="booking-desc">%appointment3%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="divider"></div>
|
||||
<p>{{.address}}</p>
|
||||
|
||||
<p class="footer">%footer%</p>
|
||||
<a class="footer" href="https://www.kk-innovation.eu">%dsgvo%</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,96 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: "Arial", sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
}
|
||||
table.content {
|
||||
width: 100%;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
color: #555;
|
||||
margin: 0 0 15px;
|
||||
}
|
||||
.verification-code {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #3498db;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.booking-details {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
|
||||
background-color: #f4f4f4;
|
||||
text-align: center;
|
||||
|
||||
border-radius: 8px;
|
||||
}
|
||||
.booking-details p {
|
||||
margin: 5px 20px;
|
||||
}
|
||||
.booking-desc {
|
||||
color: #000;
|
||||
}
|
||||
.booking-label {
|
||||
font-weight: bold;
|
||||
color: #3498db;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 20px;
|
||||
color: #777;
|
||||
font-size: 12px;
|
||||
}
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table class="container" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="content">
|
||||
<h1>%title%</h1>
|
||||
<p>%header%</p>
|
||||
<p>%text1%</p>
|
||||
<div class="divider"></div>
|
||||
<table class="booking-details">
|
||||
<tr>
|
||||
<td>
|
||||
<p class="booking-label">%yourAppointment%</p>
|
||||
<p class="booking-desc">%appointment1%</p>
|
||||
<p class="booking-desc">%appointment2%</p>
|
||||
<p class="booking-desc">%appointment3%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="divider"></div>
|
||||
<p>{{.address}}</p>
|
||||
|
||||
<a class="footer" href="https://www.kk-innovation.eu">%dsgvo%</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -18,6 +18,78 @@
|
|||
"de": "Bitte gebe diesen Code in der App ein"
|
||||
}
|
||||
},
|
||||
"emailVerifyFailed": {
|
||||
"mailSubject": {
|
||||
"de": "Ihre Buchung wurde storniert"
|
||||
},
|
||||
"title": {
|
||||
"de": "Ihre Buchung wurde storniert"
|
||||
},
|
||||
"header": {
|
||||
"de": "Liebe(r) {{.name}},"
|
||||
},
|
||||
"text1": {
|
||||
"de": "Ihre Buchung wurde storniert. Sie können gerne einen neuen Termin auf unserer Webseite festlegen."
|
||||
},
|
||||
"yourAppointment": {
|
||||
"de": "Ihr Termin:"
|
||||
},
|
||||
"appointment1": {
|
||||
"de": "{{.activityName}} bei {{.username}},"
|
||||
},
|
||||
"appointment2": {
|
||||
"de": "{{.day}}, {{.dayNumber}}. {{.month}} {{.year}}"
|
||||
},
|
||||
"appointment3": {
|
||||
"de": "von {{.startTime}} bis {{.endTime}} Uhr"
|
||||
},
|
||||
"footer": {
|
||||
"de": "Vielen Dank, dass Sie unseren Service gewählt haben. Bei Fragen kontaktieren Sie uns gerne."
|
||||
},
|
||||
"dsgvo": {
|
||||
"de": "Datenschutzerklärung"
|
||||
}
|
||||
},
|
||||
"emailVerification2": {
|
||||
"mailSubject": {
|
||||
"de": "Bitte Bestätigen Sie Ihre Buchung"
|
||||
},
|
||||
"title": {
|
||||
"de": "Buchungsbestätigung"
|
||||
},
|
||||
"header": {
|
||||
"de": "Liebe(r) {{.name}},"
|
||||
},
|
||||
"text1": {
|
||||
"de": "Ihre Buchung wurde erfolgreich empfangen und wartet auf Bestätigung. Bitte klicken Sie auf die untenstehende Schaltfläche, um den Vorgang abzuschließen."
|
||||
},
|
||||
"verifyButton": {
|
||||
"de": "Buchung bestätigen"
|
||||
},"cancelButton": {
|
||||
"de": "Buchung stornieren"
|
||||
},
|
||||
"cancelText": {
|
||||
"de": "Falls Sie Ihren Termin nicht wahrnehmen können, bitten wir Sie, den Termin zu stornieren."
|
||||
},
|
||||
"yourAppointment": {
|
||||
"de": "Ihr Termin:"
|
||||
},
|
||||
"appointment1": {
|
||||
"de": "{{.activityName}} bei {{.username}},"
|
||||
},
|
||||
"appointment2": {
|
||||
"de": "{{.day}}, {{.dayNumber}}. {{.month}} {{.year}}"
|
||||
},
|
||||
"appointment3": {
|
||||
"de": "von {{.startTime}} bis {{.endTime}} Uhr"
|
||||
},
|
||||
"footer": {
|
||||
"de": "Vielen Dank, dass Sie unseren Service gewählt haben. Bei Fragen kontaktieren Sie uns gerne."
|
||||
},
|
||||
"dsgvo": {
|
||||
"de": "Datenschutzerklärung"
|
||||
}
|
||||
},
|
||||
"newUserSignIn": {
|
||||
"mailSubject": {
|
||||
"en": "A new sign-in was detected",
|
||||
|
|
Loading…
Reference in New Issue