Skip to content

Commit

Permalink
added tests for email templating
Browse files Browse the repository at this point in the history
  • Loading branch information
CommanderStorm committed Sep 3, 2023
1 parent 2d61267 commit 9200fcb
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 66 deletions.
31 changes: 15 additions & 16 deletions server/backend/cron/emailTemplates/feedbackBody.gohtml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<h1>Feedback via TumCampusApp:</h1>

{{ if .Feedback.Valid }}
{{ if .Feedback.Valid -}}
<blockquote>
{{ .Feedback.String }}
{{- .Feedback.String -}}
</blockquote>
{{ end }}

{{- else -}}
<i>no feedback provided</i>
{{- end }}
<table>
<tr>
<th>Inforation type</th>
<th>Details</th>
</tr>
{{ if .Latitude.Valid }}
{{- if .Latitude.Valid }}
<tr>
<th>Nutzer-Standort</th>
<td>
Expand All @@ -20,24 +20,23 @@
</a>
</td>
</tr>
{{ end }}
{{- end }}
<tr>
<th>OS-Version</th>
<td>{{ if .OsVersion.Valid }}{{.OsVersion.String }}{{else}}unknown{{end}}</td>
</tr>
<tr>
<th>App-Version</th>
<td>{{ if .AppVersion.Valid }}{{.APPVersion.String }}{{else}}unknown{{end}}</td>
<td>{{ if .AppVersion.Valid }}{{.AppVersion.String }}{{else}}unknown{{end}}</td>
</tr>
</table>

{{ if .ImageCount }}
{{- if .ImageCount }}
<h2>Fotos:</h2><br/>
<ol>
{{ range $val := Iterate .ImageCount }}
<li>
<a href="https://app.tum.de/File/feedback/{{ $.Id }}/{{ $val }}.png">Foto {{ $val }}</a>
</li>
{{ end }}
{{- range $val := iterate .ImageCount }}
<li>
<a href="https://app.tum.de/File/feedback/{{ $.Id }}/{{ $val }}.png">Foto {{ $val }}</a>
</li>
{{- end }}
</ol>
{{ end }}
{{- end -}}
22 changes: 12 additions & 10 deletions server/backend/cron/emailTemplates/feedbackBody.txt.tmpl
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
Feedback via TumCampusApp:

{{- if .Feedback.Valid }}
{{ .Feedback.String }}
{{ if .Feedback.Valid }}
{{- .Feedback.String -}}
{{ else -}}
no feedback provided
{{- end }}

Metadata:
{{- if .Latitude.Valid }}
- Nutzer-Standort:
latitude: {{ .Latitude.Float64 }}, longitude: {{ .Longitude.Float64 }}
https://www.google.com/maps/search/?api=1&query={{ .Latitude.Float64 }},{{ .Longitude.Float64 }}
- Nutzer-Standort: {{ .Latitude.Float64 }},{{ .Longitude.Float64 }} (latitude,longitude)
https://www.google.com/maps/search/?api=1&query={{ .Latitude.Float64 }},{{ .Longitude.Float64 }}
{{- end }}
- OS-Version: {{ if .OsVersion.Valid }}{{.OsVersion.String }}{{else}}unknown{{end}}
- App-Version: {{ if .AppVersion.Valid }}{{.APPVersion.String }}{{else}}unknown{{end}}
- App-Version: {{ if .AppVersion.Valid }}{{.AppVersion.String }}{{else}}unknown{{end}}
{{- if .ImageCount }}

{{ if .ImageCount }}
Fotos:
{{- range $val := Iterate .ImageCount }}
- Foto {{ $val }}: https://app.tum.de/File/feedback/{{ $.Id }}/{{ $val }}.png
Photos:
{{- range $val := iterate .ImageCount }}
- Photo {{ $val }}: https://app.tum.de/File/feedback/{{ $.Id }}/{{ $val }}.png
{{- end -}}
{{- end -}}
114 changes: 74 additions & 40 deletions server/backend/cron/feedbackEmail.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import (
)
import _ "embed"

