diff --git a/src/Listeners/Webhooks/HandlePostmarkWebhook.php b/src/Listeners/Webhooks/HandlePostmarkWebhook.php index 0530c7b1..537fd894 100644 --- a/src/Listeners/Webhooks/HandlePostmarkWebhook.php +++ b/src/Listeners/Webhooks/HandlePostmarkWebhook.php @@ -54,6 +54,10 @@ public function handle(PostmarkWebhookReceived $event): void $this->handleBounce($messageId, $event->payload); break; + case'SubscriptionChange': + $this->handleSubscriptionChange($messageId, $event->payload); + break; + default: throw new RuntimeException("Unknown Postmark webhook event type '{$eventName}'."); } @@ -105,6 +109,20 @@ private function handleBounce(string $messageId, array $content): void } } + private function handleSubscriptionChange(string $messageId, array $content): void + { + $value = $this->extractSuppressSending($content); + $timestamp = $this->extractTimestamp($content, 'ChangedAt'); + + if($value){ + $this->emailWebhookService->handleUnsubscribe($messageId, $timestamp); + } + else{ + $this->emailWebhookService->handleResubscribe($messageId); + } + } + + /** * Determine if the bounce is permanent * https://postmarkapp.com/developer/api/bounce-api#bounce-types @@ -132,6 +150,11 @@ private function extractEventName(array $payload): string return Arr::get($payload, 'RecordType'); } + private function extractSuppressSending(array $payload): bool + { + return Arr::get($payload, 'SuppressSending'); + } + private function extractMessageId(array $payload): string { return trim(Arr::get($payload, 'MessageID')); diff --git a/src/Services/Webhooks/EmailWebhookService.php b/src/Services/Webhooks/EmailWebhookService.php index e464cdd9..d6280810 100644 --- a/src/Services/Webhooks/EmailWebhookService.php +++ b/src/Services/Webhooks/EmailWebhookService.php @@ -140,6 +140,43 @@ public function handlePermanentBounce($messageId, $timestamp): void $this->unsubscribe($messageId, UnsubscribeEventType::BOUNCE); } + public function handleUnsubscribe($messageId, $timestamp): void + { + + /* @var Message $message */ + $message = Message::where('message_id', $messageId)->first(); + + if (!$message) { + return; + } + + $message->unsubscribed_at = $timestamp; + $message->save(); + + + $this->unsubscribe($messageId, UnsubscribeEventType::MANUAL_BY_SUBSCRIBER); + } + + public function handleResubscribe($messageId): void + { + + /* @var Message $message */ + $message = Message::where('message_id', $messageId)->first(); + + if (!$message) { + return; + } + + $message->unsubscribed_at = 'NULL'; + $message->save(); + + + $this->resubscribe($messageId); + } + + + + public function handleFailure($messageId, $severity, $description, $timestamp): void { /* @var Message $message */ @@ -176,6 +213,24 @@ protected function unsubscribe(string $messageId, int $typeId): void ]); } + /** + * Resubscribe a subscriber. + */ + protected function resubscribe(string $messageId): void + { + $subscriberId = DB::table('sendportal_messages')->where('message_id', $messageId)->value('subscriber_id'); + + if (!$subscriberId) { + return; + } + + DB::table('sendportal_subscribers')->where('id', $subscriberId)->update([ + 'unsubscribed_at' => NULL, + 'unsubscribe_event_id' => NULL, + 'updated_at' => now() + ]); + } + /** * Resolve the automation step from a message *