package mailgun import ( "context" "time" "github.com/mailgun/mailgun-go/v4" "go.uber.org/zap" ) type mailgunEmailer struct { config MailgunConfigurationProvider logger *zap.Logger Mailgun *mailgun.MailgunImpl } func NewEmailer(config MailgunConfigurationProvider, logger *zap.Logger) Emailer { logger = logger.Named("mailgun-emailer") // Initialize Mailgun client mg := mailgun.NewMailgun(config.GetDomainName(), config.GetAPIKey()) mg.SetAPIBase(config.GetAPIBase()) // Override to support our custom email requirements. logger.Info("✓ Mailgun emailer initialized", zap.String("domain", config.GetDomainName()), zap.String("api_base", config.GetAPIBase())) return &mailgunEmailer{ config: config, logger: logger, Mailgun: mg, } } func (me *mailgunEmailer) Send(ctx context.Context, sender, subject, recipient, body string) error { me.logger.Debug("Sending email", zap.String("sender", sender), zap.String("recipient", recipient), zap.String("subject", subject)) message := me.Mailgun.NewMessage(sender, subject, "", recipient) message.SetHtml(body) ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() // Send the message with a 10 second timeout resp, id, err := me.Mailgun.Send(ctx, message) if err != nil { me.logger.Error("Failed to send email", zap.String("sender", sender), zap.String("recipient", recipient), zap.String("subject", subject), zap.Error(err)) return err } me.logger.Info("Email sent successfully", zap.String("recipient", recipient), zap.String("subject", subject), zap.String("message_id", id), zap.String("response", resp)) return nil } func (me *mailgunEmailer) GetDomainName() string { return me.config.GetDomainName() } func (me *mailgunEmailer) GetSenderEmail() string { return me.config.GetSenderEmail() } func (me *mailgunEmailer) GetBackendDomainName() string { return me.config.GetBackendDomainName() } func (me *mailgunEmailer) GetFrontendDomainName() string { return me.config.GetFrontendDomainName() } func (me *mailgunEmailer) GetMaintenanceEmail() string { return me.config.GetMaintenanceEmail() }