// Package mail_ses - AWS SES email sender. package mail_ses import ( "context" "fmt" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/sesv2" "github.com/aws/aws-sdk-go-v2/service/sesv2/types" ) type Config struct { Region string // AWS region (e.g., "us-east-1") From string // From address for emails (must be verified in SES) AccessKey string // AWS access key ID (optional, uses default credential chain if empty) SecretKey string // AWS secret access key (optional, uses default credential chain if empty) } type Sender struct { client *sesv2.Client from string } func NewSender(ctx context.Context, sesConfig Config) (*Sender, error) { var cfg aws.Config var err error // If credentials are provided in config, use them; otherwise use default credential chain if sesConfig.AccessKey != "" && sesConfig.SecretKey != "" { cfg, err = config.LoadDefaultConfig(ctx, config.WithRegion(sesConfig.Region), config.WithCredentialsProvider(aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) { return aws.Credentials{ AccessKeyID: sesConfig.AccessKey, SecretAccessKey: sesConfig.SecretKey, }, nil })), ) } else { // Use default credential chain (env vars, ~/.aws/credentials, IAM role, etc.) cfg, err = config.LoadDefaultConfig(ctx, config.WithRegion(sesConfig.Region)) } if err != nil { return nil, fmt.Errorf("loading AWS config: %w", err) } client := sesv2.NewFromConfig(cfg) return &Sender{ client: client, from: sesConfig.From, }, nil } func (s *Sender) Send(ctx context.Context, email, subject, body string) error { input := &sesv2.SendEmailInput{ FromEmailAddress: aws.String(s.from), Destination: &types.Destination{ ToAddresses: []string{email}, }, Content: &types.EmailContent{ Simple: &types.Message{ Subject: &types.Content{ Data: aws.String(subject), Charset: aws.String("UTF-8"), }, Body: &types.Body{ Text: &types.Content{ Data: aws.String(body), Charset: aws.String("UTF-8"), }, }, }, }, } _, err := s.client.SendEmail(ctx, input) if err != nil { return fmt.Errorf("sending email via SES: %w", err) } return nil }