mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-06 15:22:47 +01:00
110 lines
2.7 KiB
Go
110 lines
2.7 KiB
Go
package mail
|
|
|
|
import (
|
|
"cmp"
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/wneessen/go-mail"
|
|
|
|
"github.com/SecurityBrewery/catalyst/app/database/sqlc"
|
|
"github.com/SecurityBrewery/catalyst/app/settings"
|
|
)
|
|
|
|
type Mailer struct {
|
|
queries *sqlc.Queries
|
|
}
|
|
|
|
func New(queries *sqlc.Queries) *Mailer {
|
|
return &Mailer{
|
|
queries: queries,
|
|
}
|
|
}
|
|
|
|
func (m *Mailer) Send(ctx context.Context, to, subject, plainTextBody, htmlBody string) error {
|
|
settings, err := settings.Load(ctx, m.queries)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load settings: %w", err)
|
|
}
|
|
|
|
if !settings.SMTP.Enabled {
|
|
return fmt.Errorf("SMTP is not enabled in settings")
|
|
}
|
|
|
|
if settings.SMTP.Host == "" || settings.SMTP.Username == "" || settings.SMTP.Password == "" {
|
|
return fmt.Errorf("SMTP settings are not configured properly: host, username, and password must be set")
|
|
}
|
|
|
|
client, err := mailClient(settings)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create mail client: %w", err)
|
|
}
|
|
|
|
message, err := createMessage(settings, to, subject, plainTextBody, htmlBody)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create mail message: %w", err)
|
|
}
|
|
|
|
if err := client.DialAndSend(message); err != nil {
|
|
return fmt.Errorf("failed to deliver mail: %w", err)
|
|
}
|
|
|
|
slog.InfoContext(ctx, "mail sent successfully", "to", to, "subject", subject)
|
|
|
|
return nil
|
|
}
|
|
|
|
func createMessage(settings *settings.Settings, to string, subject string, plainTextBody, htmlBody string) (*mail.Msg, error) {
|
|
message := mail.NewMsg()
|
|
|
|
if err := message.FromFormat(settings.Meta.SenderName, settings.Meta.SenderAddress); err != nil {
|
|
return nil, fmt.Errorf("failed to set FROM address: %w", err)
|
|
}
|
|
|
|
if err := message.To(to); err != nil {
|
|
return nil, fmt.Errorf("failed to set TO address: %w", err)
|
|
}
|
|
|
|
message.Subject(subject)
|
|
message.SetBodyString(mail.TypeTextPlain, plainTextBody)
|
|
|
|
if htmlBody != "" {
|
|
message.SetBodyString(mail.TypeTextHTML, htmlBody)
|
|
}
|
|
|
|
return message, nil
|
|
}
|
|
|
|
func mailClient(settings *settings.Settings) (*mail.Client, error) {
|
|
var authType mail.SMTPAuthType
|
|
if err := authType.UnmarshalString(cmp.Or(settings.SMTP.AuthMethod, "plain")); err != nil {
|
|
return nil, fmt.Errorf("failed to parse SMTP auth method: %w", err)
|
|
}
|
|
|
|
opts := []mail.Option{
|
|
mail.WithSMTPAuth(authType),
|
|
mail.WithUsername(settings.SMTP.Username),
|
|
mail.WithPassword(settings.SMTP.Password),
|
|
}
|
|
|
|
if settings.SMTP.Port != 0 {
|
|
opts = append(opts, mail.WithPort(settings.SMTP.Port))
|
|
}
|
|
|
|
if settings.SMTP.TLS {
|
|
opts = append(opts, mail.WithSSL())
|
|
}
|
|
|
|
if settings.SMTP.LocalName != "" {
|
|
opts = append(opts, mail.WithHELO(settings.SMTP.LocalName))
|
|
}
|
|
|
|
client, err := mail.NewClient(settings.SMTP.Host, opts...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create new mail delivery client: %w", err)
|
|
}
|
|
|
|
return client, nil
|
|
}
|