Documentation
¶
Overview ¶
Package mail sends email. A Mailable describes one email (envelope and content); a Mailer renders it and hands the Message to a Transport: SMTP, Resend, log (development) or Array (tests).
type Welcome struct{ User models.User }
func (m Welcome) Envelope() mail.Envelope {
return mail.Envelope{To: []string{m.User.Email}, Subject: "Welcome!"}
}
func (m Welcome) Content() mail.Content { return mail.View("mail/welcome", m) }
err := app.Mailer().Send(ctx, Welcome{User: u})
The app builds its Mailer from MAIL_* variables; Preview renders mailables in the browser during development.
See https://github.com/AlexGalhardo/vukem/blob/main/docs/subsystems.md#mail.
Example ¶
package main
import (
"context"
"fmt"
"github.com/AlexGalhardo/vukem/mail"
)
type Welcome struct{ Email string }
func (m Welcome) Envelope() mail.Envelope {
return mail.Envelope{To: []string{m.Email}, Subject: "Welcome!"}
}
func (m Welcome) Content() mail.Content { return mail.Text("Thanks for signing up.") }
func main() {
// Array keeps messages in memory (tests); apps configure SMTP or
// Resend through MAIL_* variables.
sent := mail.NewArray()
m := mail.New(sent, "Shop <hello@shop.test>", nil)
if err := m.Send(context.Background(), Welcome{Email: "ada@example.com"}); err != nil {
fmt.Println(err)
return
}
msgs := sent.SentTo("ada@example.com")
for i := range msgs {
fmt.Println(msgs[i].From, "|", msgs[i].Subject, "|", msgs[i].Text)
}
}
Output: "Shop" <hello@shop.test> | Welcome! | Thanks for signing up.
Index ¶
- Variables
- func Build(msg *Message) ([]byte, error)
- func Preview(m *Mailer, mailables map[string]Mailable) http.Handler
- type Array
- type Attachable
- type Attachment
- type Content
- type Enqueue
- type Envelope
- type Log
- type Mailable
- type Mailer
- func (m *Mailer) Render(ctx context.Context, mailable Mailable) (*Message, error)
- func (m *Mailer) Send(ctx context.Context, mailable Mailable) error
- func (m *Mailer) SendLater(ctx context.Context, mailable Mailable, opts ...queue.Option) error
- func (m *Mailer) SetEnqueue(fn Enqueue)
- func (m *Mailer) Transport() Transport
- type Message
- type Resend
- type ResendConfig
- type ResendError
- type SMTP
- type SMTPConfig
- type Transport
- type WithAttachmentsdeprecated
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoQueue = errors.New("mail: SendLater needs a queue (use app.Mailer or Mailer.SetEnqueue)")
ErrNoQueue is returned by SendLater on a mailer without an Enqueue.
var ErrNoRecipients = errors.New("mail: no recipients")
ErrNoRecipients is returned for messages without To, Cc or Bcc.
Functions ¶
func Build ¶
Build renders msg as RFC 5322 bytes: multipart/mixed (attachments) over multipart/related (inline parts) over multipart/alternative (text, HTML). Bcc is never written as a header.
func Preview ¶
Preview serves rendered mailables for development: the index lists names, "<name>" shows the HTML part and "<name>?text=1" the text part. Mount it only outside production:
if !app.Config.IsProduction() {
r.Handle("/_mail/", http.StripPrefix("/_mail/", mail.Preview(mailer, map[string]mail.Mailable{...})))
}
Types ¶
type Array ¶
type Array struct {
// contains filtered or unexported fields
}
Array keeps sent messages in memory (tests; vukemtest uses it).
type Attachable ¶ added in v0.21.0
type Attachable interface {
Attachments() []Attachment
}
Attachable is implemented by mailables that attach files.
type Attachment ¶
type Attachment struct {
Filename string
ContentType string
Data []byte
Inline bool
ContentID string
}
Attachment is a file sent with the message; Inline parts are referenced from HTML as cid:<ContentID>.
type Content ¶
type Content struct {
// contains filtered or unexported fields
}
Content is the body: a view (rendered by the Mailer) or literal parts.
type Enqueue ¶ added in v0.24.0
Enqueue stores a rendered message in a queue job that sends it later. The app's mailer (app.Mailer) enqueues on the app queue with the payload encrypted, so mail bodies (reset links, tokens) never sit in the jobs tables in clear text.
type Envelope ¶
type Envelope struct {
From string
To []string
Cc []string
Bcc []string
ReplyTo []string
Subject string
// Tags are provider metadata (Resend tags; X-Tag headers over SMTP).
Tags map[string]string
}
Envelope holds addresses and headers. Addresses accept "Name <a@b.c>".
type Log ¶
Log writes messages to a logger instead of sending them (development). Bodies are logged at debug level only.
type Mailer ¶
type Mailer struct {
// contains filtered or unexported fields
}
Mailer renders mailables and sends them.
func New ¶
New returns a Mailer sending from the default from address through t. views renders View contents (the app's view engine); it may be nil when only literal contents are used.
func (*Mailer) SendLater ¶ added in v0.24.0
SendLater renders mailable now (so rendering errors reach the caller) and sends it from a queue job, retried with the queue's backoff. The message ID stays the same across retries, so providers that deduplicate by it send once. opts select the queue, delay or retries of this mail. With QUEUE_CONNECTION=sync the job runs during the call.
func (*Mailer) SetEnqueue ¶ added in v0.24.0
SetEnqueue sets how SendLater queues messages. Call it before the mailer is used; app.Mailer sets it.
type Message ¶
type Message struct {
// ID identifies the message (Message-ID, Resend idempotency key).
ID string
From string
To []string
Cc []string
Bcc []string
ReplyTo []string
Subject string
HTML string
Text string
Attachments []Attachment
Tags map[string]string
}
Message is a rendered email ready for a Transport.
type Resend ¶
type Resend struct {
// contains filtered or unexported fields
}
Resend sends through the Resend HTTP API. The message ID is the Idempotency-Key, so retries never send twice.
type ResendConfig ¶
type ResendConfig struct {
APIKey config.Secret
// BaseURL defaults to https://api.resend.com (tests use a fake).
BaseURL string
// HTTP is the client (10s timeout by default).
HTTP *http.Client
// MaxRetries for 429 and 5xx responses (default 2).
MaxRetries int
// MaxBackoff caps waits between retries, including Retry-After (default 5s).
MaxBackoff time.Duration
}
ResendConfig configures the Resend transport (https://resend.com).
type ResendError ¶
ResendError is an error answered by the Resend API. It never contains the API key.
func (*ResendError) Error ¶
func (e *ResendError) Error() string
func (*ResendError) Retryable ¶
func (e *ResendError) Retryable() bool
Retryable reports whether the request may succeed later.
type SMTP ¶
type SMTP struct {
// contains filtered or unexported fields
}
SMTP sends through an SMTP server with STARTTLS (or implicit TLS on 465).
type SMTPConfig ¶
type SMTPConfig struct {
Host string
Port int // 587 (STARTTLS, default) or 465 (implicit TLS)
Username string
Password config.Secret
// InsecureSkipTLS sends without TLS (local catchers such as Mailpit
// only); by default STARTTLS is required.
InsecureSkipTLS bool
// Timeout bounds dialing and the whole exchange (default 30s).
Timeout time.Duration
// TLSConfig overrides the TLS settings (tests).
TLSConfig *tls.Config
}
SMTPConfig configures the SMTP transport.
type WithAttachments
deprecated
type WithAttachments = Attachable
WithAttachments is the pre-1.0 name of Attachable; With* names are reserved for options.
Deprecated: use Attachable.