Skip to content

Commit

Permalink
Merge pull request #145 from nickvanderveeken/feature/sparkpost-suppr…
Browse files Browse the repository at this point in the history
…ession-list

Add SparkPost suppression-list support
  • Loading branch information
roelvanduijnhoven authored Aug 18, 2021
2 parents 687c848 + 9fe5545 commit bee33da
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

class ConfigProvider
{
public function __invoke()
public function __invoke(): array
{
$module = new Module();
$config = $module->getConfig();
Expand Down
59 changes: 57 additions & 2 deletions src/Service/SparkPostService.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ class SparkPostService extends AbstractMailService
*/
protected $apiKey;

public const SUPPRESSION_LIST_TRANSACTIONAL = 'transactional';
public const SUPPRESSION_LIST_NON_TRANSACTIONAL = 'non_transactional';
public const SUPPRESSION_LISTS = [
self::SUPPRESSION_LIST_TRANSACTIONAL,
self::SUPPRESSION_LIST_NON_TRANSACTIONAL,
];

/**
* Constructor
*/
Expand Down Expand Up @@ -311,6 +318,54 @@ public function registerSendingDomain(string $domain, array $options = []): bool
return false;
}

/**
* Add an email address to the suppression lists for transactional email, non-transactional email, or both
*/
public function addToSuppressionList(string $emailAddress, string $reason, array $suppressionLists = self::SUPPRESSION_LISTS): void
{
$put = [
'recipients' => [],
];

foreach($suppressionLists as $suppressionList) {
if(in_array($suppressionList, self::SUPPRESSION_LISTS)) {
$put['recipients'][] = array(
'recipient' => $emailAddress,
'type' => $suppressionList,
'description' => $reason,
);
}
}

if ($put['recipients']) {
$response = $this->prepareHttpClient('/suppression-list/', $put)
->setMethod(HttpRequest::METHOD_PUT)
->send();

$this->parseResponse($response);
}
}

/**
* Remove an email address from the suppression lists for transactional email, non-transactional email, or both
*/
public function removeFromSuppressionList(string $emailAddress, array $suppressionLists = self::SUPPRESSION_LISTS): void
{
foreach($suppressionLists as $suppressionList) {
if (in_array($suppressionList, self::SUPPRESSION_LISTS)) {
$delete = [
'type' => $suppressionList,
];

$response = $this->prepareHttpClient('/suppression-list/' . urlencode($emailAddress), $delete)
->setMethod(HttpRequest::METHOD_DELETE)
->send();

$this->parseResponse($response, [403, 404]);
}
}
}

public function verifySendingDomain(string $domain, array $options = []): bool
{
$dkimVerify = array_key_exists('dkim_verify', $options) && $options['dkim_verify'] === true;
Expand Down Expand Up @@ -375,8 +430,8 @@ private function prepareHttpClient(string $uri, array $parameters = []): HttpCli
}

/**
* @param HttpResponse $response
*
* @param HttpResponse $response
* @param int[] $successCodes
* @throws RuntimeException
* @return array
*/
Expand Down
52 changes: 46 additions & 6 deletions tests/SlmMailTest/Service/SparkPostServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use Laminas\Mail\Address;
use Laminas\Mail\AddressList;
use Laminas\Mail\Message;
use PHPUnit\Framework\MockObject\MockBuilder;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
use SlmMail\Mail\Message\SparkPost;
Expand Down Expand Up @@ -43,7 +41,7 @@ private function expectApiResponse(int $statusCode = 200, string $responseBody =
}
$sendMessageResponse->setContent($responseBody);

$httpClientMock->expects($this->once())
$httpClientMock->expects($this->atLeastOnce())
->method('send')
->willReturn($sendMessageResponse);

Expand Down Expand Up @@ -190,14 +188,16 @@ public function testRemoveSendingDomain()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(204);
$this->assertNull($sparkPostServiceMock->removeSendingDomain('sparkpost-sending-domain.com'));
$sparkPostServiceMock->removeSendingDomain('sparkpost-sending-domain.com');
$this->doesNotPerformAssertions();
}

public function testRemoveNonExistingSendingDomain()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(404);
$this->assertNull($sparkPostServiceMock->removeSendingDomain('sparkpost-sending-domain.com'));
$sparkPostServiceMock->removeSendingDomain('sparkpost-sending-domain.com');
$this->doesNotPerformAssertions();
}

public function testVerifySendingDomain()
Expand Down Expand Up @@ -232,12 +232,52 @@ public function testVerifySendingDomainWithInvalidDkimRecord()

public function testVerifyUnregisteredSendingDomain()
{
//** @var SparkPostService $sparkPostServiceMock */
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(
404,
'{"errors":[{"message":"invalid params","description":"Sending domain \'sparkpost-sending-domain.com\' is not a registered sending domain","code":"1200"}]}'
);
$this->expectException(RuntimeException::class);
$sparkPostServiceMock->verifySendingDomain('sparkpost-sending-domain.com');
}

public function testAddToSuppressionList()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(200, '{"results":{"message":"Suppression List successfully updated"}}');
$sparkPostServiceMock->addToSuppressionList('[email protected]', 'Permanent block after hard bounce');
$this->doesNotPerformAssertions();
}

public function testAddToTransactionalSuppressionList()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(200, '{"results":{"message":"Suppression List successfully updated"}}');
$sparkPostServiceMock->addToSuppressionList('[email protected]', 'Permanent block after hard bounce', [SparkPostService::SUPPRESSION_LIST_TRANSACTIONAL]);
$this->doesNotPerformAssertions();
}

public function testRemoveFromSuppressionList()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(204);
$sparkPostServiceMock->removeFromSuppressionList('[email protected]');
$this->doesNotPerformAssertions();
}

public function testRemoveFromTransactionalSuppressionList()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(204);
$sparkPostServiceMock->removeFromSuppressionList('[email protected]', [SparkPostService::SUPPRESSION_LIST_TRANSACTIONAL]);
$this->doesNotPerformAssertions();
}

public function testRemoveNonExistingAddressFromSuppressionList()
{
/** @var SparkPostService $sparkPostServiceMock */
$sparkPostServiceMock = $this->expectApiResponse(404);
$sparkPostServiceMock->removeFromSuppressionList('[email protected]');
$this->doesNotPerformAssertions();
}
}

0 comments on commit bee33da

Please sign in to comment.