Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 994
sterfry68 Avatar asked Jan 06 '15 20:01

sterfry68


2 Answers

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
    }
}
like image 93
Mike Harrison Avatar answered Oct 23 '22 13:10

Mike Harrison


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.

like image 23
ceejayoz Avatar answered Oct 23 '22 13:10

ceejayoz