Search code examples
laravellaravel-5laravel-queuelaravel-maillaravel-notification

Laravel Notifications - delay email sending and cancel if condition met


I have an app where I am sending a push notification which is fine if the user is logged into the application - however, if they're not / if they have not read the notification within X minutes I'd like to send them an email.

The way I am going about this is to use Laravel Notifications to create a mail, broadcast & database notification. On the toMail() method I'm returning a mailable with a delay -

public function toMail($notifiable)
{
    return (new \App\Mail\Order\NewOrder($this->order))
        ->delay(now()->addMinutes(10));
}

After the minutes are up, the email will send but, before the send goes ahead I'd like to perform a check to see if the push/database notification has already been marked as read and if it has cancel the email send. The only way I can think to do this is to bind to the MessageSending event that is baked into Laravel -

// listen for emails being sent
'Illuminate\Mail\Events\MessageSending' => [
    'App\Listeners\Notification\SendingEmail'
],

The only problem is this listener receives a Swift mail event and not the original mailable I was dispatching so I don't know how to cancel it. Any ideas and thanks in advance?


Solution

  • Class extends Notification

    public function via($notifiable)
    {
        if($this->dontSend($notifiable)) {
            return [];
        }
        return ['mail'];
    }
    
    public function dontSend($notifiable)
    {
        return $this->appointment->status === 'cancelled';
    }
    

    Class EventServiceProvider

    protected $listen = [
        NotificationSending::class => [
            NotificationSendingListener::class,
        ],
    ];
    

    Class NotificationSendingListener

    public function handle(NotificationSending $event)
    {
        if (method_exists($event->notification, 'dontSend')) {
            return !$event->notification->dontSend($event->notifiable);
        }
        return true;
    }
    

    For more details look article Handling delayed notifications in Laravel