Files
kjol/snailmail/snailmail.go

82 lines
2.0 KiB
Go

// package snailmail sends email through a pluggable provider (SMTP or Cloudflare).
// The active provider and its credentials are injected via Configure(Settings),
// so the framework never reads application config. Branded message composition
// (templates, logos, copy) stays app-side: apps build an Email and call SendMail.
package snailmail
import (
"bytes"
"log"
"strings"
)
const (
TYPE_TEXT = iota
TYPE_HTML
)
// Email is a composed message ready to send. Body holds the already-rendered
// text or HTML.
type Email struct {
Recipients []string
Subject string
Body *bytes.Buffer
}
// SMTPSettings holds credentials for the SMTP provider.
type SMTPSettings struct {
Server string
Port string
Username string
Password string
DisplayFrom string
RequireAuth bool
}
// CloudflareSettings holds credentials for the Cloudflare email provider.
type CloudflareSettings struct {
AccountID string
APIToken string
FromAddress string
}
// Settings selects and configures the active email provider. Provider is "smtp"
// (default) or "cloudflare".
type Settings struct {
Provider string
SMTP SMTPSettings
Cloudflare CloudflareSettings
}
type sender interface {
Send(message Email, mailtype int) error
}
var (
settings Settings
activeSender sender
)
// Configure stores the provider credentials and selects the active provider.
// Apps call this once at startup with values from their own config.
func Configure(s Settings) {
settings = s
switch strings.ToLower(strings.TrimSpace(s.Provider)) {
case "cloudflare":
activeSender = &cloudflareSender{}
log.Println("mailer: using Cloudflare email provider")
default:
activeSender = &smtpSender{}
log.Println("mailer: using SMTP email provider")
}
}
// SendMail sends message using the configured provider (defaulting to SMTP if
// Configure was never called).
func SendMail(message Email, mailtype int) error {
if activeSender == nil {
activeSender = &smtpSender{}
}
return activeSender.Send(message, mailtype)
}