Files
EagleCast/internal/manager/message.go
T
h202-wq 66d9a033c9
publish-github-pages / deploy (push) Waiting to run
EagleCast
2026-07-09 10:03:32 -04:00

108 lines
2.7 KiB
Go

package manager
import (
"bytes"
"fmt"
"source.offmarket.win/aleagle/eaglecast/models"
)
// NewCampaignMessage creates and returns a CampaignMessage that is made available
// to message templates while they're compiled. It represents a message from
// a campaign that's bound to a single Subscriber.
func (m *Manager) NewCampaignMessage(c *models.Campaign, s models.Subscriber) (CampaignMessage, error) {
msg := CampaignMessage{
Campaign: c,
Subscriber: s,
subject: c.Subject,
from: c.FromEmail,
to: s.Email,
unsubURL: fmt.Sprintf(m.cfg.UnsubURL, c.UUID, s.UUID),
}
if err := msg.render(); err != nil {
return msg, err
}
return msg, nil
}
// render takes a Message, executes its pre-compiled Campaign.Tpl
// and applies the resultant bytes to Message.body to be used in messages.
func (m *CampaignMessage) render() error {
out := bytes.Buffer{}
// Render the subject if it's a template.
if m.Campaign.SubjectTpl != nil {
if err := m.Campaign.SubjectTpl.ExecuteTemplate(&out, models.ContentTpl, m); err != nil {
return err
}
m.subject = out.String()
out.Reset()
}
// Compile the main template.
if err := m.Campaign.Tpl.ExecuteTemplate(&out, models.BaseTpl, m); err != nil {
return err
}
m.body = out.Bytes()
// Is there an alt body?
if m.Campaign.ContentType != models.CampaignContentTypePlain && m.Campaign.AltBody.Valid {
if m.Campaign.AltBodyTpl != nil {
b := bytes.Buffer{}
if err := m.Campaign.AltBodyTpl.ExecuteTemplate(&b, models.ContentTpl, m); err != nil {
return err
}
m.altBody = b.Bytes()
} else {
m.altBody = []byte(m.Campaign.AltBody.String)
}
}
// If there are templated headers, compile them.
if m.Campaign.HeaderTpls == nil {
m.headers = m.Campaign.Headers
} else {
hdrOut := bytes.Buffer{}
m.headers = make(models.Headers, len(m.Campaign.Headers))
for i, set := range m.Campaign.Headers {
m.headers[i] = make(map[string]string, len(set))
for hdr, val := range set {
tpl := m.Campaign.HeaderTpls[i][hdr]
if tpl == nil {
m.headers[i][hdr] = val
continue
}
hdrOut.Reset()
if err := tpl.ExecuteTemplate(&hdrOut, models.ContentTpl, m); err != nil {
return fmt.Errorf("error rendering header %q: %v", hdr, err)
}
m.headers[i][hdr] = hdrOut.String()
}
}
}
return nil
}
// Subject returns a copy of the message subject
func (m *CampaignMessage) Subject() string {
return m.subject
}
// Body returns a copy of the message body.
func (m *CampaignMessage) Body() []byte {
out := make([]byte, len(m.body))
copy(out, m.body)
return out
}
// AltBody returns a copy of the message's alt body.
func (m *CampaignMessage) AltBody() []byte {
out := make([]byte, len(m.altBody))
copy(out, m.altBody)
return out
}