package emailing import ( "bytes" "fmt" "html/template" "net/smtp" "github.com/spf13/viper" ) type Mailer struct { TemplatesDir string TemplatesConfig *viper.Viper From string Host string Port int Username string Password string } func NewMailer(templates_dir string, tplcfg *viper.Viper, smtpconfig *viper.Viper) (*Mailer, error) { var ( from = smtpconfig.GetString("from") host = smtpconfig.GetString("host") port = smtpconfig.GetInt("port") username = smtpconfig.GetString("username") password = smtpconfig.GetString("password") ) return &Mailer{ TemplatesDir: templates_dir, TemplatesConfig: tplcfg, From: from, Host: host, Port: port, Username: username, Password: password, }, nil } func (m *Mailer) Send(emailcfg string, to string, data any) error { cfg := m.TemplatesConfig.Sub(emailcfg) subject := cfg.GetString("subject") files := cfg.GetStringSlice("files") auth := smtp.PlainAuth("", m.Username, m.Password, m.Host) var body bytes.Buffer mimeHeaders := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n" body.Write([]byte(fmt.Sprintf("Subject: %s \n%s\n\n", subject, mimeHeaders))) if err := executeTemplate(&body, files, data, m.TemplatesDir); err != nil { return fmt.Errorf("failed executing email template : %w", err) } smtpserver := fmt.Sprintf("%s:%d", m.Host, m.Port) err := smtp.SendMail(smtpserver, auth, m.From, []string{to}, body.Bytes()) if err != nil { return fmt.Errorf("isser sending email: %w", err) } return nil } func executeTemplate(body *bytes.Buffer, files []string, data any, templatesdir string) error { prefixed_files := []string{} for _, f := range files { prefixed_files = append(prefixed_files, templatesdir+f) } t := template.New("email").Funcs( template.FuncMap{ "unescapeHTML": UnescapeHTML, }, ) t = template.Must(t.ParseFiles(prefixed_files...)) if err := t.ExecuteTemplate(body, "main", data); err != nil { return fmt.Errorf("failed execute mail template : %w", err) } return nil } func UnescapeHTML(s string) template.HTML { return template.HTML(s) }