Webhooks And Suppression
Handle AWS SES bounce and complaint notifications with SNS signature verification and local suppression.
Webhooks And Suppression
SES emits bounce and complaint events through SNS. Vortos verifies the SNS signature, parses the notification, and runs registered bounce or complaint handlers.
Route
Default route:
/webhooks/aws/sesOverride it:
$config->webhooks()
->enabled(true)
->routePath('/internal/webhooks/ses');SNS Setup
At AWS level:
- Create an SNS topic for SES events.
- Subscribe the Vortos webhook URL.
- Attach the topic to the SES identity or configuration set for bounces and complaints.
- Confirm the SNS subscription.
- Keep the route reachable over HTTPS.
Bounce Handlers
use Vortos\AwsSes\Attribute\AsBounceHandler;
use Vortos\AwsSes\Contract\BounceHandlerInterface;
use Vortos\AwsSes\Webhook\BounceNotification;
#[AsBounceHandler]
final class MarkEmailBouncedHandler implements BounceHandlerInterface
{
public function handle(BounceNotification $notification): void
{
foreach ($notification->recipients() as $recipient) {
// Update local read model or support workflow.
}
}
}Generate a skeleton when the Make package is installed:
php bin/console vortos:ses:make:bounce-handler MarkEmailBounced --context=NotificationComplaint Handlers
use Vortos\AwsSes\Attribute\AsComplaintHandler;
use Vortos\AwsSes\Contract\ComplaintHandlerInterface;
use Vortos\AwsSes\Webhook\ComplaintNotification;
#[AsComplaintHandler]
final class UnsubscribeComplaintRecipientHandler implements ComplaintHandlerInterface
{
public function handle(ComplaintNotification $notification): void
{
foreach ($notification->recipients() as $recipient) {
// Unsubscribe or mark as complained.
}
}
}php bin/console vortos:ses:make:complaint-handler UnsubscribeComplaintRecipient --context=NotificationLocal Suppression List
The package stores suppressed recipients in aws_ses_suppression_list by default. Sending behavior is configured with onSuppressed().
$config->suppression()
->tableName('aws_ses_suppression_list')
->onSuppressed('throw');throw rejects the email when any recipient is suppressed.
strip removes suppressed recipients and sends to the remaining recipients.
Sync Commands
php bin/console vortos:ses:suppression:sync
php bin/console vortos:ses:suppression:sync --dry-run
php bin/console vortos:ses:suppression:list
php bin/console vortos:ses:suppression:list --limit=50 --offset=100Use explicit sync commands in deployment or operations workflows. Avoid expensive provider syncs during application boot unless you have a small account and a very deliberate startup policy.
Do not skip signature verification
The webhook is public internet input. Keep SNS signature verification enabled and never trust bounce or complaint payloads from unverified sources.