// Iterate is necessary, as go otherwise cannot count up in a for loop inside templates
func Iterate(count int32) []int32 {
var Items []int32
// iterate is necessary, as go otherwise cannot count up in a for loop inside templates
func iterate(count int32) []int32 {
var items []int32
var i int32
for i = 0; i < count; i++ {
Items = append(Items, i)
items = append(items, i)
}
return Items
return items
}

//go:embed emailTemplates/feedbackBody.gohtml
Expand All @@ -30,21 +30,75 @@ var htmlFeedbackBody string
//go:embed emailTemplates/feedbackBody.txt.tmpl
var txtFeedbackBody string

func parseTemplates() (*htmlTemplate.Template, *textTemplate.Template, error) {
funcMap := textTemplate.FuncMap{"iterate": iterate}
parsedHtmlBody, err := htmlTemplate.New("htmlFeedbackBody").Funcs(funcMap).Parse(htmlFeedbackBody)
if err != nil {
return nil, nil, err
}
parsedTxtBody, err := textTemplate.New("txtFeedbackBody").Funcs(funcMap).Parse(txtFeedbackBody)
if err != nil {
return nil, nil, err
}
return parsedHtmlBody, parsedTxtBody, nil

}

type MailHeaders struct {
From string
To string
ReplyTo string //optional
Timestamp time.Time
Subject string
}

func messageWithHeaders(feedback *model.Feedback) *gomail.Message {
m := gomail.NewMessage()
// From
m.SetAddressHeader("From", os.Getenv("SMTP_USERNAME"), "TUM Campus App")
// To
if feedback.Receiver.Valid {
m.SetHeader("To", feedback.Receiver.String)
} else {
m.SetHeader("To", "[email protected]")
}
// ReplyTo
if feedback.ReplyTo.Valid {
m.SetHeader("Reply-To", feedback.ReplyTo.String)
}
// Timestamp
if feedback.Timestamp.Valid {
m.SetDateHeader("Date", feedback.Timestamp.Time)
} else {
m.SetDateHeader("Date", time.Now())
}
// Subject
m.SetHeader("Subject", "Feedback via Tum Campus App")
return m
}

func generateTemplatedMail(parsedHtmlBody *htmlTemplate.Template, parsedTxtBody *textTemplate.Template, feedback *model.Feedback) (string, string, error) {
var htmlBodyBuffer bytes.Buffer
if err := parsedHtmlBody.Execute(&htmlBodyBuffer, feedback); err != nil {
return "", "", err
}
var txtBodyBuffer bytes.Buffer
if err := parsedTxtBody.Execute(&txtBodyBuffer, feedback); err != nil {
return "", "", err
}
return htmlBodyBuffer.String(), txtBodyBuffer.String(), nil
}

func (c *CronService) feedbackEmailCron() error {

var results []model.Feedback
if err := c.db.Find(&results, "processed = false").Scan(&results).Error; err != nil {
log.WithError(err).Fatal("could not get unprocessed feedback")
return err
}
funcMap := textTemplate.FuncMap{"Iterate": Iterate}
parsedHtmlBody, err := htmlTemplate.New("htmlFeedbackBody").Funcs(funcMap).Parse(htmlFeedbackBody)
if err != nil {
log.WithError(err).Fatal("htmlFeedbackBody is not a valid template")
return err
}
parsedTxtBody, err := textTemplate.New("txtFeedbackBody").Funcs(funcMap).Parse(txtFeedbackBody)
parsedHtmlBody, parsedTxtBody, err := parseTemplates()
if err != nil {
log.WithError(err).Fatal("txtFeedbackBody is not a valid template")
log.WithError(err).Fatal("could not parse email templates")
return err
}

Expand All @@ -56,43 +110,23 @@ func (c *CronService) feedbackEmailCron() error {
d := gomail.NewDialer(os.Getenv("SMTP_URL"), smtpPort, os.Getenv("SMTP_USERNAME"), os.Getenv("SMTP_PASSWORD"))
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
for i, feedback := range results {
m := gomail.NewMessage()
// set message-headers
m.SetAddressHeader("From", os.Getenv("SMTP_USERNAME"), "TUM Campus App")
if feedback.Receiver.Valid {
m.SetHeader("To", feedback.Receiver.String)
} else {
m.SetHeader("To", "[email protected]")
}
if feedback.ReplyTo.Valid {
m.SetHeader("Reply-To", feedback.ReplyTo.String)
}
if feedback.Timestamp.Valid {
m.SetDateHeader("Date", feedback.Timestamp.Time)
} else {
m.SetDateHeader("Date", time.Time{})
}
m.SetHeader("Subject", "Feedback via Tum Campus App")
m := messageWithHeaders(&feedback)

// attach a body
var txtBodyBuffer bytes.Buffer
if err := parsedTxtBody.Execute(&txtBodyBuffer, feedback); err != nil {
return err
}
m.SetBody("text/plain", txtBodyBuffer.String())

var htmlBodyBuffer bytes.Buffer
if err := parsedHtmlBody.Execute(&htmlBodyBuffer, feedback); err != nil {
htmlBodyBuffer, txtBodyBuffer, err := generateTemplatedMail(parsedHtmlBody, parsedTxtBody, &feedback)
if err != nil {
log.WithError(err).Error("Could not template mail body")
return err
}
m.AddAlternative("text/html", htmlBodyBuffer.String())
m.SetBody("text/plain", txtBodyBuffer)
m.AddAlternative("text/html", htmlBodyBuffer)

// send mail
if err := d.DialAndSend(m); err != nil {
log.WithError(err).Error("could not send mail")
continue
}
log.Trace("sending feedback %d to %s successfull", i, feedback.Receiver)
log.Tracef("sending feedback %d to %v successfull", i, feedback.Receiver)

// prevent the message being send the next time around
if err := c.db.Find(model.Feedback{}, "id = ?", feedback.Id).Update("processed", "true").Error; err != nil {
Expand Down
Loading

0 comments on commit 9200fcb

Please sign in to comment.