diff --git a/src/Illuminate/Notifications/Events/NotificationFailed.php b/src/Illuminate/Notifications/Events/NotificationFailed.php index b69e1c5485af..6c3d77c8d8df 100644 --- a/src/Illuminate/Notifications/Events/NotificationFailed.php +++ b/src/Illuminate/Notifications/Events/NotificationFailed.php @@ -31,11 +31,11 @@ class NotificationFailed public $channel; /** - * The data needed to process this failure. + * The exception that caused the failure. * - * @var array + * @var \Throwable */ - public $data = []; + public $throwable; /** * Create a new event instance. @@ -43,12 +43,12 @@ class NotificationFailed * @param mixed $notifiable * @param \Illuminate\Notifications\Notification $notification * @param string $channel - * @param array $data + * @param \Throwable $throwable * @return void */ - public function __construct($notifiable, $notification, $channel, $data = []) + public function __construct($notifiable, $notification, $channel, $throwable) { - $this->data = $data; + $this->throwable = $throwable; $this->channel = $channel; $this->notifiable = $notifiable; $this->notification = $notification; diff --git a/src/Illuminate/Notifications/NotificationSender.php b/src/Illuminate/Notifications/NotificationSender.php index 698d19dcb95f..24b6dbc63a54 100644 --- a/src/Illuminate/Notifications/NotificationSender.php +++ b/src/Illuminate/Notifications/NotificationSender.php @@ -6,11 +6,13 @@ use Illuminate\Contracts\Translation\HasLocalePreference; use Illuminate\Database\Eloquent\Collection as ModelCollection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Notifications\Events\NotificationFailed; use Illuminate\Notifications\Events\NotificationSending; use Illuminate\Notifications\Events\NotificationSent; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\Support\Traits\Localizable; +use Throwable; class NotificationSender { @@ -145,11 +147,18 @@ protected function sendToNotifiable($notifiable, $id, $notification, $channel) return; } - $response = $this->manager->driver($channel)->send($notifiable, $notification); - - $this->events->dispatch( - new NotificationSent($notifiable, $notification, $channel, $response) - ); + try { + $response = $this->manager->driver($channel)->send($notifiable, $notification); + + $this->events->dispatch( + new NotificationSent($notifiable, $notification, $channel, $response) + ); + } catch (Throwable $e) { + $this->events->dispatch( + new NotificationFailed($notifiable, $notification, $channel, $e) + ); + throw $e; + } } /** diff --git a/tests/Notifications/NotificationChannelManagerTest.php b/tests/Notifications/NotificationChannelManagerTest.php index efcce081aeee..7c7a359f810a 100644 --- a/tests/Notifications/NotificationChannelManagerTest.php +++ b/tests/Notifications/NotificationChannelManagerTest.php @@ -2,12 +2,14 @@ namespace Illuminate\Tests\Notifications; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Container\Container; use Illuminate\Contracts\Bus\Dispatcher as Bus; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\ChannelManager; +use Illuminate\Notifications\Events\NotificationFailed; use Illuminate\Notifications\Events\NotificationSending; use Illuminate\Notifications\Events\NotificationSent; use Illuminate\Notifications\Notifiable; @@ -101,6 +103,27 @@ public function testNotificationCanBeQueued() $manager->send([new NotificationChannelManagerTestNotifiable], new NotificationChannelManagerTestQueuedNotification); } + + public function testNotificationDispatchFaildEvent() + { + $container = new Container; + $container->instance('config', ['app.name' => 'Name', 'app.logo' => 'Logo']); + $container->instance(Bus::class, $bus = m::mock()); + $container->instance(Dispatcher::class, $events = m::mock()); + Container::setInstance($container); + $manager = m::mock(ChannelManager::class.'[driver]', [$container]); + $events->shouldReceive('until')->with(m::type(NotificationSending::class))->andReturn(true); + $manager->shouldReceive('driver')->once()->andReturn($driver = m::mock()); + $driver->shouldReceive('send')->once()->andThrow(new Exception('Mail exception')); + $events->shouldReceive('dispatch')->once()->with(m::type(NotificationFailed::class)); + + try { + $manager->send([new NotificationChannelManagerTestNotifiable], new NotificationChannelManagerTestNotCancelledNotification); + $this->fail('Should fail'); + } catch(Exception $e) { + $this->assertEquals('Mail exception', $e->getMessage()); + } + } } class NotificationChannelManagerTestNotifiable