Download the PHP package postilio/postilio-php without Composer
On this page you can find all versions of the php package postilio/postilio-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download postilio/postilio-php
More information about postilio/postilio-php
Files in postilio/postilio-php
Package postilio-php
Short Description The official PHP client for the Postilio API: European transactional email.
License MIT
Homepage https://postilio.eu
Informations about the package postilio-php
Postilio for PHP
The official PHP client for the Postilio API: European transactional email. Send email, read messages and their events, manage domains, suppressions and webhooks, read your usage, and verify webhook signatures.
PHP 8.2 or later. It depends on nothing but the PSR HTTP interfaces: bring the PSR-18 client your framework already has, or let it send with curl. No Guzzle, no global state.
Not published on Packagist yet; the API is in alpha. See CHANGELOG.md.
Install
Quickstart
Create an API key in the portal under Keys & SMTP. A test key (pk_test_…) goes through every check but never
delivers, so start with one. The sender must be on a verified domain of the key's project.
Create one PostilioClient and reuse it. More in the examples/.
The HTTP client
Without a client of your own, the SDK sends with curl (ext-curl), with a 30-second timeout per request and 10 seconds
to connect, no redirects, and HTTP(S) only:
Or pass any PSR-18 client with its PSR-17 request and stream factories; its own timeouts and proxy settings then apply:
With php-http/discovery installed, you may leave out the factories. Every setting is a constructor argument: nothing global, so two clients with different keys can live side by side.
Sending
SendEmailRequest takes everything POST /v1/emails does:
Attachments take the file's bytes; the client encodes them. The API checks every field and answers with an exception
when it refuses one (see Errors); the SDK does not repeat those rules. A test key checks sendAt but
simulates the message at once, so with a test key nothing waits and cancelEmail() throws a ConflictException
(email_not_scheduled).
sendTestEmail() sends one email to an address of your own (a member's, or one confirmed for test mail), to check a
domain end to end.
Sending safely twice: idempotency
A request can time out after Postilio accepted it. sendEmail() therefore always sends an Idempotency-Key: one it
makes per call, so its own retries never send twice. Pass your own key to be safe across restarts and queues too:
Within 24 hours, the same key with the same request answers as the first time and sends nothing; the same key with
another request throws a ConflictException (idempotency_key_reused_with_different_request).
Errors
An error answer throws a Postilio\Exception\PostilioException, or a subclass per status:
| Status | Exception |
|---|---|
| 400 | ValidationException, with errors per field |
| 401 | AuthenticationException |
| 403 | PermissionException |
| 404 | NotFoundException |
| 409 | ConflictException |
| 413 | PayloadTooLargeException |
| 422 | UnprocessableException |
| 429 | RateLimitException, with retryAfter; PlanLimitException for the plan's month, day or minute |
| 5xx | ServerException, with the traceId to quote to support |
| none | TransportException: the connection failed or timed out |
errorCode holds the API's stable code and errorMessage the sentence some codes come with; error() gives the code as
a Postilio\Enum\ErrorCode, or null for one this version does not know yet. Postilio may add codes, so handle an
unknown one by the exception's class:
Messages name the call and the status, never the API key.
Retries
Off by default. With maxRetries, the client tries a call again after a 408, 429, 500, 502, 503, 504 or a network
failure, but only when sending it again cannot do anything twice: a GET, or a send, which carries an
Idempotency-Key. Creating, changing and deleting are never retried, and neither is a test email.
It waits as long as Retry-After says, or else 0.5, 1, 2 … seconds with some random spread, never longer than
maxRetryDelay. An answer that asks to wait longer (the sandbox's daily limit, say) throws at once with retryAfter
set, rather than blocking your request. The curl timeout applies to each attempt.
Statuses and other values
Statuses, event types, reasons and modes are backed enums in Postilio\Enum (EmailStatus, DomainStatus,
DmarcStatus, WebhookEventType, EmailEventReason, …). Postilio may add values: a model keeps a value it does not
know as a string, so a field such as EmailDetails::$status is EmailStatus|string. Compare with the enum case:
Models are immutable: readonly properties, a public constructor (handy in your own tests) and fromArray().
Domains, suppressions, webhooks and usage
These need a key with the matching scope (domains:manage, suppressions:manage, webhooks:manage, usage:read), and
a live key for all but reading domains: listDomains() and getDomain() need only domains:read (which domains:manage
includes) and also work with a test key, for code that only shows a sender domain's status.
Receiving webhooks
Verify every delivery before you trust it. WebhookVerifier implements the
Standard Webhooks scheme: a constant-time comparison, a timestamp within five
minutes either way (so a captured request cannot be replayed later), and both signatures during a secret rotation.
Verify the raw body, before parsing it.
Testing your code
Use a test key in your own tests and CI: nothing is delivered, and the recipient decides the outcome
(delivered@, bounced@, deferred@, complained@, [email protected]). Switching to live is
swapping the key. To test without the network, pass a PSR-18 client that answers what you need.
Versioning
Semantic versioning. Until 1.0 a minor version may change the public API; every change is in
CHANGELOG.md. Classes and members marked @internal (Postilio\Internal\*) are not part of it.
Contributing and security
See SECURITY.md.
License
MIT.
All versions of postilio-php with dependencies
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0