PHPackages                             spatie/laravel-mail-preview - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. spatie/laravel-mail-preview

ActiveLibrary[Testing &amp; Quality](/categories/testing)

spatie/laravel-mail-preview
===========================

A mail driver to quickly preview mail

6.2.2(2mo ago)1.3k419.3k↑26%804MITPHPPHP ^8.2CI passing

Since Mar 13Pushed 2mo ago21 watchersCompare

[ Source](https://github.com/spatie/laravel-mail-preview)[ Packagist](https://packagist.org/packages/spatie/laravel-mail-preview)[ Docs](https://github.com/themsaid/laravel-preview-mail-driver)[ Fund](https://spatie.be/open-source/support-us)[ GitHub Sponsors](https://github.com/spatie)[ RSS](/packages/spatie-laravel-mail-preview/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (45)Used By (4)

A mail driver to quickly preview mail
=====================================

[](#a-mail-driver-to-quickly-preview-mail)

[![Latest Version on Packagist](https://camo.githubusercontent.com/9453eeab8141dd042685ef736bb87c22b617ddfa7efe0d03048ccd5dc8489dbc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d6d61696c2d707265766965772e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-mail-preview)[![run-tests](https://github.com/spatie/laravel-mail-preview/actions/workflows/run-tests.yml/badge.svg)](https://github.com/spatie/laravel-mail-preview/actions/workflows/run-tests.yml)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Total Downloads](https://camo.githubusercontent.com/ea75c9fe1d9d87ea28cdf0bd28263832fdad22e62d32f9526fda89ddc595bc6f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d6d61696c2d707265766965772e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-mail-preview)

This package can display a small overlay whenever a mail is sent. The overlay contains a link to the mail that was just sent.

[![screenshot](https://github.com/spatie/laravel-mail-preview/raw/main/docs/images/overlay.png?raw=true)](https://github.com/spatie/laravel-mail-preview/blob/main/docs/images/overlay.png?raw=true)

This can be handy when testing out emails in a local environment.

Support us
----------

[](#support-us)

[![](https://camo.githubusercontent.com/986d0877cf9e119c7925893055f158def861634af375abfb509f76ecab049989/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f6c61726176656c2d6d61696c2d707265766965772e6a70673f743d31)](https://spatie.be/github-ad-click/laravel-mail-preview)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-mail-preview
```

### Configuring the mail transport

[](#configuring-the-mail-transport)

This package contains a mail transport called `preview`. We recommend to only use this transport in non-production environments. To use the `preview` transport, change the `mailers.smtp.transport` to `preview` in your `config/mail.php` file:

```
// in config/mail.php

'mailers' => [
    'smtp' => [
        'transport' => 'preview',
        // ...
    ],
    // ...
],
```

### Registering the preview middleware route

[](#registering-the-preview-middleware-route)

The package can display a link to sent mails whenever they are sent. To use this feature, you must add the `Spatie\MailPreview\Http\Middleware\AddMailPreviewOverlayToResponse` middleware to the `web` middleware group in your kernel.

```
// in app/Http/Kernel.php

protected $middlewareGroups = [
    'web' => [
        // other middleware

        \Spatie\MailPreview\Http\Middleware\AddMailPreviewOverlayToResponse::class,
    ],

    // ...
];
```

You must also add the `mailPreview` to your routes file. Typically, the routes file will be located at `routes/web.php`.

```
// in routes/web.php

Route::mailPreview();
```

This will register a route to display sent mails at `/spatie-mail-preview`. To customize the URL, pass the URL you want to the macro.

```
Route::mailPreview('custom-url-where-sent-mails-will-be-shown');
```

### Publishing the config file

[](#publishing-the-config-file)

Optionally, you can publish the config file with:

```
php artisan vendor:publish --provider="Spatie\MailPreview\MailPreviewServiceProvider" --tag="mail-preview-config"
```

This is the content of the config file that will be published at `config/mail-preview.php`:

```
return [
    /*
     * By default, the overlay will only be shown and mail will only be stored
     * when the application is in debug mode.
     */
    'enabled' => env('APP_DEBUG', false),

    /*
     * All mails will be stored in the given directory.
     */
    'storage_path' => storage_path('email-previews'),

    /*
     * This option determines how long generated preview files will be kept.
     */
    'maximum_lifetime_in_seconds' => 60,

    /*
     * When enabled, a link to mail will be added to the response
     * every time a mail is sent.
     */
    'show_link_to_preview' => true,

    /*
     * Determines how long the preview pop up should remain visible.
     *
     * Set this to `false` if the popup should stay visible.
     */
    'popup_timeout_in_seconds' => 8,

    /**
     * Determines the date format used for the file names.
     *
     * The default 'u' stands for microseconds.
     */
    'filename_date_format' => 'u',
];
```

### Publishing the views

[](#publishing-the-views)

Optionally, you can publish the views that render the preview overlay and the mail itself.

```
php artisan vendor:publish --provider="Spatie\MailPreview\MailPreviewServiceProvider" --tag="mail-preview-views"
```

You can modify the views that will be published at `resources/views/vendor/mail-preview` to your liking.

Usage
-----

[](#usage)

Everytime an email is sent, an `.html` and `.eml` file will be saved in the directory specified in the `storage_path` of the `mail-preview` config file. The name includes the first recipient and the subject:

```
1457904864_john_at_example_com_invoice_000234.html
1457904864_john_at_example_com_invoice_000234.eml

```

You can open the `.html` file in a web browser. The `.eml` file in your default email client to have a realistic look of the final output.

### Preview in a web browser

[](#preview-in-a-web-browser)

When you open the `.html` file in a web browser you'll be able to see how your email will look.

At the beginning of the generated file you'll find an HTML comment with all the message info:

```

```

### Events

[](#events)

Whenever a mail is stored on disk, the `Spatie\MailPreview\Events\MailStoredEvent` will be fired. It has three public properties:

- `message`: an instance of `Swift_Mime_SimpleMessage`
- `pathToHtmlVersion`: the path to the html version of the sent mail
- `pathToEmlVersion`: the path to the email version of the sent mail

### Making assertions against sent mails

[](#making-assertions-against-sent-mails)

Currently, using Laravel's `Mail::fake` you cannot make any assertions against the content of a mail, as the using the fake will not render the mail.

The `SentMails` facade provided this package does allow you to make asserts against the content.

This allows you to make assertions on the content of a mail, without having the mailable in scope.

```
// in a test

Artisan::call(CommandThatSendsMail::class);

Spatie\MailPreview\Facades\SentMails::assertLastContains('something in your mail');
```

Let's explain other available assertions method using this mailable as example.

```
namespace App\Mail;

use Illuminate\Mail\Mailable;

class MyNewSongMailable extends Mailable
{
    public function build()
    {
        $this
            ->to('ringo@example.com')
            ->cc('paul@examle.com')
            ->bcc('john@examle.com')
            ->subject('Here comes the sun')
            ->html("It's been a long cold lonely winter");
    }
}
```

In your code you can send that mailable with:

```
Mail::send(new MyNewSongMailable());
```

In your tests you can assert that the mail was sent using the `assertSent` function. You should pass a callable to `assertSent` which will get an instance of `SentMail` to it. Each sent mail will be passed to the callable. If the callable returns `true` the assertions passes.

```
use Spatie\MailPreview\Facades\SentMails;
use \Spatie\MailPreview\SentMails\SentMail;

SentMails::assertSent(fn (SentMail $mail) => $mail->bodyContains('winter')); // will pass
SentMails::assertSent(fn (SentMail $mail) => $mail->bodyContains('spring')); // will not pass
```

You can use as many assertion methods on the `SentMail` as you like.

```
SentMails::assertSent(function (SentMail $mail)  {
    return
        $mail->subjectContains('sun') &&
        $mail->hasTo('ringo@example.com')
        $mail->bodyContains('winter');
```

The `Spatie\MailPreview\Facades\SentMails` has the following assertions methods:

- `assertCount(int $expectedCount)`: assert how many mails were sent
- `assertLastContains(string $expectedSubstring)`: assert that the body of the last sent mail contains a given substring
- `assertSent($findMailCallable, int $expectedCount = 1)`: explained above
- `assertTimesSent(int $expectedCount, Closure $findMail)`
- `assertNotSent(Closure $findMail)`

Additionally, the `Spatie\MailPreview\Facades\SentMails` has these methods:

- `all`: returns an array of sent mails. Each item will be an instance of `sentMail`
- `count()`: returns the amount of mails sent
- `last`: returns an instance of `SentMail` for the last sent mail. If no mail was sent `null` will be returned.
- `lastContains`: returns `true` if the body of the last sent mail contains the given substring
- `timesSent($findMailCallable)`: returns the amount of mails the were sent and that passed the given callable

The `sentMail` class provides these assertions:

- `assertSubjectContains($expectedSubstring)`
- `assertFrom($expectedAddress)`
- `assertTo$expectedAddress)`
- `assertCc($expectedAddress)`
- `assertBcc($expectedAddress)`
- `assertContains($substring)`: will pass if the body of the mail contains the substring

Additionally, `sentMail` contains these methods:

- `subject()`: return the body of a mail
- `to()`: returns all to recipients as an array
- `cc()`: returns all cc recipients as an array
- `bcc()`: returns all bcc recipients as an array
- `body()`: returns the body of a mail
- `subjectContains)`: returns a boolean
- `hasFrom($expectedAddress)`: return a boolean
- `hasTo($expectedAddress)`: return a boolean
- `hasCc($expectedAddress)`: return a boolean
- `hasBcc($expectedAddress)`: return a boolean

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

UPGRADING
---------

[](#upgrading)

Please see [UPGRADING](UPGRADING.md) for what to do to switch over from `themsaid/laravel-mail-preview`, and how to upgrade to newer major versions.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Freek Van der Herten](https://github.com/freekmurze)
- [Mohamed Said](https://github.com/themsaid)
- [All Contributors](../../contributors)

The initial version of this package was created by Mohamed Said, who graciously entrusted this package to us at Spatie.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

71

—

ExcellentBetter than 100% of packages

Maintenance83

Actively maintained with recent releases

Popularity61

Solid adoption and visibility

Community38

Small or concentrated contributor base

Maturity88

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 55.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~84 days

Recently: every ~179 days

Total

44

Last Release

84d ago

Major Versions

v2.1.1 → v3.0.02020-03-05

v3.1.0 → v4.0.02020-09-13

v4.0.0 → 5.0.02021-01-28

5.2.0 → 6.0.02022-01-13

v4.0.1 → 6.2.02024-04-08

PHP version history (5 changes)v1.0.0PHP &gt;=5.5.9

v3.0.0PHP ^7.2.5

v4.0.0PHP ^7.3

5.0.0PHP ^8.0

6.1.0PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (147 commits)")[![themsaid](https://avatars.githubusercontent.com/u/4332182?v=4)](https://github.com/themsaid "themsaid (58 commits)")[![mrk-j](https://avatars.githubusercontent.com/u/1250622?v=4)](https://github.com/mrk-j "mrk-j (10 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (6 commits)")[![tvbeek](https://avatars.githubusercontent.com/u/2026498?v=4)](https://github.com/tvbeek "tvbeek (5 commits)")[![AdrianMrn](https://avatars.githubusercontent.com/u/12762044?v=4)](https://github.com/AdrianMrn "AdrianMrn (4 commits)")[![SudoGetBeer](https://avatars.githubusercontent.com/u/7324694?v=4)](https://github.com/SudoGetBeer "SudoGetBeer (4 commits)")[![rudiedirkx](https://avatars.githubusercontent.com/u/168024?v=4)](https://github.com/rudiedirkx "rudiedirkx (3 commits)")[![stefanzweifel](https://avatars.githubusercontent.com/u/1080923?v=4)](https://github.com/stefanzweifel "stefanzweifel (2 commits)")[![riasvdv](https://avatars.githubusercontent.com/u/3626559?v=4)](https://github.com/riasvdv "riasvdv (2 commits)")[![bjrnblm](https://avatars.githubusercontent.com/u/2300511?v=4)](https://github.com/bjrnblm "bjrnblm (2 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (2 commits)")[![mustafaaloko](https://avatars.githubusercontent.com/u/4721735?v=4)](https://github.com/mustafaaloko "mustafaaloko (2 commits)")[![JayBizzle](https://avatars.githubusercontent.com/u/340752?v=4)](https://github.com/JayBizzle "JayBizzle (1 commits)")[![joelmellon](https://avatars.githubusercontent.com/u/13803216?v=4)](https://github.com/joelmellon "joelmellon (1 commits)")[![chefe](https://avatars.githubusercontent.com/u/1331316?v=4)](https://github.com/chefe "chefe (1 commits)")[![mattsparks](https://avatars.githubusercontent.com/u/1678388?v=4)](https://github.com/mattsparks "mattsparks (1 commits)")[![mikemand](https://avatars.githubusercontent.com/u/745184?v=4)](https://github.com/mikemand "mikemand (1 commits)")[![SamuelNitsche](https://avatars.githubusercontent.com/u/24483576?v=4)](https://github.com/SamuelNitsche "SamuelNitsche (1 commits)")[![spoyntersmith](https://avatars.githubusercontent.com/u/22387308?v=4)](https://github.com/spoyntersmith "spoyntersmith (1 commits)")

---

Tags

laravelmailtestinglaravelmail

### Embed Badge

![Health badge](/badges/spatie-laravel-mail-preview/health.svg)

```
[![Health](https://phpackages.com/badges/spatie-laravel-mail-preview/health.svg)](https://phpackages.com/packages/spatie-laravel-mail-preview)
```

###  Alternatives

[mpociot/laravel-test-factory-helper

Generate Laravel test factories from your existing models

933635.2k2](/packages/mpociot-laravel-test-factory-helper)[christophrumpel/missing-livewire-assertions

This package adds missing livewire test assertions.

149336.0k9](/packages/christophrumpel-missing-livewire-assertions)[encodia/laravel-health-env-vars

Custom check for Spatie's Laravel Health - Ensure every .env variable you need has been set

20143.5k](/packages/encodia-laravel-health-env-vars)[masterro/laravel-mail-viewer

Easily view in browser outgoing emails.

6392.1k](/packages/masterro-laravel-mail-viewer)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
