A mail driver to quickly preview mail

Overview

A mail driver to quickly preview mail

Latest Version on Packagist GitHub Workflow Status Software License Total Downloads

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

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

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

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. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/laravel-mail-preview

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

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\AddMailPreviewPopupToResponse 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

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,
];

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

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

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:

<!--
From:{"[email protected]":"Acme HQ"},
to:{"[email protected]":"Jack Black"},
reply-to:{"[email protected]"},
cc:[{"[email protected]":"Acme Finance"}, {"[email protected]":"Acme Management"}],
bcc:null,
subject:Invoice #000234
-->

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

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('[email protected]')
            ->cc('[email protected]')
            ->bcc('[email protected]')
            ->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('[email protected]')
        $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

Please see CHANGELOG for more information on what has changed recently.

UPGRADING

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

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

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

License

The MIT License (MIT). Please see License File for more information.

Comments
  • Session store not set on request

    Session store not set on request

    in /home/vagrant/mt2magic-com/vendor/laravel/framework/src/Illuminate/Http/Request.php line 859 at Request->session() in /home/vagrant/mt2magic-com/vendor/themsaid/laravel-mail-preview/src/MailPreviewMiddleware.php line 27 at MailPreviewMiddleware->handle(object(Request), object(Closure))

    I keep getting "Session store not set on request"

    opened by zek 8
  • Race condition with css inliner

    Race condition with css inliner

    Not sure whose bug it is, maybe fedeisas/laravel-mail-css-inliner's.

    css inliner's service provider (in register()):

    $this->app->afterResolving('mail.manager', function (MailManager $mailManager) {
        $mailManager->getSwiftMailer()->registerPlugin($this->app->make(CssInlinerPlugin::class));
        return $mailManager;
    });
    

    and mail preview's (in boot()):

    $this->app['mail.manager']->extend('preview', function () {
        return new PreviewTransport(
            $this->app->make('Illuminate\Filesystem\Filesystem'),
            $this->app['config']['mailpreview.path'],
            $this->app['config']['mailpreview.maximum_lifetime']
        );
    });
    

    So mail preview is directly accessing (and building) mail.manager, which immeditately triggers css inliner's afterResolving, which triggers immediately triggers createTransport(), with a transport preview that doesn't exist yet, because mail preview's extend() hasn't even run yet.

    Moving mail preview's extend() into a afterResolving('mail.manager', ...) doesn't help, because when the mail manager is finally created (not on every request, just when sending mail) the same race condition happens.

    This wasn't a problem with css inliner 2.2 + themsaid/laravel-mail-preview. Maybe because it was a mailer then, not a transport. No idea how to fix this. Typical DI race condition.

    opened by rudiedirkx 6
  • Ray in controller

    Ray in controller

    Hi There,

    In the following line of code, and the one after that there are calls to the "ray" function, but that function is not available. link to code where issue occurs

    I just clean installed this package into my project (PHP8/L8) and got the following error:

    Error

    Call to undefined function Spatie\MailPreview\Http\Controllers\ray()
    https://standaard-cms-v3.test/spatie-mail-preview?file_type=eml&mail_preview_file_name=969172_subject
    
    opened by m-bosch 5
  • Issue with EncryptCookies middleware, session not forgotten

    Issue with EncryptCookies middleware, session not forgotten

    Steps to reproduce:

    1. laravel new mail-preview-test
    2. composer require themsaid/laravel-mail-preview
    3. Create a new MailPreviewController with the following contents:
    <?php
    
    namespace App\Http\Controllers;
    
    use Mail;
    
    class MailPreviewController extends Controller
    {
        public function send()
        {
            Mail::raw('foo', function ($message) {
                $message->to('[email protected]');
            });
    
            var_dump(session()->all());
    
            return 'mail sent';
        }
        public function preview()
        {
            var_dump(session()->all());
    
            return '</body>';
        }
    }
    
    1. Change web.php to:
    <?php
    
    Route::get('/', 'MailPreviewController@send');
    Route::get('/preview', 'MailPreviewController@preview');
    
    1. Visit http://mail-preview-test.test/
    2. Visit http://mail-preview-test.test/preview
    3. See that middleware to unset session is not working correctly, the preview link is visible after refreshing

    Demo repository: https://github.com/mrk-j/laravel-mail-preview-bug-example

    opened by mrk-j 4
  • Move notification template into view

    Move notification template into view

    Move notification template into view so that it can be published and customised 🎉

    @themsaid given both mailcatcher and mailtrap have inexplicably stopped working for me – this package made me very happy 😀 thanks!

    opened by stevelacey 4
  • Add mail.preview config to allow simpler conditional enabling, open door to other enhancments.

    Add mail.preview config to allow simpler conditional enabling, open door to other enhancments.

    Would you consider a pull request to change the logic of laravel-mail-preview/src/MailProvider.php to call $this->registerPreviewSwiftMailer() if either the current condition is met or $this->app['config']['mail.preview'] == true?

    The rationale is that by providing a config key which can enable mail previews without replacing the mail driver, (1) it becomes simpler to condition mail previews upon the environment, APP_DEBUG value, or similar (certainly possible as is, but more cumbersome), and (2) you open the door to enhancements akin to that in #7 (currently closed, I realize).

    I'll provide the PR, just wanted to confirm it would be well received first. Thanks!

    opened by coderabbi 4
  • Add the option to configure the popup timeout (or disable it)

    Add the option to configure the popup timeout (or disable it)

    I added a new config value for the timeout. If it is less then 1 it will disable the timeout so it stays on the screen.

    This will close https://github.com/themsaid/laravel-mail-preview/issues/24

    opened by tvbeek 3
  • L5.4 supported yet?

    L5.4 supported yet?

    Just wondering if this has full L5.4 support yet? I've installed it in my L5.4 project and although there are no apparent errors, its not creating the html files.

    opened by Bulmer 3
  • Open directly in the browser?

    Open directly in the browser?

    How about opening the HTML files that are sent directly in the default browser?

    I believe the letter_opener gem for Rails does this - would be very handy.

    opened by franzliedke 3
  • ValueError: Path cannot be empty

    ValueError: Path cannot be empty

    Hi there!

    Description

    I tried to preview some mails on my local environment, and I've got this error when I tried to see previews on the package's route.

    https://flareapp.io/share/x7Xk26OP#F37

    I looked on Google and I found the same issue when using Laragon. It was something with tmp directory. Unfortunately, I don't use Laragon and those solutions were not solving my problem. I use Valet.

    https://laracasts.com/discuss/channels/laravel/error-valueerror-path-cannot-be-empty-in-file

    Information

    Laravel Version: 9.24.0
    PHP Version: 8.1.10
    Composer Version: 2.4.1

    Thank you!

    opened by alexmanase 2
  • Fix HTML preview for Laravel 9

    Fix HTML preview for Laravel 9

    Hi,

    The HTML preview was broken in Laravel 9. We need to convert the SentMessage instance back to an Email instance so we can call the getHtmlBody() method. The body of SentMessage contains an encoded form of the e-mail.

    This PR fixes this issue.

    opened by mrk-j 2
