Skip to content

Commit

Permalink
SparkPostApiTransport handleError response
Browse files Browse the repository at this point in the history
  • Loading branch information
gam6itko committed Jun 15, 2020
1 parent 5925cda commit 960e2ff
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.idea
/composer.lock
/vendor/
/.php_cs.cache
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
],
"require": {
"php": "^7.1",
"ext-json": "*",
"symfony/mailer": "^4.4|^5.0"
},
"require-dev": {
Expand Down
26 changes: 25 additions & 1 deletion src/Transport/SparkPostApiTransport.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Gam6itko\Symfony\Mailer\SparkPost\Mime\SparkPostEmail;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\Exception\HttpTransportException;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
use Symfony\Component\Mime\Email;
Expand Down Expand Up @@ -51,13 +52,17 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e

$this->log($payload);

return $this->client->request('POST', 'https://api.sparkpost.com/api/v1/transmissions/', [
$response = $this->client->request('POST', 'https://api.sparkpost.com/api/v1/transmissions/', [
'headers' => [
'Authorization' => $this->key,
'Content-Type' => 'application/json',
],
'json' => $payload,
]);

$this->handleError($response);

return $response;
}

private function buildRecipients(Envelope $envelope): array
Expand Down Expand Up @@ -126,4 +131,23 @@ private function log(array $payload)
}
$this->getLogger()->debug('SparkPostApiTransport send', $payload);
}

/**
* @throws HttpTransportException
*/
private function handleError(ResponseInterface $response): void
{
if (200 === $response->getStatusCode()) {
return;
}

$data = json_decode($response->getContent(false), true);
$this->getLogger()->error('SparkPostApiTransport error response', $data);
$error = $data['errors'][0] ?? null;
if (empty($error)) {
return;
}

throw new HttpTransportException("[{$error['code']}] {$error['message']}. {$error['description']}.", $response);
}
}
7 changes: 5 additions & 2 deletions tests/EventListener/SinkEnvelopeListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
*/
class SinkEnvelopeListenerTest extends TestCase
{
public static function setUpBeforeClass(): void
{
BypassFinals::enable();
}

public function testSinkEmail()
{
$envelope = new Envelope(Address::fromString('test case <[email protected]>'), [
Expand All @@ -37,8 +42,6 @@ public function testSinkEmail()

public function testNoPrefix()
{
BypassFinals::enable();

$messageEvent = $this->createMock(MessageEvent::class);
$messageEvent
->expects(self::never())
Expand Down
96 changes: 82 additions & 14 deletions tests/Transport/SparkPostApiTransportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\DelayedEnvelope;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\Exception\HttpTransportException;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\RawMessage;
Expand All @@ -21,15 +22,43 @@
*/
class SparkPostApiTransportTest extends TestCase
{
private function createDefaultMessage(): Email
{
return (new Email())
->from('[email protected]')
->to('[email protected]')
->subject('Test email')
->text('Test email for you!')
->attach(str_pad('', 200, 'A'), 'name.txt');
}

private function createDefaultEnvelope(): Envelope
{
return new Envelope(new Address('[email protected]'), [new Address('[email protected]')]);
}

private function createDefaultResponse(): ResponseInterface
{
$response = $this->createMock(ResponseInterface::class);
$response
->expects(self::atLeastOnce())
->method('getStatusCode')
->willReturn(200);
return $response;
}

/**
* @dataProvider dataSend
*/
public function testSend(RawMessage $message, Envelope $envelope, string $expectedJson)
public function testSend(RawMessage $message, Envelope $envelope, string $expectedJson): void
{
$response = $this->createDefaultResponse();

$client = $this->createMock(HttpClientInterface::class);
$client->expects(self::once())
$client
->expects(self::once())
->method('request')
->willReturnCallback(function (string $method, string $url, array $options = []) use ($expectedJson) {
->willReturnCallback(function (string $method, string $url, array $options = []) use ($expectedJson, $response) {
self::assertEquals('POST', $method);
self::assertEquals('https://api.sparkpost.com/api/v1/transmissions/', $url);
self::assertArrayHasKey('headers', $options);
Expand All @@ -40,7 +69,7 @@ public function testSend(RawMessage $message, Envelope $envelope, string $expect
self::assertIsArray($options['json']);
self::assertJsonStringEqualsJsonString($expectedJson, json_encode($options['json']));

return $this->createMock(ResponseInterface::class);
return $response;
});
$transport = new SparkPostApiTransport('api-key', $client);
$transport->send($message, $envelope);
Expand Down Expand Up @@ -198,20 +227,15 @@ public function dataSend()
];
}

public function testTruncateAttachemntData()
public function testTruncateAttachmentData(): void
{
$message = (new Email())
->from('[email protected]')
->to('[email protected]')
->subject('Test email')
->text('Test email for you!')
->attach(str_pad('', 200, 'A'), 'name.txt');
$envelope = new Envelope(new Address('[email protected]'), [new Address('[email protected]')]);
$response = $this->createDefaultResponse();

$client = $this->createMock(HttpClientInterface::class);
$client
->expects(self::once())
->method('request');
->method('request')
->willReturn($response);

$logger = $this->createMock(LoggerInterface::class);
$logger
Expand All @@ -223,7 +247,7 @@ public function testTruncateAttachemntData()
self::assertSame('<<<truncated>>>', $context['content']['attachments'][0]['data']);
});
$transport = new SparkPostApiTransport('api-key', $client, null, $logger);
$transport->send($message, $envelope);
$transport->send($this->createDefaultMessage(), $this->createDefaultEnvelope());
}

public function testToString()
Expand All @@ -232,4 +256,48 @@ public function testToString()
$transport = new SparkPostApiTransport('api-key', $client);
self::assertSame('sparkpost+api://', (string) $transport);
}

public function testNotSuccess(): void
{
self::expectException(HttpTransportException::class);
self::expectExceptionMessage('[1902] Message generation rejected. Blocked Sending Domain <domain.com>.');

$error = [
'errors' => [
[
'message' => 'Message generation rejected',
'description' => 'Blocked Sending Domain <domain.com>',
'code' => '1902',
],
],
'results' => [
'total_rejected_recipients' => 0,
'total_accepted_recipients' => 1,
'id' => '012345678901234567',
],
];
$response = $this->createMock(ResponseInterface::class);
$response
->expects(self::atLeastOnce())
->method('getStatusCode')
->willReturn(400);
$response
->expects(self::atLeastOnce())
->method('getContent')
->willReturn(json_encode($error));

$client = $this->createMock(HttpClientInterface::class);
$client
->expects(self::once())
->method('request')
->willReturn($response);

$logger = $this->createMock(LoggerInterface::class);
$logger
->expects(self::once())
->method('error');

$transport = new SparkPostApiTransport('api-key', $client, null, $logger);
$transport->send($this->createDefaultMessage(), $this->createDefaultEnvelope());
}
}

0 comments on commit 960e2ff

Please sign in to comment.