Skip to main content
Version: 0.3

Mailer

Mailer is the high-level convenience type. It wraps a Sender with helpers for plain text, HTML, templates, and batch sending. The default From address you pass to NewMailer is used whenever an email does not specify its own sender.

Creating a Mailer

sender, err := email.NewSMTPSender(config)
if err != nil {
log.Fatal(err)
}

mailer := email.NewMailer(sender, "no-reply@example.com")
defer mailer.Close() // closes the underlying sender

For senders wrapped in middleware, use NewMailerWithOptions:

mailer := email.NewMailerWithOptions(sender, "no-reply@example.com",
email.WithMiddleware(
email.WithRecovery(),
email.WithLogging(logger),
),
)

Send & SendHTML

For one-off messages, the Send and SendHTML helpers skip the builder and accept (ctx, to, subject, body) directly.

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// Plain text
err := mailer.Send(ctx,
[]string{"alice@example.com", "bob@example.com"},
"Daily report",
"Today's numbers are looking good.",
)

// HTML
err = mailer.SendHTML(ctx,
[]string{"alice@example.com"},
"Welcome!",
"<h1>Welcome to MyApp</h1><p>Click <a href=\"https://example.com\">here</a> to get started.</p>",
)

SendTemplate

Render a registered template with arbitrary data. See Templates for how to register them.

data := map[string]any{
"Name": "Alice",
"VerifyLink": "https://example.com/verify/abc123",
}

err := mailer.SendTemplate(ctx,
[]string{"alice@example.com"},
"welcome",
data,
)

Batch Sending

SendBatch sends many emails concurrently with a bounded worker pool. Failures are aggregated and returned as a single joined error — successful sends still go through.

emails := []*email.Email{
email.NewEmail().SetFrom("no-reply@example.com").AddTo("alice@example.com").
SetSubject("Hi Alice").SetBody("Hello"),
email.NewEmail().SetFrom("no-reply@example.com").AddTo("bob@example.com").
SetSubject("Hi Bob").SetBody("Hello"),
email.NewEmail().SetFrom("no-reply@example.com").AddTo("carol@example.com").
SetSubject("Hi Carol").SetBody("Hello"),
}

// Concurrency limit of 5
if err := mailer.SendBatch(ctx, emails, 5); err != nil {
log.Printf("some sends failed: %v", err)
}

Close

Always defer mailer.Close(). It releases pooled SMTP connections, drains the async queue (if wrapping AsyncSender), and flushes any internal buffers.

mailer := email.NewMailer(sender, config.From)
defer mailer.Close()