From 1681bc1cce1770319f350e12bf63fa0287d9f3f1 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 19 Jul 2021 14:26:15 -0700 Subject: [PATCH] [Mailer] Make sure Http TransportException is not leaking --- .../Bridge/Amazon/Transport/SesApiTransport.php | 12 ++++++++++-- .../Bridge/Amazon/Transport/SesHttpTransport.php | 12 ++++++++++-- .../Mailchimp/Transport/MandrillApiTransport.php | 11 +++++++++-- .../Mailchimp/Transport/MandrillHttpTransport.php | 11 +++++++++-- .../Mailgun/Transport/MailgunApiTransport.php | 15 +++++++++++---- .../Mailgun/Transport/MailgunHttpTransport.php | 15 +++++++++++---- .../Postmark/Transport/PostmarkApiTransport.php | 11 +++++++++-- .../Sendgrid/Transport/SendgridApiTransport.php | 12 +++++++++--- 8 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php index 639bacfae2d72..ccbf6b166cac8 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php @@ -18,6 +18,7 @@ use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Email; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -63,8 +64,15 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'body' => $payload = $this->getPayload($email, $envelope), ]); - $result = new \SimpleXMLElement($response->getContent(false)); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $content = $response->getContent(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Amazon server.', $response, 0, $e); + } + + $result = new \SimpleXMLElement($content); + if (200 !== $statusCode) { throw new HttpTransportException('Unable to send an email: '.$result->Error->Message.sprintf(' (code %d).', $result->Error->Code), $response); } diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php index d17d23b1e097f..47809444a3026 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php @@ -16,6 +16,7 @@ use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractHttpTransport; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -69,8 +70,15 @@ protected function doSendHttp(SentMessage $message): ResponseInterface $response = $this->client->request('POST', 'https://'.$this->getEndpoint(), $request); - $result = new \SimpleXMLElement($response->getContent(false)); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $content = $response->getContent(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Amazon server.', $response, 0, $e); + } + + $result = new \SimpleXMLElement($content); + if (200 !== $statusCode) { throw new HttpTransportException('Unable to send an email: '.$result->Error->Message.sprintf(' (code %d).', $result->Error->Code), $response); } diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php index f05d60ad4e34d..3feccff25ce7d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php @@ -18,6 +18,7 @@ use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Email; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -48,8 +49,14 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'json' => $this->getPayload($email, $envelope), ]); - $result = $response->toArray(false); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Mandrill server.', $response, 0, $e); + } + + if (200 !== $statusCode) { if ('error' === ($result['status'] ?? false)) { throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $result['code']), $response); } diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php index 1c3846d160210..d21158252d42c 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php @@ -17,6 +17,7 @@ use Symfony\Component\Mailer\Transport\AbstractHttpTransport; use Symfony\Component\Mime\Address; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -55,8 +56,14 @@ protected function doSendHttp(SentMessage $message): ResponseInterface ], ]); - $result = $response->toArray(false); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Mandrill server.', $response, 0, $e); + } + + if (200 !== $statusCode) { if ('error' === ($result['status'] ?? false)) { throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $result['code']), $response); } diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php index c0e26476f35d1..731d535e7bf58 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php @@ -19,6 +19,7 @@ use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Part\Multipart\FormDataPart; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -62,13 +63,19 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'body' => $body->bodyToIterable(), ]); - $result = $response->toArray(false); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Mailgun server.', $response, 0, $e); + } + + if (200 !== $statusCode) { if ('application/json' === $response->getHeaders(false)['content-type'][0]) { - throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $response->getStatusCode()), $response); + throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $statusCode), $response); } - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $response->getStatusCode()), $response); + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); } $sentMessage->setMessageId($result['id']); diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php index 524bb4f81abf1..1c7b1cb0ee152 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php @@ -18,6 +18,7 @@ use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\Multipart\FormDataPart; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -64,13 +65,19 @@ protected function doSendHttp(SentMessage $message): ResponseInterface 'body' => $body->bodyToIterable(), ]); - $result = $response->toArray(false); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Mailgun server.', $response, 0, $e); + } + + if (200 !== $statusCode) { if ('application/json' === $response->getHeaders(false)['content-type'][0]) { - throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $response->getStatusCode()), $response); + throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $statusCode), $response); } - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $response->getStatusCode()), $response); + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); } $message->setMessageId($result['id']); diff --git a/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php index 72e71195c1924..10bd68f27dc37 100644 --- a/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php @@ -18,6 +18,7 @@ use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Email; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -52,8 +53,14 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'json' => $this->getPayload($email, $envelope), ]); - $result = $response->toArray(false); - if (200 !== $response->getStatusCode()) { + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Postmark server.', $response, 0, $e); + } + + if (200 !== $statusCode) { throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); } diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index f1424ae9589c5..39c6df1a90513 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -19,6 +19,7 @@ use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -50,10 +51,15 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'auth_bearer' => $this->key, ]); - if (202 !== $response->getStatusCode()) { - $errors = $response->toArray(false); + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote Sendgrid server.', $response, 0, $e); + } - throw new HttpTransportException('Unable to send an email: '.implode('; ', array_column($errors['errors'], 'message')).sprintf(' (code %d).', $response->getStatusCode()), $response); + if (202 !== $statusCode) { + throw new HttpTransportException('Unable to send an email: '.implode('; ', array_column($result['errors'], 'message')).sprintf(' (code %d).', $statusCode), $response); } $sentMessage->setMessageId($response->getHeaders(false)['x-message-id'][0]);