make Mailer an interface

This commit is contained in:
dhax 2025-03-05 15:42:02 +01:00
parent dd2412463b
commit 08c09ffee7
10 changed files with 234 additions and 227 deletions

106
email/mailer.go Normal file
View file

@ -0,0 +1,106 @@
// Package email provides email sending functionality.
package email
import (
"bytes"
"fmt"
"html/template"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/jaytaylor/html2text"
"github.com/vanng822/go-premailer/premailer"
)
var templates *template.Template
type Mailer interface {
Send(Message) error
}
// Message struct holds all parts of a specific email Message.
type Message struct {
From Email
To Email
Subject string
Template string
Content any
html string
text string
}
// parse parses the corrsponding template and content
func (m *Message) parse() error {
buf := new(bytes.Buffer)
if err := templates.ExecuteTemplate(buf, m.Template, m.Content); err != nil {
return err
}
prem, err := premailer.NewPremailerFromString(buf.String(), premailer.NewOptions())
if err != nil {
return err
}
html, err := prem.Transform()
if err != nil {
return err
}
m.html = html
text, err := html2text.FromString(html, html2text.Options{PrettyTables: true})
if err != nil {
return err
}
m.text = text
return nil
}
// Email struct holds email address and recipient name.
type Email struct {
Name string
Address string
}
// NewEmail returns an email address.
func NewEmail(name string, address string) Email {
return Email{
Name: name,
Address: address,
}
}
func parseTemplates() error {
templates = template.New("").Funcs(fMap)
return filepath.Walk("./templates", func(path string, info os.FileInfo, err error) error {
if strings.Contains(path, ".html") {
_, err = templates.ParseFiles(path)
return err
}
return err
})
}
var fMap = template.FuncMap{
"formatAsDate": formatAsDate,
"formatAsDuration": formatAsDuration,
}
func formatAsDate(t time.Time) string {
year, month, day := t.Date()
return fmt.Sprintf("%d.%d.%d", day, month, year)
}
func formatAsDuration(t time.Time) string {
dur := time.Until(t)
hours := int(dur.Hours())
mins := int(dur.Minutes())
v := ""
if hours != 0 {
v += strconv.Itoa(hours) + " hours and "
}
v += strconv.Itoa(mins) + " minutes"
return v
}