Documentation
¶
Overview ¶
Package email is a small, dependency-light email client: a full RFC 5322 envelope, multipart (alternative/mixed/related) rendering, and a middleware hook chain around a pluggable Transport. The default SMTPTransport speaks net/smtp with an optional STARTTLS+auth relay path and a plaintext no-auth path for local catchers.
Neutral interfaces (Transport, Renderer, Sender) keep the implementation (net/smtp, html/template) out of the exported surface, so consumers wrap or depend on the interface without importing those packages.
Example ¶
Example shows the common wiring: an SMTP transport, a Validate+Retry middleware chain, and a template.Renderer, composed into a Sender that delivers a templated message by kind.
It has no "Output:" comment, so `go test` compiles it but does not run it -- SendKind below would otherwise dial the SMTP host from smtp.LoadConfig (a local catcher such as maildev by default), which this package's test suite must not depend on.
package main
import (
"context"
"fmt"
"time"
email "github.com/Bugs5382/go-email"
"github.com/Bugs5382/go-email/smtp"
"github.com/Bugs5382/go-email/template"
)
func main() {
renderer := template.New()
if err := renderer.Register(
"welcome",
"Welcome, {{.Name}}!",
"<p>Hi {{.Name}}, welcome aboard.</p>",
"Hi {{.Name}}, welcome aboard.",
); err != nil {
fmt.Println(err)
return
}
sender := email.New(
smtp.NewSMTPTransport(smtp.LoadConfig()),
email.WithMiddleware(email.Validate(), email.Retry(3, time.Second)),
email.WithRenderer(renderer),
)
ctx := context.Background()
msg := email.Message{
From: "no-reply@example.com",
To: []string{"user@example.com"},
}
if err := sender.SendKind(ctx, "welcome", msg, map[string]any{"Name": "Ada"}); err != nil {
fmt.Println(err)
}
}
Output:
Index ¶
- Variables
- type Attachment
- type BulkOption
- type BulkResult
- type Deduper
- type Encryptor
- type MemDeduper
- type Message
- type Middleware
- type NopDeduper
- type NopRecorder
- type NopSuppressor
- type Option
- type Priority
- type Recipient
- type Recorder
- type Rendered
- type Renderer
- type SendFunc
- type Sender
- type Sensitivity
- type Signer
- type Suppressor
- type TransientError
- type Transport
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoRenderer = errors.New("email: SendKind requires a Renderer (see WithRenderer)")
ErrNoRenderer is returned by SendKind when the Sender was built without WithRenderer.
var ErrSuppressed = errors.New("email: all recipients suppressed")
ErrSuppressed is returned by the Suppress middleware when every recipient (To ∪ Cc ∪ Bcc) has been filtered out as suppressed, so there is no one left to send to. Suppress returns it in place of calling next, giving callers (e.g. SendBulk) a distinguishable, explicit outcome instead of having to infer a skip from an emptied recipient list.
var ErrValidation = errors.New("email: message failed validation")
ErrValidation is returned (wrapped) by Validate when a Message fails envelope validation. Callers can test for it with errors.Is.
Functions ¶
This section is empty.
Types ¶
type Attachment ¶
type Attachment struct {
Filename string
ContentType string
Content []byte
Inline bool
ContentID string
}
Attachment is a single file attached to, or inlined within, a Message. Inline attachments (Inline true) are referenced from HTML bodies via ContentID, e.g. `<img src="cid:ContentID">`.
type BulkOption ¶
type BulkOption func(*bulkConfig)
BulkOption configures a SendBulk call.
func WithListUnsubscribe ¶
func WithListUnsubscribe(url, post string) BulkOption
WithListUnsubscribe sets the List-Unsubscribe and List-Unsubscribe-Post header values applied to every recipient's Message in a bulk send.
func WithThrottle ¶
func WithThrottle(rate time.Duration) BulkOption
WithThrottle paces a bulk send by waiting rate between each recipient's send. A non-positive rate disables throttling (the default).
type BulkResult ¶
BulkResult tallies the outcome of a SendBulk call: how many recipients were actually sent to, how many were skipped (e.g. suppressed), how many failed, and the per-address error for each failure.
type Deduper ¶
type Deduper interface {
// Seen reports whether key has already been marked as sent.
Seen(ctx context.Context, key string) (bool, error)
// Mark records key as sent.
Mark(ctx context.Context, key string) error
}
Deduper decides whether a Message identified by an opaque dedup key has already been sent, and records that a key has now been sent. Consumers derive the key however they see fit (e.g. a template name plus recipient) and place it in Message.Meta["dedup_key"].
type MemDeduper ¶
type MemDeduper struct {
// contains filtered or unexported fields
}
MemDeduper is an in-memory, mutex-guarded Deduper suitable for a single process or for tests. It does not persist across restarts and does not coordinate across processes; long-lived or multi-process deployments should supply their own Deduper backed by shared storage.
func NewMemDeduper ¶
func NewMemDeduper() *MemDeduper
NewMemDeduper returns a ready-to-use MemDeduper.
type Message ¶
type Message struct {
From, EnvelopeFrom string
To, Cc, Bcc []string
ReplyTo, Subject, HTML, Text string
Attachments []Attachment
Headers map[string]string
Priority Priority
Sensitivity Sensitivity
ListUnsubscribe, ListUnsubscribePost string
Meta map[string]any
}
Message is the neutral, transport-agnostic email envelope. It carries no dependency on any concrete transport (e.g. net/smtp) so callers can build and inspect a Message without pulling in an implementation.
func (Message) Bytes ¶
Bytes renders m into RFC 5322 message bytes (headers plus body), ready to be handed to a Transport for delivery. See buildMIME for the MIME structure it produces.
func (Message) Recipients ¶
Recipients returns the full SMTP RCPT TO set: To ∪ Cc ∪ Bcc.
type Middleware ¶
Middleware wraps a SendFunc with additional behavior, returning a new SendFunc that runs that behavior around a call to next.
func Dedupe ¶
func Dedupe(d Deduper) Middleware
Dedupe returns a Middleware that skips sending a Message whose Meta["dedup_key"] has already been marked as seen by d, unless Meta["resend"] is true. Messages without a dedup key always send. On a successful send, the key is marked so future attempts are deduplicated.
func Encrypt ¶
func Encrypt(e Encryptor) Middleware
Encrypt returns a Middleware that calls e.Encrypt on m before next. If e is nil, the returned Middleware is the identity: it calls next unchanged.
func Record ¶
func Record(r Recorder) Middleware
Record returns a Middleware that calls next and then reports the outcome (nil or non-nil) to r, including failures. The original send error (if any) is always returned to the caller, regardless of what r.Record returns.
func Retry ¶
func Retry(attempts int, base time.Duration) Middleware
Retry returns a Middleware that retries next up to attempts times when it fails with a TransientError, using exponential backoff starting at base (base, base*2, base*4, ...) between attempts. Non-transient errors are returned immediately without retrying. The wait between attempts honors ctx cancellation. An attempts value below 1 is treated as 1, so next is always called at least once rather than being silently skipped.
func Sign ¶
func Sign(s Signer) Middleware
Sign returns a Middleware that calls s.Sign on m before next. If s is nil, the returned Middleware is the identity: it calls next unchanged.
func Suppress ¶
func Suppress(s Suppressor) Middleware
Suppress returns a Middleware that removes addresses reported as suppressed by s from To, Cc, and Bcc before calling next. It is typically placed ahead of bulk sends to honor bounce or unsubscribe lists. If filtering leaves no recipient at all, it returns ErrSuppressed without calling next, rather than attempting a send with zero recipients.
func Validate ¶
func Validate() Middleware
Validate returns a Middleware that rejects a Message before it reaches the next stage unless: From is a syntactically valid address, there is at least one recipient (To ∪ Cc ∪ Bcc), and every recipient address is syntactically valid. Failures are reported as ErrValidation (wrapped with details via errors.Is-compatible wrapping).
type NopDeduper ¶
type NopDeduper struct{}
NopDeduper is a Deduper that never remembers anything: every key is reported as unseen, and Mark is a no-op. It is the zero-value default for consumers that do not need deduplication.
type NopRecorder ¶
type NopRecorder struct{}
NopRecorder is a Recorder that discards every outcome. It is the zero-value default for consumers that do not need send auditing.
type NopSuppressor ¶
type NopSuppressor struct{}
NopSuppressor is a Suppressor that never suppresses any address. It is the zero-value default for consumers that do not maintain a suppression list.
func (NopSuppressor) Suppressed ¶
Suppressed always reports false.
type Option ¶
type Option func(*sender)
Option configures a Sender built by New.
func WithMiddleware ¶
func WithMiddleware(mws ...Middleware) Option
WithMiddleware appends mws, in order, to the Sender's middleware chain. mws[0] runs outermost (first), mirroring chain's semantics.
func WithRenderer ¶
WithRenderer sets the Renderer that SendKind uses to resolve a kind and data into a Message body. Without it, SendKind returns an error.
type Priority ¶
type Priority int
Priority is the RFC 2076-family email priority hint (Importance/X-Priority/ Priority headers). The zero value, PriorityNormal, emits no priority headers at all.
type Recipient ¶
Recipient is one target of a bulk send: an address plus the data a Renderer resolves into that recipient's Subject/HTML/Text body.
type Recorder ¶
Recorder observes the outcome of every send attempt, whether it succeeded or failed. It is typically used for audit trails or delivery logs.
type Rendered ¶
type Rendered struct {
Subject, HTML, Text string
}
Rendered is the resolved subject/HTML/text content produced by a Renderer, ready to be assembled into a Message body.
type Renderer ¶
Renderer resolves a subject/HTML/text body for a named kind of content (e.g. a template name) and arbitrary data, returning it ready to be assembled into a Message. No concrete implementation (e.g. html/template) appears in this interface, so callers can depend on Renderer without pulling in one.
type SendFunc ¶
SendFunc sends a single Message. It is the terminal operation that a Middleware chain wraps: the innermost SendFunc typically delegates to a Transport, while each Middleware layer adds a cross-cutting concern (validation, retries, auditing, and so on) around it.
type Sender ¶
type Sender interface {
// Send runs m through the middleware chain and delivers it via the
// underlying Transport.
Send(ctx context.Context, m Message) error
// SendKind resolves kind and data via the configured Renderer into a
// Subject/HTML/Text body, applies it to a copy of m, and sends that
// copy via Send.
SendKind(ctx context.Context, kind string, m Message, data any) error
// SendBulk resolves kind and each Recipient's Data via the configured
// Renderer into a copy of base addressed to that one recipient, and
// sends every copy through the same path Send uses. A per-recipient
// failure or suppression is tallied in the returned BulkResult rather
// than aborting the rest of the batch.
SendBulk(ctx context.Context, kind string, base Message, recipients []Recipient, opts ...BulkOption) (BulkResult, error)
}
Sender is the top-level entry point for delivering mail: it runs a Message through the configured middleware chain to a Transport, optionally resolving its content from a named kind via a Renderer first.
type Sensitivity ¶
type Sensitivity int
Sensitivity is the RFC 5322 Sensitivity header hint. The zero value, SensitivityNormal, emits no Sensitivity header.
const ( SensitivityNormal Sensitivity = iota SensitivityPersonal SensitivityPrivate SensitivityConfidential )
type Suppressor ¶
Suppressor decides whether a given address must never receive mail (e.g. a bounce or unsubscribe list).
type TransientError ¶
type TransientError struct {
Err error
}
TransientError marks an error as transient: safe to retry. Transports and other middleware should wrap retryable failures (e.g. temporary network or SMTP 4xx errors) in a TransientError so that Retry knows to act on them.
func (TransientError) Error ¶
func (e TransientError) Error() string
Error implements the error interface.
func (TransientError) Unwrap ¶
func (e TransientError) Unwrap() error
Unwrap allows errors.Is/errors.As to see through to the wrapped error.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package otel provides an OpenTelemetry email.Middleware: it wraps a Send call in a span plus send counter and duration metrics.
|
Package otel provides an OpenTelemetry email.Middleware: it wraps a Send call in a span plus send counter and duration metrics. |
|
Package template provides a TemplateRenderer, a concrete email.Renderer backed by the standard library's text/template and html/template packages.
|
Package template provides a TemplateRenderer, a concrete email.Renderer backed by the standard library's text/template and html/template packages. |