template-monorepo/internal/model/notification/provider/email/smtp_sender.go

72 lines
1.7 KiB
Go
Raw Permalink Normal View History

package email
import (
"context"
"fmt"
"github.com/google/uuid"
"gopkg.in/gomail.v2"
)
// SMTPSettings configures an SMTP Sender (ported from app-cloudep-notification-service).
type SMTPSettings struct {
Sort int
Host string
Port int
Username string
Password string
}
// SMTPSender delivers email via SMTP (gomail).
type SMTPSender struct {
name string
sort int
dialer *gomail.Dialer
}
// NewSMTPSender builds an SMTP provider. Host and Port are required.
func NewSMTPSender(cfg SMTPSettings) (*SMTPSender, error) {
if cfg.Host == "" {
return nil, fmt.Errorf("email smtp: host is required")
}
if cfg.Port <= 0 {
return nil, fmt.Errorf("email smtp: port must be positive")
}
return &SMTPSender{
name: "smtp",
sort: cfg.Sort,
dialer: gomail.NewDialer(cfg.Host, cfg.Port, cfg.Username, cfg.Password),
}, nil
}
func (s *SMTPSender) Name() string { return s.name }
func (s *SMTPSender) Sort() int { return s.sort }
func (s *SMTPSender) Send(ctx context.Context, msg *Message) (string, error) {
if err := ctx.Err(); err != nil {
return "", err
}
if msg == nil || len(msg.To) == 0 {
return "", fmt.Errorf("email smtp: message or recipients missing")
}
from := msg.From
if from == "" {
return "", fmt.Errorf("email smtp: from address is required")
}
m := gomail.NewMessage()
m.SetHeader("From", from)
m.SetHeader("To", msg.To...)
m.SetHeader("Subject", msg.Subject)
m.SetBody("text/html", msg.Body)
// gomail does not accept context; honor cancellation before blocking I/O.
if err := ctx.Err(); err != nil {
return "", err
}
if err := s.dialer.DialAndSend(m); err != nil {
return "", fmt.Errorf("email smtp: %w", err)
}
return uuid.NewString(), nil
}