package mailer import ( domain "RenewCMS/internal/domain/mail" "RenewCMS/internal/infrastructure/config" "bytes" "embed" "html/template" "log" "gopkg.in/gomail.v2" ) type MailRepository struct { smtp config.SmtpSettings } //go:embed templates/* var mailTemplateFiles embed.FS func NewMailRepository(smtp config.SmtpSettings) *MailRepository { return &MailRepository{smtp: smtp} } const defaultSubject = "RenewCMS | Action required" type subjectProvider interface { Subject() string } func subjectFor(templateName string, data any) string { if provider, ok := data.(subjectProvider); ok { return provider.Subject() } switch templateName { case "verification": return "Verify your RenewCMS account" case "password-reset": return "Reset your RenewCMS password" } return defaultSubject } func (m MailRepository) Render(templateName string, data any) (string, string, error) { subject := subjectFor(templateName, data) tmpl, err := template.ParseFS(mailTemplateFiles, "templates/"+templateName+".html") if err != nil { log.Println("error when template.ParseFS:", err) return subject, "", err } var body bytes.Buffer if err := tmpl.Execute(&body, data); err != nil { log.Println("error when tmpl.Execute:", err) return subject, "", err } return subject, body.String(), nil } func (m MailRepository) Send(receiverAddress string, templateName string, data any) error { login := m.smtp.Login sender := m.smtp.Sender password := m.smtp.Password smtpHost := m.smtp.Host smtpPort := m.smtp.Port d := gomail.NewDialer(smtpHost, smtpPort, login, password) subject, body, err := m.Render(templateName, data) if err != nil { return err } msg := gomail.NewMessage() msg.SetHeaders(map[string][]string{ "From": {"RenewCMS <" + sender + ">"}, "To": {receiverAddress}, "Subject": {subject}, }) msg.SetBody("text/html", body) if err := d.DialAndSend(msg); err != nil { log.Println("error when sending email:", err) return err } return nil } var _ domain.Repository = &MailRepository{}