diff --git a/src/Endpoints/MessagesEndpoint.php b/src/Endpoints/MessagesEndpoint.php index 6d0a1de..1513c5c 100644 --- a/src/Endpoints/MessagesEndpoint.php +++ b/src/Endpoints/MessagesEndpoint.php @@ -5,6 +5,7 @@ use Lettermint\Responses\MessageEventsResponse; use Lettermint\Responses\MessageListResponse; use Lettermint\Responses\MessageResponse; +use Lettermint\Responses\ProcessInboundMessageResponse; use Lettermint\Responses\ScheduledMessageResponse; class MessagesEndpoint extends Endpoint @@ -30,6 +31,11 @@ public function cancel(string $messageId): ScheduledMessageResponse return $this->hydrate(ScheduledMessageResponse::class, $this->postArray($this->path('/messages/{messageId}/cancel', ['messageId' => $messageId]))); } + public function process(string $messageId): ProcessInboundMessageResponse + { + return $this->hydrate(ProcessInboundMessageResponse::class, $this->postArray($this->path('/messages/{messageId}/process', ['messageId' => $messageId]))); + } + public function events(string $messageId, array $query = []): MessageEventsResponse { return $this->hydrate(MessageEventsResponse::class, $this->getArray($this->path('/messages/{messageId}/events', ['messageId' => $messageId]), $query)); diff --git a/src/Responses/ProcessInboundMessageResponse.php b/src/Responses/ProcessInboundMessageResponse.php new file mode 100644 index 0000000..617ac10 --- /dev/null +++ b/src/Responses/ProcessInboundMessageResponse.php @@ -0,0 +1,13 @@ + * @phpstan-type CursorPage array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} - * @phpstan-type MessageStatus 'scheduled'|'pending'|'queued'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' + * @phpstan-type MessageStatus 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' * @phpstan-type SendMailRequest array{route?: string, from: string, to: non-empty-list, cc?: list, bcc?: list, reply_to?: list, subject: string, scheduled_at?: string, headers?: array, metadata?: array, tag?: string|null, tags?: list, settings?: array{track_opens?: bool, track_clicks?: bool, tls?: TlsPolicy}|null, html?: string|null, text?: string|null, attachments?: list} * @phpstan-type SendBatchMailRequest list * @phpstan-type TlsPolicy 'opportunistic'|'enforced' @@ -26,7 +26,7 @@ * @phpstan-type MessageAttachmentData array{size: int, filename: string, content_id: string|null, content_type: string} * @phpstan-type MessageData array{id: string, type: MessageType, status: MessageStatus, status_changed_at: string|null, scheduled_at: string|null, tag: string|null, tags: list, from_email: string, from_name: string|null, reply_to: list|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, attachments: list|null, metadata: array|null, spam_score?: float|int|null, spam_symbols?: list, route_id: string, created_at: string} * @phpstan-type MessageEventData array{message_id: string, event: MessageEventType, tag: string|null, tags: list, metadata: array|null, timestamp: string} - * @phpstan-type MessageEventType 'scheduled'|'rescheduled'|'canceled'|'released'|'queued'|'processed'|'suppressed'|'delivered'|'auto_replied'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'opened'|'clicked'|'inbound_received'|'inbound_queued'|'inbound_spam_blocked'|'inbound_processed'|'inbound_retry' + * @phpstan-type MessageEventType 'scheduled'|'rescheduled'|'canceled'|'released'|'queued'|'processed'|'suppressed'|'delivered'|'auto_replied'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'opened'|'clicked'|'inbound_received'|'inbound_queued'|'inbound_spam_blocked'|'inbound_released'|'inbound_processed'|'inbound_retry' * @phpstan-type MessageListData array{id: string, type: MessageType, status: MessageStatus, scheduled_at: string|null, spam_score?: float|int|null, from_email: string, from_name: string|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, reply_to: list|null, tag: string|null, tags: list, status_changed_at: string|null, created_at: string} * @phpstan-type MessageRecipientData array{email: string, name: string|null} * @phpstan-type MessageStatsData array{messages_transactional: int, messages_broadcast: int, messages_inbound: int, deliverability: float|int} @@ -96,6 +96,7 @@ * @phpstan-type MessageListResponse array{data: list, links: list, meta: array{path: string|null, per_page: int, next_cursor: string|null, next_cursor_url: string|null, prev_cursor: string|null, prev_cursor_url: string|null}} * @phpstan-type MessageResponse MessageData * @phpstan-type MessageEventsResponse array{data: list, links: list, meta: array{path: string|null, per_page: int, next_cursor: string|null, next_cursor_url: string|null, prev_cursor: string|null, prev_cursor_url: string|null}} + * @phpstan-type ProcessInboundMessageResponse array{data: array{message_id: string, status: 'queued', webhook_target_count: int}} * @phpstan-type ProjectListResponse array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} * @phpstan-type CreateProjectResponse array{data: ProjectData, message: string, api_token: string} * @phpstan-type ProjectResponse ProjectData diff --git a/tests/Endpoints/MessagesEndpointTest.php b/tests/Endpoints/MessagesEndpointTest.php index 41fd84c..276f69c 100644 --- a/tests/Endpoints/MessagesEndpointTest.php +++ b/tests/Endpoints/MessagesEndpointTest.php @@ -33,6 +33,12 @@ expect($this->endpoint->cancel('message-id')->status)->toBe('canceled'); }); +test('it processes a quarantined inbound message', function () { + $this->httpClient->shouldReceive('post')->once()->with('/v1/messages/message-id/process', [], [])->andReturn(['data' => ['message_id' => 'message-id', 'status' => 'queued', 'webhook_target_count' => 1]]); + + expect($this->endpoint->process('message-id')->data['status'])->toBe('queued'); +}); + test('it retrieves message events', function () { $query = ['include_machine_events' => true]; $this->httpClient->shouldReceive('get')->once()->with('/v1/messages/message-id/events', $query)->andReturn(['data' => []]); diff --git a/tests/SdkCoverageTest.php b/tests/SdkCoverageTest.php index d6c8452..640397e 100644 --- a/tests/SdkCoverageTest.php +++ b/tests/SdkCoverageTest.php @@ -29,6 +29,7 @@ ['team', 'message.show', MessagesEndpoint::class, 'retrieve'], ['team', 'rescheduleMessage', MessagesEndpoint::class, 'reschedule'], ['team', 'cancelScheduledMessage', MessagesEndpoint::class, 'cancel'], + ['team', 'processInboundMessage', MessagesEndpoint::class, 'process'], ['team', 'message.events', MessagesEndpoint::class, 'events'], ['team', 'message.source', MessagesEndpoint::class, 'source'], ['team', 'message.html', MessagesEndpoint::class, 'html'], @@ -67,7 +68,7 @@ ['team', 'webhook.showDelivery', WebhooksEndpoint::class, 'delivery'], ]; - expect($operations)->toHaveCount(52); + expect($operations)->toHaveCount(53); $missing = [];