BrainMinder/internal/smtp/mailer.go
2024-08-22 10:13:16 +02:00

103 lines
2.0 KiB
Go

package smtp
import (
"bytes"
"time"
"brainminder.speedtech.it/assets"
"brainminder.speedtech.it/internal/funcs"
"github.com/wneessen/go-mail"
htmlTemplate "html/template"
textTemplate "text/template"
)
const defaultTimeout = 10 * time.Second
type Mailer struct {
client mail.Client
from string
}
func NewMailer(host string, port int, username, password, from string) (*Mailer, error) {
client, err := mail.NewClient(host, mail.WithTimeout(defaultTimeout), mail.WithSMTPAuth(mail.SMTPAuthLogin), mail.WithPort(port), mail.WithUsername(username), mail.WithPassword(password))
if err != nil {
return nil, err
}
mailer := &Mailer{
client: *client,
from: from,
}
return mailer, nil
}
func (m *Mailer) Send(recipient string, data any, patterns ...string) error {
for i := range patterns {
patterns[i] = "emails/" + patterns[i]
}
msg := mail.NewMsg()
err := msg.To(recipient)
if err != nil {
return err
}
err = msg.From(m.from)
if err != nil {
return err
}
ts, err := textTemplate.New("").Funcs(funcs.TemplateFuncs).ParseFS(assets.EmbeddedFiles, patterns...)
if err != nil {
return err
}
subject := new(bytes.Buffer)
err = ts.ExecuteTemplate(subject, "subject", data)
if err != nil {
return err
}
msg.Subject(subject.String())
plainBody := new(bytes.Buffer)
err = ts.ExecuteTemplate(plainBody, "plainBody", data)
if err != nil {
return err
}
msg.SetBodyString(mail.TypeTextPlain, plainBody.String())
if ts.Lookup("htmlBody") != nil {
ts, err := htmlTemplate.New("").Funcs(funcs.TemplateFuncs).ParseFS(assets.EmbeddedFiles, patterns...)
if err != nil {
return err
}
htmlBody := new(bytes.Buffer)
err = ts.ExecuteTemplate(htmlBody, "htmlBody", data)
if err != nil {
return err
}
msg.AddAlternativeString(mail.TypeTextHTML, htmlBody.String())
}
for i := 1; i <= 3; i++ {
err = m.client.DialAndSend(msg)
if nil == err {
return nil
}
if i != 3 {
time.Sleep(2 * time.Second)
}
}
return err
}