Skip to content
← All packages

Postal integration for Laravel

Postal mail server integration for Laravel: a typed multi-server send transport, verified webhooks for delivery, bounce, open and click events, inbound email and an idempotent per-message status store.

Postal is a self-hosted mail server with an HTTP send API and signed webhooks. This package treats it as a typed delivery bus rather than a fire-and-forget mail driver: you send through a fully-typed client or transparently via MAIL_MAILER=postal, and you get the delivery outcome back as Laravel events instead of guessing.

What It Covers

Typed sending

Send via the mail transport or a typed client, with retries, typed exceptions and correct handling of Postal returning HTTP 200 with an error envelope.

Three connection types

Per server: api (structured JSON), smtp-api (raw RFC 2822 over the HTTP API) and smtp (classic submission).

Verified webhooks

RSA signatures checked over the raw request body, deliveries deduplicated on Postal's webhook uuid, and one typed Laravel event per Postal event type.

Delivery status store

An idempotent row per message with latest status, open and click counters and the owning model, plus a deduplicated event log.

Inbound email

Postal routes deliver to a signed endpoint that becomes a typed event with bodies, headers, attachments and raw source.

Multiple servers

One config entry per Postal mail server addressed by name, or provisioned dynamically from a database via a registry contract.

Diagnosis built in

A postal:doctor command checks servers, keys, routes, store tables, the mailer and live connectivity with CI-friendly exit codes, so a misconfigured key or an unregistered webhook route surfaces before your users find it. postal:ping, postal:tail and postal:message cover the day-to-day: is it reachable, what is arriving, and what happened to this one message.

Requirements

PHP 8.4+, Laravel 12 or 13. Tested against Postal 3.x. This site sends its own mail through it.