[Mailer] Fixed Mailgun API bridge JsonException when API response is not applicaton/json

- Fixes issue #38146
This commit is contained in:
Andrea Sprega 2020-09-10 17:31:24 +02:00
parent 4409a30dee
commit ce8f7e5c02
2 changed files with 32 additions and 1 deletions

View File

@ -180,6 +180,35 @@ class MailgunApiTransportTest extends TestCase
$transport->send($mail);
}
public function testSendThrowsForErrorResponseWithContentTypeTextHtml()
{
$client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface {
$this->assertSame('POST', $method);
$this->assertSame('https://api.mailgun.net:8984/v3/symfony/messages', $url);
$this->assertStringContainsStringIgnoringCase('Authorization: Basic YXBpOkFDQ0VTU19LRVk=', $options['headers'][2] ?? $options['request_headers'][1]);
// NOTE: Mailgun API does this even if "Accept" request header value is "application/json".
return new MockResponse('Forbidden', [
'http_code' => 401,
'response_headers' => [
'content-type' => 'text/html',
],
]);
});
$transport = new MailgunApiTransport('ACCESS_KEY', 'symfony', 'us', $client);
$transport->setPort(8984);
$mail = new Email();
$mail->subject('Hello!')
->to(new Address('saif.gmati@symfony.com', 'Saif Eddin'))
->from(new Address('fabpot@symfony.com', 'Fabien'))
->text('Hello There!');
$this->expectException(HttpTransportException::class);
$this->expectExceptionMessage('Unable to send an email: Forbidden (code 401).');
$transport->send($mail);
}
public function testTagAndMetadataHeaders()
{
$json = json_encode(['foo' => 'bar']);

View File

@ -64,15 +64,17 @@ class MailgunApiTransport extends AbstractApiTransport
'body' => $body->bodyToIterable(),
]);
$result = $response->toArray(false);
if (200 !== $response->getStatusCode()) {
if ('application/json' === $response->getHeaders(false)['content-type'][0]) {
$result = $response->toArray(false);
throw new HttpTransportException('Unable to send an email: '.$result['message'].sprintf(' (code %d).', $response->getStatusCode()), $response);
}
throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $response->getStatusCode()), $response);
}
// The assumption here is that all 200 responses are "application/json", so it's safe to call "toArray".
$result = $response->toArray(false);
$sentMessage->setMessageId($result['id']);
return $response;