miniauth/pkg/smtpclient/smtpclient.go
2025-03-14 18:03:21 +01:00

107 lines
2.4 KiB
Go

package smtpclient
import (
"bytes"
"embed"
"fmt"
"html/template"
"strings"
"git.keks.cloud/kekskurse/miniauth/pkg/utils"
"github.com/go-gomail/gomail"
"github.com/rs/zerolog"
)
type SMTPConfig struct {
Server string `env:"SERVER"`
Port int `env:"PORT, default=587"`
Username string `env:"USERNAME"`
Password string `env:"PASSWORD"`
From string `env:"FROM"`
}
type SMTPClient struct {
log zerolog.Logger
config SMTPConfig
}
//go:embed template/*
var templates embed.FS
func (s SMTPClient) SendMail(templateName string, to string, data any) error {
log := s.log.With().Str("templateName", templateName).Str("to", to).Any("data", data).Str("func", "SendMail").Logger()
if to == "error@error.error" {
return ErrCantSendMailToErrorMail
}
if s.config.Server == "test" {
return nil
}
subject, txt, html, err := s.renderTemplates(templateName, data)
if err != nil {
return utils.WrapError(ErrCantRenderTemplate, err, log)
}
m := gomail.NewMessage()
m.SetHeader("From", s.config.From)
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/plain", txt)
m.AddAlternative("text/html", html)
d := gomail.NewDialer(s.config.Server, s.config.Port, s.config.Username, s.config.Password)
err = d.DialAndSend(m)
if err != nil {
return utils.WrapError(ErrCantSendMail, err, log)
}
return nil
}
func NewSMTPClient(c SMTPConfig) SMTPClient {
client := SMTPClient{}
client.config = c
return client
}
func NewDummySMTPClient() SMTPClient {
s := SMTPClient{}
s.config.Server = "test"
return s
}
func (s SMTPClient) renderTemplates(templateName string, data any) (string, string, string, error) {
subject, err := s.renderFile(fmt.Sprintf("%v.subject", templateName), data)
if err != nil {
return "", "", "", err
}
txt, err := s.renderFile(fmt.Sprintf("%v.txt", templateName), data)
if err != nil {
return "", "", "", err
}
html, err := s.renderFile(fmt.Sprintf("%v.html", templateName), data)
if err != nil {
return "", "", "", err
}
return subject, txt, html, nil
}
func (s SMTPClient) renderFile(filename string, data any) (string, error) {
tmpl, err := template.ParseFS(templates, "template/"+filename)
if err != nil {
return "", err
}
var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
if err != nil {
return "", err
}
renderedString := buf.String()
return strings.Trim(renderedString, "\n"), nil
}