sterfry68
sterfry68

Reputation: 1093

Laravel Mail Listener (Before Send - Ability to Cancel)

Is there a way to use Laravel's "Event" class to run some code before every email is sent? I'd also like the ability to cancel the Mail::send();.

Of course I could do this before I send an email:

Event::fire('email.beforeSend');

And then I could listen this way:

Event::listen('email.beforeSend', function()
{
    //my code here
});

The problem with this is that I have to remember to run Event::fire() which I'd rather not do. In my case I'm bouncing the email address against an unsubscribe list to make sure that I don't send any spam.

Upvotes: 10

Views: 7768

Answers (2)

Mike Harrison
Mike Harrison

Reputation: 1393

For Laravel 5 you can listen to the Illuminate\Mail\Events\MessageSending event and return false if you want to cancel sending the message.

Add this to your EventServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'Illuminate\Mail\Events\MessageSending' => [
            'App\Listeners\CheckEmailPreferences',
        ],
    ];
}

Here is my event listener at App\Listeners\CheckEmailPreferences

<?php

namespace App\Listeners;

use App\User;
use Illuminate\Mail\Events\MessageSending;
use Illuminate\Support\Facades\App;

class CheckEmailPreferences
{
    public function handle( MessageSending $event )
    {
        //if app is in prod and we don't want to send any emails
        if(App::environment() === 'production' && ! env('SEND_MAIL_TO_CUSTOMERS')){
            return false;
        }

        //you can check if the user wants to receive emails here
    }
}

Upvotes: 13

ceejayoz
ceejayoz

Reputation: 180023

Laravel's Mail class fires mailer.sending as part of the sending process.

protected function sendSwiftMessage($message)
{
    if ($this->events)
    {
        $this->events->fire('mailer.sending', array($message));
    }

    if ( ! $this->pretending)
    {
        $this->swift->send($message, $this->failedRecipients);
    }
    elseif (isset($this->logger))
    {
        $this->logMessage($message);
    }
}

You could catch this event and adjust the $message object, or you could likely prevent sending by calling Mail::pretend(); within your event handler.

Upvotes: 6

Related Questions