mailer

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 6 Imported by: 0

README

mailer

import "github.com/brpaz/lib-go/mailer"

Package mailer provides a Mailer abstraction for sending email, plus implementations for common scenarios.

Sending mail

Build a Message and pass it to Send:

err := m.Send(ctx, mailer.Message{
    From:    "noreply@example.com",
    To:      []string{user.Email},
    Subject: "Welcome!",
    Body:    "<p>Thanks for signing up.</p>",
    HTML:    true,
})
Implementations

SMTP sends mail through an SMTP server using the standard library:

auth := smtp.PlainAuth("", "user", "pass", "smtp.example.com")
m    := mailer.NewSMTP("smtp.example.com:587", auth)
Testing

Pass Noop when a component needs a Mailer but the test doesn't care about email — every Send is discarded:

svc := NewSignupService(mailer.Noop{})

Pass InMemory to assert which messages a service sent, without wiring a real transport:

m   := mailer.NewInMemory()
svc := NewSignupService(m)

_ = svc.Register(ctx, user)
assert.Equal(t, []mailer.Message{
    {From: "noreply@example.com", To: []string{user.Email}, Subject: "Welcome!"},
}, m.Sent())
Swapping the implementation

Code should depend on the Mailer interface rather than a concrete type. This allows swapping SMTP for a transactional email provider's API (e.g. Postmark, Resend, SES) at the wiring layer without touching the rest of the codebase.

Index

Variables

ErrNoRecipients is returned by Send when the message has no recipients.

var ErrNoRecipients = errors.New("mailer: message has no recipients")

type InMemory

InMemory records every sent message instead of delivering it. Use it in tests to assert which emails a service sent, without wiring a real transport. Safe for concurrent use.

type InMemory struct {
    // contains filtered or unexported fields
}

func NewInMemory
func NewInMemory() *InMemory

NewInMemory creates an empty InMemory mailer.

func (*InMemory) Send
func (m *InMemory) Send(_ context.Context, msg Message) error

Send records msg and returns nil.

func (*InMemory) Sent
func (m *InMemory) Sent() []Message

Sent returns a copy of every message recorded so far, in send order.

type Mailer

Mailer sends email messages.

Implementations can talk to an SMTP server (like SMTP) or a transactional email provider's API (e.g. Postmark, Resend, SES) by providing a different implementation at the wiring layer.

type Mailer interface {
    // Send delivers msg. It returns an error if the message could not be
    // handed off to the underlying transport.
    Send(ctx context.Context, msg Message) error
}

type Message

Message is an email to be sent.

type Message struct {
    // From is the sender address.
    From string

    // To lists the recipient addresses. At least one is required.
    To  []string

    // Subject is the email subject line.
    Subject string

    // Body is the email content. Its format is determined by HTML.
    Body string

    // HTML indicates whether Body is HTML (true) or plain text (false).
    HTML bool
}

type Noop

Noop is a Mailer that discards every message. Use it as a default when email sending is disabled or irrelevant to the code under test.

type Noop struct{}

func NewNoop
func NewNoop() Noop

NewNoop returns a ready-to-use Noop mailer.

func (Noop) Send
func (Noop) Send(_ context.Context, _ Message) error

Send does nothing and returns nil.

type SMTP

SMTP is a Mailer that sends mail through an SMTP server using the standard library's net/smtp package.

type SMTP struct {
    // contains filtered or unexported fields
}

func NewSMTP
func NewSMTP(addr string, auth smtp.Auth) *SMTP

NewSMTP returns a SMTP mailer that dials addr (host:port) and authenticates with auth. Pass nil for auth to skip authentication.

func (*SMTP) Send
func (m *SMTP) Send(ctx context.Context, msg Message) error

Send implements Mailer. It builds a minimal MIME message from msg and hands it off via [smtp.SendMail].

Generated by gomarkdoc

Documentation

Overview

Package mailer provides a Mailer abstraction for sending email, plus implementations for common scenarios.

Sending mail

Build a Message and pass it to Send:

err := m.Send(ctx, mailer.Message{
    From:    "noreply@example.com",
    To:      []string{user.Email},
    Subject: "Welcome!",
    Body:    "<p>Thanks for signing up.</p>",
    HTML:    true,
})

Implementations

SMTP sends mail through an SMTP server using the standard library:

auth := smtp.PlainAuth("", "user", "pass", "smtp.example.com")
m    := mailer.NewSMTP("smtp.example.com:587", auth)

Testing

Pass Noop when a component needs a Mailer but the test doesn't care about email — every Send is discarded:

svc := NewSignupService(mailer.Noop{})

Pass InMemory to assert which messages a service sent, without wiring a real transport:

m   := mailer.NewInMemory()
svc := NewSignupService(m)

_ = svc.Register(ctx, user)
assert.Equal(t, []mailer.Message{
    {From: "noreply@example.com", To: []string{user.Email}, Subject: "Welcome!"},
}, m.Sent())

Swapping the implementation

Code should depend on the Mailer interface rather than a concrete type. This allows swapping SMTP for a transactional email provider's API (e.g. Postmark, Resend, SES) at the wiring layer without touching the rest of the codebase.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoRecipients = errors.New("mailer: message has no recipients")

ErrNoRecipients is returned by Send when the message has no recipients.

Functions

This section is empty.

Types

type InMemory

type InMemory struct {
	// contains filtered or unexported fields
}

InMemory records every sent message instead of delivering it. Use it in tests to assert which emails a service sent, without wiring a real transport. Safe for concurrent use.

func NewInMemory

func NewInMemory() *InMemory

NewInMemory creates an empty InMemory mailer.

func (*InMemory) Send

func (m *InMemory) Send(_ context.Context, msg Message) error

Send records msg and returns nil.

func (*InMemory) Sent

func (m *InMemory) Sent() []Message

Sent returns a copy of every message recorded so far, in send order.

type Mailer

type Mailer interface {
	// Send delivers msg. It returns an error if the message could not be
	// handed off to the underlying transport.
	Send(ctx context.Context, msg Message) error
}

Mailer sends email messages.

Implementations can talk to an SMTP server (like SMTP) or a transactional email provider's API (e.g. Postmark, Resend, SES) by providing a different implementation at the wiring layer.

type Message

type Message struct {
	// From is the sender address.
	From string

	// To lists the recipient addresses. At least one is required.
	To []string

	// Subject is the email subject line.
	Subject string

	// Body is the email content. Its format is determined by HTML.
	Body string

	// HTML indicates whether Body is HTML (true) or plain text (false).
	HTML bool
}

Message is an email to be sent.

type Noop

type Noop struct{}

Noop is a Mailer that discards every message. Use it as a default when email sending is disabled or irrelevant to the code under test.

func NewNoop

func NewNoop() Noop

NewNoop returns a ready-to-use Noop mailer.

func (Noop) Send

func (Noop) Send(_ context.Context, _ Message) error

Send does nothing and returns nil.

type SMTP

type SMTP struct {
	// contains filtered or unexported fields
}

SMTP is a Mailer that sends mail through an SMTP server using the standard library's net/smtp package.

func NewSMTP

func NewSMTP(addr string, auth smtp.Auth) *SMTP

NewSMTP returns a SMTP mailer that dials addr (host:port) and authenticates with auth. Pass nil for auth to skip authentication.

func (*SMTP) Send

func (m *SMTP) Send(ctx context.Context, msg Message) error

Send implements Mailer. It builds a minimal MIME message from msg and hands it off via smtp.SendMail.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL