Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature #52916 [Mailer] Dispatch event for Postmark's "inactive recip…
…ient" API error (vicdelfant) This PR was squashed before being merged into the 7.1 branch. Discussion ---------- [Mailer] Dispatch event for Postmark's "inactive recipient" API error | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? |no | New feature? | yes | Deprecations? | no | Issues | Fix #50165 | License | MIT Given the use of Postmark and a recipient that previously generated a bounce, attempting to send another email to that email address results in an HTTP 422 response, along with the error code [`406 - Inactive Recipient`](https://postmarkapp.com/developer/api/overview#error-codes). In the real world, this situation can arise easily in cases of a typo or an email address that had temporary issues. Because `PostmarkApiTransport` requires an HTTP 200 and throws a `HttpTransportException` for any other HTTP code, something that's of minor interest to the application itself (i.e. a _possibly_ inactive e-mail address) now causes an exception. Depending on the userland logic, this can halt a process that sends out survey reminders, cause the Messenger component to queue the message for retrying etc. To handle this more elegantly, I'm proposing the following changes: * Add a `PostmarkDeliveryEventFactory` for casting any (future) delivery events to an instance of `PostmarkDeliveryEvent`. Currently, only support the 406 'inactive recipient' error is included; * Adjust the `PostmarkApiTransport` so it checks for supported delivery events on an HTTP code other than 200, and if so, dispatches the event accordingly. We cannot port this logic to the Postmark SMTP transport because, according to Postmark's own documentation, these error response codes are only provided by their API endpoints. Commits ------- 6ffd173 [Mailer] Dispatch event for Postmark's "inactive recipient" API error
- Loading branch information
Showing
7 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
64 changes: 64 additions & 0 deletions
64
src/Symfony/Component/Mailer/Bridge/Postmark/Event/PostmarkDeliveryEvent.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Mailer\Bridge\Postmark\Event; | ||
|
||
use Symfony\Component\Mime\Header\Headers; | ||
|
||
class PostmarkDeliveryEvent | ||
{ | ||
public const CODE_INACTIVE_RECIPIENT = 406; | ||
|
||
private int $errorCode; | ||
|
||
private Headers $headers; | ||
|
||
private ?string $message; | ||
|
||
public function __construct(string $message, int $errorCode) | ||
{ | ||
$this->message = $message; | ||
$this->errorCode = $errorCode; | ||
|
||
$this->headers = new Headers(); | ||
} | ||
|
||
public function getErrorCode(): int | ||
{ | ||
return $this->errorCode; | ||
} | ||
|
||
public function getHeaders(): Headers | ||
{ | ||
return $this->headers; | ||
} | ||
|
||
public function getMessage(): ?string | ||
{ | ||
return $this->message; | ||
} | ||
|
||
public function getMessageId(): ?string | ||
{ | ||
if (!$this->headers->has('Message-ID')) { | ||
return null; | ||
} | ||
|
||
return $this->headers->get('Message-ID')->getBodyAsString(); | ||
} | ||
|
||
public function setHeaders(Headers $headers): self | ||
{ | ||
$this->headers = $headers; | ||
|
||
return $this; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/Symfony/Component/Mailer/Bridge/Postmark/Event/PostmarkDeliveryEventFactory.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Mailer\Bridge\Postmark\Event; | ||
|
||
use Symfony\Component\Mime\Email; | ||
|
||
class PostmarkDeliveryEventFactory | ||
{ | ||
public function create(int $errorCode, string $message, Email $email): PostmarkDeliveryEvent | ||
{ | ||
if (!$this->supports($errorCode)) { | ||
throw new \InvalidArgumentException(sprintf('Error code "%s" is not supported.', $errorCode)); | ||
} | ||
|
||
return (new PostmarkDeliveryEvent($message, $errorCode)) | ||
->setHeaders($email->getHeaders()); | ||
} | ||
|
||
public function supports(int $errorCode): bool | ||
{ | ||
return \in_array($errorCode, [ | ||
PostmarkDeliveryEvent::CODE_INACTIVE_RECIPIENT, | ||
]); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/Symfony/Component/Mailer/Bridge/Postmark/Event/PostmarkEvents.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Mailer\Bridge\Postmark\Event; | ||
|
||
class PostmarkEvents | ||
{ | ||
public const DELIVERY = 'postmark.delivery'; | ||
} |
26 changes: 26 additions & 0 deletions
26
...Symfony/Component/Mailer/Bridge/Postmark/Tests/Event/PostmarkDeliveryEventFactoryTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Mailer\Bridge\Postmark\Tests\Event; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\Mailer\Bridge\Postmark\Event\PostmarkDeliveryEvent; | ||
use Symfony\Component\Mailer\Bridge\Postmark\Event\PostmarkDeliveryEventFactory; | ||
|
||
class PostmarkDeliveryEventFactoryTest extends TestCase | ||
{ | ||
public function testFactorySupportsInactiveRecipient() | ||
{ | ||
$factory = new PostmarkDeliveryEventFactory(); | ||
|
||
$this->assertTrue($factory->supports(PostmarkDeliveryEvent::CODE_INACTIVE_RECIPIENT)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters