From 5ff799f5e7d49e0d6c542fe79d4b247ff8365575 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Fri, 9 Jan 2026 14:03:05 -0500 Subject: [PATCH] Now renders a .md file to use as the text and HTML versions of emails. --- common/email/api.go | 46 ++++++++++++++++++++++++++++++++---------- common/email/data.go | 5 +++-- config/settings.go | 1 + config_example.json | 3 ++- emails/signup.html | 3 --- emails/signup.md | 4 ++++ features/email/api.go | 3 +-- tools/cmd/qmgr/main.go | 3 +-- 8 files changed, 47 insertions(+), 21 deletions(-) delete mode 100644 emails/signup.html create mode 100644 emails/signup.md diff --git a/common/email/api.go b/common/email/api.go index f9c97e2..a587cc3 100644 --- a/common/email/api.go +++ b/common/email/api.go @@ -6,17 +6,14 @@ import ( "context" "log" "github.com/redis/go-redis/v9" - "github.com/gofiber/template/html/v2" + "github.com/yuin/goldmark" "MY/webapp/config" + "path/filepath" + "text/template" + "os" "strings" ) -var HTMLTemplates *html.Engine - -func init() { - HTMLTemplates = html.New("./emails", ".html") -} - func NewSender(ctx context.Context) (Sender){ client := redis.NewClient(&redis.Options{ Addr: config.Settings.Redis.HostPort, @@ -55,6 +52,33 @@ func (sender *Sender) Close() { sender.redis_client.Close() } +func (router *Router) Render(tmpl_path string, data any) (string, string, error) { + tmpl_path = filepath.Join(config.Settings.Email.Templates, tmpl_path) + + // load the markdown file + md_file, err := os.ReadFile(tmpl_path) + if err != nil { return "", "", err } + + // template it + tmpl, err := template.New(tmpl_path).Parse(string(md_file)) + if err != nil { return "", "", err } + + out := new(strings.Builder) + err = tmpl.Execute(out, data) + if err != nil { return "", "", err } + text_out := out.String() + + // convert to html + out.Reset() + err = goldmark.Convert([]byte(text_out), out) + if err != nil { return "", "", err } + + html_out := out.String() + + // return the template .md as plain text and .html as html + return string(text_out), string(html_out), nil +} + func (router *Router) DeliverEmail(msg EmailMessage) error { email_msg := mail.NewMsg() err := email_msg.From(msg.From) @@ -65,10 +89,6 @@ func (router *Router) DeliverEmail(msg EmailMessage) error { email_msg.Subject(msg.Subject) - out := new(strings.Builder) - err = HTMLTemplates.Render(out, msg.HTMLTemplate, msg.Data) - email_msg.SetBodyString(mail.TypeTextHTML, out.String()) - if config.Settings.Email.XMailer != "" { email_msg.SetGenHeader(mail.HeaderXMailer, config.Settings.Email.XMailer) } @@ -77,8 +97,12 @@ func (router *Router) DeliverEmail(msg EmailMessage) error { email_msg.SetGenHeader(mail.HeaderUserAgent, config.Settings.Email.UserAgent) } + text, html, err := router.Render(msg.Template, nil) if err != nil { return err } + email_msg.SetBodyString(mail.TypeTextHTML, html) + email_msg.AddAlternativeString(mail.TypeTextPlain, text) + err = router.smtp_client.DialAndSendWithContext(router.ctx, email_msg) if err != nil { return err } diff --git a/common/email/data.go b/common/email/data.go index ceabbb2..2886b3e 100644 --- a/common/email/data.go +++ b/common/email/data.go @@ -4,15 +4,15 @@ import ( "github.com/redis/go-redis/v9" "github.com/wneessen/go-mail" "context" + ) type EmailMessage struct { To string From string Subject string + Template string Data any - TextTemplate string - HTMLTemplate string } type Sender struct { @@ -24,5 +24,6 @@ type Router struct { redis_client *redis.Client smtp_client *mail.Client ctx context.Context + } diff --git a/config/settings.go b/config/settings.go index 5c2da54..21e9a20 100644 --- a/config/settings.go +++ b/config/settings.go @@ -28,6 +28,7 @@ type config struct { XMailer string UserAgent string RedisQueue string + Templates string } } diff --git a/config_example.json b/config_example.json index 8cb528e..8d6fd1a 100644 --- a/config_example.json +++ b/config_example.json @@ -19,6 +19,7 @@ "Port": 1025, "XMailer": "nunya-business", "UserAgent": "nunya-business", - "RedisQueue": "email" + "RedisQueue": "email", + "Templates": "emails" } } diff --git a/emails/signup.html b/emails/signup.html deleted file mode 100644 index d3aadde..0000000 --- a/emails/signup.html +++ /dev/null @@ -1,3 +0,0 @@ -

Welcome!

- -

You signed up!

diff --git a/emails/signup.md b/emails/signup.md new file mode 100644 index 0000000..e493761 --- /dev/null +++ b/emails/signup.md @@ -0,0 +1,4 @@ +Welcome +======= + +Welcome to my website! diff --git a/features/email/api.go b/features/email/api.go index b3bc87e..81751ab 100644 --- a/features/email/api.go +++ b/features/email/api.go @@ -11,8 +11,7 @@ func PostApiEmailSend(c *fiber.Ctx) error { To: c.FormValue("To"), From: c.FormValue("From"), Subject: c.FormValue("Subject"), - TextTemplate: c.FormValue("Template"), - HTMLTemplate: c.FormValue("Template"), + Template: c.FormValue("Template"), }) return c.Redirect("/email/") diff --git a/tools/cmd/qmgr/main.go b/tools/cmd/qmgr/main.go index de39b81..ef205cb 100644 --- a/tools/cmd/qmgr/main.go +++ b/tools/cmd/qmgr/main.go @@ -15,8 +15,7 @@ func main() { To: "tina.recip@example.com", From: "toni.sender@example.com", Subject: "This is my first mail.", - TextTemplate: "signup", - HTMLTemplate: "signup", + Template: "signup", } sender := email.NewSender(ctx)