Skip to content

Commit 322ffaf

Browse files
authored
[12.x] Pass TransportException without Response to NotificationFailed event (#56061)
Prevents including the CurlResponse object that cannot be serialized with the NotificationFailed event.
1 parent 996b283 commit 322ffaf

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

src/Illuminate/Notifications/NotificationSender.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Illuminate\Support\Collection;
1313
use Illuminate\Support\Str;
1414
use Illuminate\Support\Traits\Localizable;
15+
use Symfony\Component\Mailer\Exception\HttpTransportException;
16+
use Symfony\Component\Mailer\Exception\TransportException;
1517
use Throwable;
1618

1719
class NotificationSender
@@ -159,6 +161,10 @@ protected function sendToNotifiable($notifiable, $id, $notification, $channel)
159161
$response = $this->manager->driver($channel)->send($notifiable, $notification);
160162
} catch (Throwable $exception) {
161163
if (! $this->failedEventWasDispatched) {
164+
if ($exception instanceof HttpTransportException) {
165+
$exception = new TransportException($exception->getMessage(), $exception->getCode());
166+
}
167+
162168
$this->events->dispatch(
163169
new NotificationFailed($notifiable, $notification, $channel, ['exception' => $exception])
164170
);

tests/Notifications/NotificationSenderTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
use Illuminate\Contracts\Queue\ShouldQueue;
99
use Illuminate\Notifications\AnonymousNotifiable;
1010
use Illuminate\Notifications\ChannelManager;
11+
use Illuminate\Notifications\Events\NotificationFailed;
12+
use Illuminate\Notifications\Events\NotificationSending;
1113
use Illuminate\Notifications\Notifiable;
1214
use Illuminate\Notifications\Notification;
1315
use Illuminate\Notifications\NotificationSender;
1416
use Mockery as m;
1517
use PHPUnit\Framework\TestCase;
18+
use Symfony\Component\Mailer\Exception\HttpTransportException;
19+
use Symfony\Component\Mailer\Exception\TransportException;
20+
use Symfony\Contracts\HttpClient\ResponseInterface;
1621

1722
class NotificationSenderTest extends TestCase
1823
{
@@ -138,6 +143,29 @@ public function testItCanSendQueuedWithViaConnectionsNotifications()
138143

139144
$sender->send($notifiable, new DummyNotificationWithViaConnections);
140145
}
146+
147+
public function testNotificationFailedSentWithoutHttpTransportException()
148+
{
149+
$this->expectException(TransportException::class);
150+
151+
$notifiable = new AnonymousNotifiable();
152+
$manager = m::mock(ChannelManager::class);
153+
$manager->shouldReceive('driver')->andReturn($driver = m::mock());
154+
$response = m::mock(ResponseInterface::class);
155+
$driver->shouldReceive('send')->andThrow(new HttpTransportException('Transport error', $response));
156+
$bus = m::mock(BusDispatcher::class);
157+
158+
$events = m::mock(EventDispatcher::class);
159+
$events->shouldReceive('listen')->once();
160+
$events->shouldReceive('until')->with(m::type(NotificationSending::class))->andReturn(true);
161+
$events->shouldReceive('dispatch')->once()->withArgs(function ($event) {
162+
return $event instanceof NotificationFailed && $event->data['exception'] instanceof TransportException;
163+
});
164+
165+
$sender = new NotificationSender($manager, $bus, $events);
166+
167+
$sender->sendNow($notifiable, new DummyNotificationWithViaConnections(), ['mail']);
168+
}
141169
}
142170

143171
class DummyQueuedNotificationWithStringVia extends Notification implements ShouldQueue

0 commit comments

Comments
 (0)