Failover transport (failover mailer): a composite that tries an ordered list
of child mailers (named under a chain key) and falls through to the next on
failure — returning the first success and reporting failure only when every
child fails. A child that throws is treated as a failure so the chain advances.
MailerManager resolves the child mailers by name and hands the already-built
transports to the composite. A failover mailer with no children throws a
PostalException.
Automatic inline images: the renderer scans the HTML body for <img>
sources and embeds the embeddable ones — data: image URIs (decoded in
memory) and local image file paths (read at render) — rewriting each
reference to a cid: URL and de-duplicating identical sources. Remote
(http(s)://) and existing cid: sources are left untouched, and only files
that sniff as images are read. On by default; disable per message with
Email::$autoEmbedImages = false. Adds Attachment::embedData().
Amazon SES transport (ses mailer): delivers through the official
aws/aws-sdk-php SesV2 client (SigV4 signing and HTTP owned by the SDK).
Sends structured Simple content by default and switches to raw MIME for
attachments/inline images, HTML without an explicit text body, or when
forceRaw is set. Maps Email::metadata() onto SES EmailTags (dropping and
debug-logging tags that break SES's character rules), applies an optional
configurationSet, and returns the SES message id. aws/aws-sdk-php is an
optional dependency (install it with composer require aws/aws-sdk-php).
Email::metadata(key, value) builder for provider tags, mapped by API
transports onto their tagging feature and ignored by the others.
Attachments and inline images: Email::attach() (file by path, read lazily at
render), Email::attachData() (raw bytes), and Email::embedImage() (inline
CID image referenceable from HTML), backed by the Attachment value object. The
renderer nests multipart/mixed (attachments) around multipart/related
(inline images) around the existing multipart/alternative, with base64 parts
chunked at 76 columns and part headers sanitised against filename injection.
Core send pipeline: compose an Email and send it through a transport via
service('mailer'), receiving a SendResult.
Email message builder with from/replyTo/to/cc/bcc/subject/html/text/
header/priority/returnPath (mutable, chainable).
Address value object that parses and renders "Name <email>".
SendResult with ok()/fail()/cancelled() factories.
TransportInterface and the NullTransport implementation.
MailerManager (resolves the default and named mailers from Config\Email via an
extensible transport map, lazily and cached) and a minimal Mailer that clones the
message at the dispatch boundary.
Config\Email configuration and the service('mailer') service.
MessageRenderer that serialises an Email into a raw RFC 5322 / MIME string:
text/plain, or multipart/alternative whenever HTML is present (with an
automatically generated HTML→text fallback when no text body is set). Emits
custom headers, Return-Path/Sender, and non-default X-Priority; applies
RFC 2047 header encoding and quoted-printable body encoding (7-bit clean,
within the 998-octet SMTP limit); strips CR/LF to prevent header injection;
exposes the rendered header set via headers().
LogTransport and the built-in log mailer, which render the message and
write the full MIME to a PSR-3 log channel (default level debug) instead of
delivering it.
Email lifecycle events fired around every send: email.composing (at the
start), email.sending (immediately before the transport — returning false
cancels the send and yields SendResult::cancelled()), and email.sent /
email.failed afterwards (each receiving the Email and SendResult). All
emission is gated behind Config\Email::$fireEvents (default true).
SendmailTransport/MailTransport and the sendmail and mail mailers,
which hand the rendered MIME to a local MTA: sendmail pipes it to the
configured binary (path) with -oi -t, and mail splits it across PHP's
native mail(). Both deliver Bcc via a header the MTA strips, set the
envelope sender (-f) from the return path or From (validated and
shell-escaped), and talk through the SendmailProcess/MailFunction seams
for testing.
LegacyEmailAdapter, a drop-in replacement for CodeIgniter 4's email service.
service('email') now returns the adapter, which exposes the full legacy
fluent API (setFrom/setTo/setCC/setBCC/setSubject/setMessage/
setAltMessage/setMailType/setHeader/setPriority/setWordWrap/
setProtocol/attach/send/printDebugger/batchBCCSend/validation
helpers) on top of the new Email builder and Mailer. Honors the legacy
flat Config\Email keys (protocol, SMTP*, mailPath, mailType,
wordWrap/wrapChars, priority, BCCBatch*, DSN) so existing apps need
no configuration changes. Invalid addresses are swallowed (send() returns
false and never throws). For CI4 parity, Return-Path and Reply-To
default to From, and sends flow through the event pipeline (a
email.sending listener can cancel). See
Legacy Compatibility.
Optional hard word-wrap for the plain-text part: set Email::$wordWrap (and
$wrapChars, default 76) and MessageRenderer wraps at word boundaries,
leaving long space-less tokens (e.g. URLs) intact.
Mailer::fake() and the FakeTransport test double: swaps the bound
service('mailer') for an in-memory recorder (no network, no real transport)
and returns it. Exposes content-matcher assertions — assertSent(),
assertSentTo(), assertNotSent(), assertNothingSent(), assertSentCount()
— and sent() for inspecting the recorded messages. See
Testing Mail.
Mailable, an abstract class-based email definition: compose the message in
build() (which runs lazily at send time) via protected from/to/subject/
html/text helpers, pick a named mailer with transport(), and send() to
route through service('mailer'). Each send tags the message with the
Mailable's class. The make:mailable Spark command scaffolds a class into
app/Mails/ (--force overwrites). FakeTransport::sent() and assertSent()
now also accept a Mailable class-string (with an optional closure filter) so
tests can assert by type. See Mailables.