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 }