VOOZH about

URL: https://deepwiki.com/hypervel/mail/7-message-lifecycle

⇱ Message Lifecycle | hypervel/mail | DeepWiki


Loading...
Menu

Message Lifecycle

This page explains the complete journey of an email message from creation through final delivery or queuing. It covers the preparation pipeline, view rendering, event dispatching, and the decision points that route messages through synchronous or asynchronous sending paths.

For details about the event system and how to listen for lifecycle events, see Event System. For queue-specific configuration and the SendQueuedMailable job implementation, see Queue Integration.


Lifecycle Overview

The message lifecycle consists of five distinct phases that every email passes through, whether sent synchronously or queued for later delivery.

Complete Lifecycle Flow


Sources: src/Mailable.php163-182 src/Mailer.php269-278


Phase 1: Message Creation and Configuration

A message lifecycle begins when application code instantiates a Mailable class. During this phase, the message is configured with recipients, content, and metadata.

Creation Flow


Sources: src/Mailable.php513-622 src/Mailable.php736-788

Configuration Methods

The Mailable class provides fluent methods that populate internal properties used during the preparation phase:

MethodPropertyDescription
to()$toSets recipient addresses
cc()$ccSets carbon copy recipients
bcc()$bccSets blind carbon copy recipients
subject()$subjectSets email subject line
view()$viewSets Blade template path
markdown()$markdownSets Markdown template path
html()$htmlSets raw HTML content
attach()$attachmentsAdds file attachments

Sources: src/Mailable.php48-151


Phase 2: Send Initiation and Queue Detection

When send() is called on a Mailable, the system determines whether to send immediately or queue for later delivery.

Send Entry Point Decision


Sources: src/Mailable.php163-182 src/Mailer.php269-278

Queue Path Execution

When a Mailable implements the ShouldQueue interface, the Mailer.sendMailable() method src/Mailer.php269-278 detects this and immediately calls queue() instead of proceeding with synchronous sending. The queue() method src/Mailable.php187-201 creates a SendQueuedMailable job and pushes it to the queue system.

Sources: src/Mailable.php187-201 src/Mailable.php222-229


Phase 3: Preparation Pipeline

The preparation phase consolidates data from multiple sources into the Mailable instance properties. This occurs via prepareMailableForDelivery() which orchestrates four hydration steps.

Preparation Phase Flow


Sources: src/Mailable.php1340-1353 src/Mailable.php1358-1471

Hydration Methods

Each hydration method checks for the existence of an optional method and, if present, calls it to extract structured data:

Hydration MethodSource MethodHydrated Data
ensureHeadersAreHydrated()headers()Message-Id, References, custom headers
ensureEnvelopeIsHydrated()envelope()from, to, cc, bcc, replyTo, subject, tags, metadata
ensureContentIsHydrated()content()view, html, text, markdown, htmlString, with data
ensureAttachmentsAreHydrated()attachments()Attachment objects

Sources: src/Mailable.php1358-1379 src/Mailable.php1384-1417 src/Mailable.php1422-1453 src/Mailable.php1458-1471


Phase 4: View Building and Message Construction

After preparation, the system builds the views and constructs the final message object that will be passed to the transport layer.

View Building Pipeline


Sources: src/Mailable.php255-280 src/Mailable.php287-295 src/Mailable.php302-317

Message Construction in Mailer

The Mailer.send() method src/Mailer.php215-264 receives the view and data, then constructs a Message object:

  1. Create Message: Instantiate Message with Symfony Email src/Mailer.php425-448
  2. Apply Callback: Execute user-provided closure to configure message src/Mailer.php233-235
  3. Add Content: Render views and add HTML/text parts src/Mailer.php237
  4. Apply Global To: Override recipients if global "to" is set src/Mailer.php242-244

Sources: src/Mailer.php215-264 src/Mailer.php321-334 src/Mailer.php425-448


Phase 5: Event Dispatching and Transport Sending

The final phase involves event dispatching for interception and the actual sending through the transport layer.

Send and Event Flow


Sources: src/Mailer.php249-261 src/Mailer.php453-459 src/Mailer.php464-473 src/Mailer.php478-483

Event Dispatching Details

Two events are dispatched during the send phase:

MessageSending Event

Dispatched by shouldSendMessage() src/Mailer.php464-473 before sending. Listeners can prevent sending by calling dontSend() on the event object. The method returns the result of $event->shouldSend().


MessageSent Event

Dispatched by dispatchSentEvent() src/Mailer.php478-483 after successful sending. This event cannot prevent delivery as the message has already been sent.

Sources: src/Mailer.php464-473 src/Mailer.php478-483


Synchronous vs Asynchronous Paths

The lifecycle diverges at the send initiation phase based on whether the Mailable implements ShouldQueue.

Path Comparison


Sources: src/Mailer.php269-278 src/Mailable.php187-201

Forcing Synchronous Send

The sendNow() method src/Mailer.php283-288 bypasses queue detection and forces synchronous sending even if the Mailable implements ShouldQueue:


Sources: src/Mailer.php283-288


State Transitions and Properties

Throughout the lifecycle, the Mailable instance's properties are populated and transformed.

Property Evolution Table

Lifecycle PhaseProperties SetMethods Involved
CreationConstructor sets public properties__construct()
Configuration$to, $cc, $bcc, $subject, $view, etc.to(), cc(), subject(), view()
BuildCustom properties set by developerbuild()
Headers Hydration$callbacks (for Symfony headers)ensureHeadersAreHydrated()
Envelope Hydration$from, $to, $cc, $bcc, $subject, $tags, $metadataensureEnvelopeIsHydrated()
Content Hydration$view, $html, $textView, $markdown, $viewDataensureContentIsHydrated()
Attachments Hydration$attachments, $rawAttachments, $diskAttachmentsensureAttachmentsAreHydrated()
View Building$assertionableRenderStrings (for testing)buildView(), buildViewData()

Sources: src/Mailable.php48-151 src/Mailable.php1340-1471


Locale Handling

The lifecycle respects locale settings through the Localizable trait src/Mailable.php29 which wraps operations in withLocale().

Locale Application Flow


The send() method src/Mailable.php163-182 wraps its entire execution in withLocale(), ensuring that view rendering and any locale-dependent operations use the correct locale. The locale can be set via:

  1. Explicit call: $mailable->locale('es')
  2. Recipient preference: When to() receives a HasLocalePreference object src/Mailable.php531-533

Sources: src/Mailable.php163-182 src/Mailable.php487-492 src/Mailable.php531-533


Lifecycle Completion

The lifecycle completes with one of three outcomes:

Outcome Types

OutcomeReturn ValueCondition
Sent SuccessfullySentMessage objectSynchronous send completed
QueuednullImplements ShouldQueue or explicitly queued
CancellednullMessageSending event prevented sending

Sources: src/Mailable.php163-182 src/Mailer.php251-264 src/Mailer.php269-278


Error Handling

If an exception occurs during transport sending, it propagates up the call stack. The sendSymfonyMessage() method src/Mailer.php453-459 uses a try-finally block but does not catch exceptions, allowing transport-layer errors to bubble up to application code.

For queued messages, exceptions are handled by the queue system's failure mechanisms, which can retry jobs according to the configured retry policy.

Sources: src/Mailer.php453-459