101 lines
2.2 KiB
Go
101 lines
2.2 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 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
|
|
}
|