Search code examples
laravelemail

Is there any event after sent email in Laravel


My app flow looks like this:

  1. I created an invoice, invoice status = created
  2. I send it to user, I use Queueable so the process of sending email is separated from main app.
  3. After sending email complete, invoice status should be sent

The problem is, I could not find any event like AfterEmailSent for specific Mailable class in app/Mail.


Solution

  • Starting in Laravel 5.2 you can utilize the EventBus to subscribe to events that are emitted by the Laravel mailer.

    You can read about the specific here: laravel.com/docs/master/mail#events

    In Laravel 5.2 it emits an event when a message is being sent

    // EventServiceProvider.php
    
    protected $listen = [
        'Illuminate\Mail\Events\MessageSending' => [
            'App\Listeners\LogSentMessage',
        ],
    ];
    

    Starting in Laravel 5.5 there's a specific MessageSent event:

    
    // EventServiceProvider
    
    protected $listen = [
        'Illuminate\Mail\Events\MessageSending' => [
            'App\Listeners\LogSendingMessage',
        ],
        'Illuminate\Mail\Events\MessageSent' => [
            'App\Listeners\LogSentMessage',
        ],
    ];
    

    Of course, in newer versions of PHP you can use more legible syntax:

    // EventServiceProvider.php
    
    protected $listen = [
        MessageSending::class => [
            LogSendingMessage::class,
        ],
        MessageSent::class => [
            LogSentMessage::class,
        ],
    ];
    

    There is also an event available in Laravel 5.1, but you utilize the event bus in 5.1 differently than in 5.2+. If needed, you can view the docs on those here: https://laravel.com/docs/5.1/mail#events


    In Practice:

    The Mailer events don't send a reference to the Mailable that resulted in the event being emitted (huge wtf, imo). So, you'll have to devise a way to determine which Mailable has been sent as a result of the MessageSent event being emitted.

    I'm actively working on something that needs this functionality. It looks like the view data that is provided to the Mailable is included on the SentMessage event. It's nasty, but I'll be adding a reference to the mailable object itself to that view data, so I can capture it on the Listener, and respond accordingly.