cicadel
Documentation

Email

mail.Message represents an envelope and its text/HTML content. mail.Sender validates messages before dispatching to an explicit mail.Transport. Delivery is synchronous and context-aware. Construction performs no network activity.

go
sender := mail.Sender{Transport: mail.SMTP{
    Address: "smtp.example.com:587",
    Username: smtpUsername,
    Password: smtpPassword,
}}
err := sender.Send(ctx, mail.Message{
    From: "App <app@example.com>",
    To: []string{"recipient@example.com"},
    Subject: "Account invitation",
    Text: "Your account is ready.",
    HTML: "<p>Your account is ready.</p>",
})

Credentials and recipients come from application configuration or trusted data. The account starter wires recovery delivery in project/accounts.go; the authentication guide lists its environment settings.

Ask your agent

text
Read https://cicadel.fauzaanu.com/en/dev/topics/email/index.md.
Add email delivery for [event] using Cicadel mail.Sender.
Read SMTP credentials from secret configuration, send after successful persistence,
and test recipients and message content with an in-memory transport.

Message and MIME contract

Messages support To, Cc, Bcc, ReplyTo, plain text, HTML alternatives, attachments and extension headers. Bcc addresses are used only for the SMTP envelope and never appear in serialized MIME. Message.Bytes() validates and serializes the message with Date, Message-ID, UTF-8 headers, quoted-printable bodies, multipart alternatives and base64 attachments. MIME parts use CRLF and standard line wrapping. The sender mailbox and recipient mailboxes are parsed, and CR/LF/NUL header injection is rejected.

go
message.Attachments = []mail.Attachment{{
    Filename: "report.csv",
    ContentType: "text/csv",
    Data: csvBytes,
}}
message.Headers = map[string]string{"X-Application": "reports"}

Attachment names cannot include path separators. Bytes are application-provided; this API does not read arbitrary filesystem paths. Extra headers accept X-* headers, Message-ID, In-Reply-To and References; they cannot override envelope, MIME or Bcc fields. Duplicate case-insensitive header names are rejected. Callers own attachment size limits and must not mutate messages during a send.

Use mail.RenderComponent(ctx, message, content) to render compiled typed UI into the HTML body; supply message.Text explicitly for a text alternative. Existing mail.Render remains a compatibility helper for separate Go text and escaped HTML templates. Neither helper converts arbitrary user HTML into trusted markup. Email client CSS support differs from browser CSS; tailor email components to the intended email clients.

SMTP and batches

SMTP.Encryption defaults to starttls, requiring STARTTLS and certificate verification. tls supports implicit TLS, commonly port 465. A cloned TLSConfig can supply a private certificate pool; disabling verification is rejected and the minimum TLS version is 1.2. Credentials are sent only after TLS. Explicit plain mode is limited to an actual loopback destination and refuses credentials; it is for local mail capture tools.

The default timeout is 30 seconds for the batch. Context cancellation closes the connection, including while awaiting an SMTP response. Sender.SendMany validates the full input before delivery and reuses one SMTP connection when supported. It returns the number accepted before an error. A failed QUIT after all DATA commands were accepted does not make those messages failed sends. A connection failure during DATA acknowledgement can leave delivery uncertain; the caller owns its retry/idempotency policy. The framework does not silently retry or silently swallow delivery errors.

Development backends

BackendBehavior
mail.CaptureThread-safe in-memory outbox with deep copies on write and read
&mail.Console{Writer: writer}Serialized MIME to an explicit writer, with synchronized writes
mail.File{Directory: path}One mode-0600 .eml file per message in a private directory
mail.Discard{}Explicitly validate without delivery
Custom mail.TransportImplement Send(context.Context, mail.Message) error

Console/file messages include private bodies and reset links. Select them explicitly for development; the accounts starter uses SMTP. Writers, filesystems, credentials and provider accounts remain application-owned. No application email is sent by tests: the SMTP tests use isolated loopback servers with locally created certificates, and account tests inject a capture callback.

mail/delivery_test.go verifies MIME parsing, attachment decoding, Bcc privacy, header rejection, outbox isolation, file permissions, STARTTLS/implicit TLS, connection reuse, partial delivery, failed upgrades and cancellation. Run the package under the race detector alongside the framework CI suite.

↑

Type to search this version.