Releases(6.0.4)
Owner
Spatie
We create open source, digital products and courses for the developer community
Spatie
Mandrill mail driver for Laravel for version 6+

Laravel Mandrill Driver This package re-enables Mandrill driver functionality using the Mail facade in Laravel 6+. To install the package in your proj

Eng Hasan Hajjar 2 Sep 30, 2022
Provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice

WP PHPMailer provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

Itineris Limited 61 Dec 6, 2022
A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address

A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address Mail spf checker A Laravel package to c

Dieter Coopman 110 Dec 16, 2022
Queue, preview and and send emails stored in the database.

Codeigniter4 email queue Queue, preview and and send emails stored in the database. This package provides an interface for creating emails on the fly

null 3 Apr 12, 2022
Bounce Mail Handler for PHP | This is a "reboot" of PHPMailer-BMH from WorxWare.

PHP 7.0+ Support Composer & PSR-0 Support PHPUnit testing via Travis CI (TODO: more tests needed) PHP-Quality testing via SensioLabsInsight (TODO: mor

Lars Moelleken 43 Jan 7, 2023
:envelope: E-Mail Address Validator (syntax, dns, trash, typo)

✉️ E-Mail Address Validator for PHP Warning The best way to validate an e-mail address is still to send a duplicate opt-in-mail, when the user clicks

Lars Moelleken 41 Dec 25, 2022
Mail sending module for Mezzio and Laminas MVC with support for file attachment and template email composition

This module provides an easy and flexible way to send emails from Mezzio and Laminas MVC applications (formerly known as Zend Expressive and Zend MVC). It allows you to pre-configure emails and transports, and then send those emails at runtime.

null 82 Jan 16, 2022
Laravel Mail Credentials switcher for Budget Laravel Applications

Laravel Mail Switcher Laravel Mail Credentials Switcher is a library which helps you to: Manage your Mail Service Credentials Configure the Laravel's

(Seth) Phat Tran 34 Dec 24, 2022
PostfixAdmin - web based virtual user administration interface for Postfix mail servers

PostfixAdmin An open source, web based interface for managing domains/mailboxes/aliases etc on a Postfix based mail server.

PostfixAdmin 755 Jan 3, 2023
💌 Mail app for Nextcloud

Nextcloud Mail ?? A mail app for Nextcloud Why is this so awesome? ?? Integration with other Nextcloud apps! Currently Contacts, Calendar & Files – mo

Nextcloud 684 Dec 26, 2022
Crud PHP 8 com Form E-mail

Crud com PHP 8 PDO Login - Cadastro de Usuários - Edição - Deleção - Adição | Formulário envio de e-mail Para rodar o Crud é preciso instalar um servi

Isaias Oliveira 4 Nov 16, 2021
Mail Web is a Laravel package which catches emails locally for debugging

Mail Web is a Laravel package which catches emails locally for debugging Installation Use the package manager composer to install Mail Web. composer r

Appoly 64 Dec 24, 2022
Simple mail sending by PHPMailer and Create your local system.

Simple mail sending by PHPMailer and Create your local system. Send mail zero of cost and also send Attachment like Photo, pdf and multiple files. You should be create a login and verify two steps authentication like OTP, verifications ?? link. PHPMailer make your dreams project eassy and simple also free of cost.

SUSHIL KUMBHAR 2 Dec 8, 2021
A testing package for intercepting mail sent from Laravel

Laravel Mail Intercept A testing package for intercepting mail sent from Laravel This testing suite intercepts Laravel Mail just before they are sent

Kirschbaum Development Group, LLC 91 Oct 18, 2022
Mail application developed with Symfony 5

Fakey-Mail Mail application developed with Symfony 5! Check out the requirements for info on how to launch the app. Check out the basic functionality

Mauro 2 Jun 21, 2022
✉️ Laravel Mail Explorer

Mailbook Mailbook is a Laravel package that lets you easily inspect your mails without having to actually trigger it in your application. View demo In

Max Hoogenbosch 88 Dec 29, 2022
Mail Api for fetch or send mails

flux-mail-api Mail Api for fetch or send mails Installation Native Download RUN (mkdir -p /%path%/libs/flux-mail-api && cd /%path%/libs/flux-mail-api

null 2 Dec 12, 2022
A mail driver to quickly preview mail

A mail driver to quickly preview mail This package can display a small overlay whenever a mail is sent. The overlay contains a link to the mail that w

Spatie 1k Jan 4, 2023
Magento 2 Preview/Visit Catalog allows the store owner to quickly preview the catalog (product & category) pages from the admin panel.

Magento 2 Preview/Visit Catalog Overview Magento 2 Preview/Visit Catalog allows the store owner to quickly preview the catalog (product & category) pa

Raj KB 4 Sep 27, 2022
Arc admin comment preview - Simple Textpattern plugin that adds a comment preview to admin

arc_admin_comment_preview This is a Textpattern plugin for adding comment previews to the admin comment edit pages. Requirements Textpattern 4.0.8+ In

Andy Carter 1 Jan 20, 2017