72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
|
|
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
|
||
|
|
}
|