Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Mail Preview Laravel Package

spatie/laravel-mail-preview

A Laravel mail transport that previews sent mail locally. Swap your mailer's transport to 'preview' and a small overlay appears whenever a mail is sent, linking to the rendered message. Add the middleware to the web group to enable it. Handy for testing emails in local environments.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. spatie/laravel-mail-preview is a thin, non-invasive add-on that plugs into three well-defined Laravel extension points: the mail transport registry (config/mail.php), the HTTP middleware stack, and a route macro (Route::mailPreview()). It does not wrap or patch the framework, and it ships an opt-out config (enabled, storage_path, maximum_lifetime_in_seconds, show_link_to_preview, popup_timeout_in_seconds) that lets a team scope its blast radius.

The package delivers two distinct capabilities, and a TPM should evaluate them separately:

  1. Developer preview loop — every sent mail is persisted as .html and .eml, with an in-browser overlay linking to the artifact. This is a developer-experience win for teams iterating on transactional templates (onboarding, invoices, password resets) where Mailtrap/Mailhog adds a round trip.
  2. Test-time content assertions — the SentMails facade (assertLastContains, assertSent, assertTimesSent, assertNotSent, plus per-message assertSubjectContains/assertTo/assertContains) closes a real gap: Mail::fake does not render the mailable, so content assertions are otherwise impossible without booting the renderer manually. This is the more durable, more defensible reason to adopt, because it produces CI-enforced coverage rather than local convenience.

Integration feasibility. Low effort. composer require, one transport string change, one middleware entry in the web group, one route macro, optional vendor:publish for config and views. A competent Laravel engineer can validate it in under a day; org-wide rollout is a documentation exercise, not an engineering one.

Technical risk. Several items warrant scrutiny:

  • Documentation drift. The README still describes MailStoredEvent as carrying a Swift_Mime_SimpleMessage. Laravel 9+ moved to Symfony Mailer, and the package dropped Laravel 8 in v6. Any consumer writing an event listener against the documented type is working from stale docs — verify the actual payload before building on it.
  • Middleware placement. Guidance says to add AddMailPreviewOverlayToResponse to the global web group. An unconditional entry in shared kernel code is a production incident waiting on a config mistake. Prefer environment-conditional registration in a service provider.
  • Silent mail loss. The preview transport replaces a real transport. If enabled is true outside debug, mail is written to local disk and never delivered, with no error. This is the single highest-severity failure mode.
  • PII on disk. Filenames embed the recipient address and subject; bodies contain full message content. Storage path and retention (maximum_lifetime_in_seconds, default 60s for cleanup) must be treated as a data-handling control, not a convenience.
  • Ecosystem signal. 0 dependents and ~1.3k stars indicate a well-known but shallowly-integrated utility. Low community validation; expect to be your own integration test on non-mainstream configurations.

Key questions.

  • Is this being adopted for the preview overlay, the assertion API, or both? (Different ROI, different risk.)
  • Does the current Laravel version in our services match what the changelog confirms (9/10/11)? Laravel 12 support is not evidenced.
  • Who owns guaranteeing the transport is never active outside local/CI?
  • Do we already have a mail-testing convention (snapshot tests, Mailpit in CI)? If so, are we adding a second mechanism?
  • What is our policy on writing rendered mail bodies to developer workstations?

Integration Approach

Stack fit. Native to Laravel applications on the 9–11 line; the package is a Laravel service provider plus a transport, so it assumes the framework's mail manager, HTTP kernel, and Blade view layer. It is not applicable to Lumen, Symfony-only services, or non-PHP mail pipelines. For a Laravel-dominant estate it fits without architectural negotiation.

Migration path. Two entry points:

  • From themsaid/laravel-mail-preview — the package was transferred from Mohamed Said; an UPGRADING.md exists, and v4.0.1 is explicitly the first release post-transfer, with v5.0.0 a rewrite "to modern standards." Treat this as a namespace and config-shape migration, not a drop-in.
  • From nothing / from Mailpit or Mailtrap — do not rip out the existing local mail catcher. Run the package alongside it during evaluation; the preview artifacts are additive and the two approaches answer different questions (visual fidelity vs. inbox-level delivery behavior).

