Send email with PHP
Send transactional email from PHP through PostStack.
PHP ships with cURL in the core, so you can talk to PostStack without Composer if you want a minimal dependency tree. Frameworks that already have a mailer — Symfony Mailer, WordPress, Laravel — are easier to point at the SMTP relay; there is a separate Laravel guide for Mailables, queues and notifications.
Quickstart#
Install the SDK
Nothing to install: the examples use PHP’s cURL extension, which most PHP builds include. Check that it is loaded:
bashphp -m | grep -i curl # prints "curl" when the extension is availableInitialize the client
php$apiKey = getenv('POSTSTACK_API_KEY'); $baseUrl = 'https://api.poststack.dev';Send an email
php<?php $apiKey = getenv('POSTSTACK_API_KEY'); $payload = json_encode([ 'from' => 'hello@yourdomain.com', 'to' => ['user@example.com'], 'subject' => 'Hello from PHP!', 'html' => '<h1>Welcome!</h1>', ]); $ch = curl_init('https://api.poststack.dev/emails'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/json', ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); echo $status, ' ', $response; // 202 {"id":"em_..."}Handle errors
php<?php class PoststackException extends RuntimeException { public int $statusCode; public ?string $requestId; public function __construct(int $statusCode, string $message, ?string $requestId = null) { parent::__construct($message); $this->statusCode = $statusCode; $this->requestId = $requestId; } } function send_email(array $payload, int $attempts = 3): array { $apiKey = getenv('POSTSTACK_API_KEY'); // One key for every attempt: a retry after a lost response replays the // original send instead of delivering a second copy. $idempotencyKey = bin2hex(random_bytes(16)); for ($i = 0; $i < $attempts; $i++) { $ch = curl_init('https://api.poststack.dev/emails'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 10, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/json', 'Idempotency-Key: ' . $idempotencyKey, ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); if ($response === false) { // network error or timeout sleep(2 ** $i); continue; } if ($status >= 200 && $status < 300) { return json_decode($response, true); } if ($status === 429 || $status >= 500) { sleep(2 ** $i); continue; } throw new PoststackException($status, (string) $response); } throw new RuntimeException('send_email retries exhausted'); }
Framework integrations#
Laravel
Set MAIL_MAILER=smtp, MAIL_HOST=smtp.poststack.dev, MAIL_PORT=587, MAIL_USERNAME=poststack and MAIL_PASSWORD to your API key in .env. Every Mailable, notification and queued mail then goes through PostStack. The Laravel guide has the full setup.
Symfony Mailer
Set MAILER_DSN=smtp://poststack:${POSTSTACK_API_KEY}@smtp.poststack.dev:587 in .env — the smtp:// scheme upgrades to STARTTLS on 587; use smtps://…@smtp.poststack.dev:465 for implicit TLS. Inject MailerInterface into your services and call $mailer->send($email).
WordPress
Install WP Mail SMTP, FluentSMTP, or any SMTP plugin. Point it at smtp.poststack.dev with username poststack and your API key as the password: port 587 with encryption TLS (STARTTLS), or port 465 with SSL. All transactional WordPress emails (admin alerts, password resets, WooCommerce order emails) start delivering through PostStack.
Common pitfalls#
Disabling SSL verification
CURLOPT_SSL_VERIFYPEER => false opens you to MITM attacks. Always leave SSL verification enabled — the PostStack TLS cert is from a public CA.
Misconfiguring MAIL_FROM_ADDRESS
Your From address must be on a verified domain. Laravel’s default hello@example.com is rejected. Update MAIL_FROM_ADDRESS in .env to your verified domain.
Holding cURL handles open per-request
For low-volume PHP apps the per-request handle is fine. For high-volume CLI workers, reuse a single cURL handle with curl_init once and curl_setopt per request to amortise the TLS handshake.
FAQ#
Do I need Composer or a package?
No. PHP’s built-in cURL is enough. For Laravel, you can also configure SMTP without adding a package.
Can I use this with WordPress?
Yes — use WP Mail SMTP or FluentSMTP. Point it at smtp.poststack.dev with username poststack and the API key as the password: port 587 with TLS (STARTTLS) or port 465 with SSL. Every WordPress email (admin, WooCommerce, Contact Form 7) then flows through PostStack.
How do I send email with Laravel?
Point Laravel’s SMTP mailer at smtp.poststack.dev in .env and keep using Mailables and Mail::to(...)->send(...). The Laravel guide covers queued mail, notifications, attachments and the HTTP API.
Reference#
The docs this guide builds on:
- SDKs — every official client, its retries and idempotency keys
- SMTP relay — hosts, ports, TLS modes and the
X-PostStack-*headers - Emails API — every send field, attachments, scheduling and batch sends
- Templates — stored templates with variables
- Webhooks — event types, payloads and signature verification
- Suppressions — what happens to an address after a hard bounce or complaint
Ready to send from PHP?
Create a free account and an API key — no card needed.