Compatibility. Pin to a minor and let Renovate/Dependabot surface upgrades; churn is low (roughly one release per Laravel major plus small fixes). Confirm PHP version support in composer.json before committing. Watch for the v9→v10→v11 pattern where each Laravel major arrives as a dedicated compatibility release — plan a small quarterly upgrade slot rather than assuming silent forward compatibility.

Sequencing.

  1. Pilot (week 1) — one Laravel service, one developer, require --dev, transport swap behind APP_DEBUG, middleware registered conditionally rather than unconditionally. Measure: does the overlay survive our actual response types (Inertia, Livewire, JSON)? That is the most likely first breakage.
  2. Assertion pilot (week 2) — add two or three SentMails assertions to an existing mail test suite. This validates the higher-value half of the package before any org-wide recommendation.
  3. Standardize (week 3–4) — document as a recommended dev dependency with a copy-paste config block and an explicit "never in staging/production" rule; add the enabled env gate to the standard service template.
  4. Defer — CI-level integration until step 2 shows assertion value; do not couple the preview feature's adoption to the test feature's rollout.

Operational Impact

Maintenance. Vendor-maintained by Spatie under MIT, with an active changelog and a clear maintainer handoff history. Surface area is small — a transport, a middleware, a route macro, a facade, and two Blade views — so the internal cost is essentially "keep the version pinned and upgrade annually." The published views and config create a fork risk if anyone customizes them; discourage view publishing unless a concrete styling need exists.

Support. Community only: GitHub issues, no SLA, no commercial backing tier. Acceptable for a developer-tooling dependency; unacceptable as a load-bearing component of a customer-facing path. Escalation for a blocked engineer is "pin to a prior version and work around," which must be acceptable to the team.

Scaling. Non-issue by design — it is a per-workstation and per-CI concern. The two scaling-adjacent concerns are (a) disk growth on developer machines and build agents if cleanup is disabled or maximum_lifetime_in_seconds is raised, and (b) concurrency on shared CI runners if multiple jobs write to the same storage_path. Both are configuration problems, not package limitations.

Failure modes (ranked by severity):

  1. Production activation — preview transport live with enabled true; mail silently discarded. Mitigation: hard environment guard, not just APP_DEBUG; a startup assertion or config test that fails loudly.
  2. Overlay injected into unintended responses — global web middleware appending markup to JSON, streaming, or file-download responses. Mitigation: conditional middleware registration; smoke-test non-HTML endpoints during pilot.
  3. Sensitive content persisted — recipient addresses in filenames, full bodies on disk, longer-than-intended retention. Mitigation: default retention, gitignore the storage path, treat as a data-handling item in the adoption checklist.
  4. Transport override breaks adjacent mail configuration — v6.0.2 fixed a parent-constructor issue and v6.1.4 addressed mail-manager service ordering; these are recent, real defects in exactly the area most likely to cause subtle misbehavior. Mitigation: verify non-preview mailers still work after install.
  5. Route collision or exposure — /spatie-mail-preview publicly reachable on a misconfigured staging host, exposing captured mail. Mitigation: environment gate plus, where possible, network-level restriction.

Ramp-up. Very low. A Laravel developer is productive in under an hour from the README; the assertion API is self-documenting and follows familiar Mail::fake idioms. There is no training program required — one internal README page and a standard config snippet suffice. The real ramp-up cost is organizational discipline around the environment gate, which should be encoded in the service template rather than in documentation people may not read.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
alesima/laravel-azure-service-bus
tomshaw/shopcart
likyly/laravel
darthsoup/shoppingcart
tdt/core
labyrinthe/connect-php
encore2/laravel-admin2
cboxdk/laravel-console-kit
shapecode/doctrine-dbal-datetimeutc
gilads-otiannoh254/inertia-protocol
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel