Skip to content

Send emails with PHP / Laravel

Learn how to send transactional emails using PostStack and PHP / Laravel.

PHP ships with cURL in the core, so you can talk to PostStack without Composer if you want a minimal dependency tree. For Laravel, configuring PostStack as the mail transport in `config/mail.php` is usually the cleanest path — every `Mail::send`, `Notification::route('mail', ...)`, and queued mailable goes through PostStack with no per-call changes.

1. Install the SDK

bash
# No external packages needed — uses built-in cURL

2. Initialize the client

php
$apiKey = getenv('POSTSTACK_API_KEY');
$baseUrl = 'https://api.poststack.dev';

3. 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);
curl_close($ch);

echo $response;

4. Handle errors

PHP / Laravel idioms for error handling, retries, and structured logging when calling the PostStack API.

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');

    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',
            ],
            CURLOPT_HEADER => true,
        ]);
        $response = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        curl_close($ch);

        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 mail transport

In `config/mail.php`, add a `poststack` mailer with `transport: smtp`, `host: smtp.poststack.dev`, `port: 587`, `encryption: tls`, `username: poststack`, `password: env("POSTSTACK_API_KEY")`. Set `MAIL_MAILER=poststack` in `.env`. Every `Mail::send` and `Notification::send` now flows through PostStack — no controller changes needed.

Laravel queued mail

Queued mailables (`ShouldQueue`) work unchanged. The queue worker picks up the job, opens an SMTP connection to PostStack, and sends. Use Horizon to monitor throughput and retry failures.

Symfony Mailer

Configure the `MAILER_DSN` to `smtp://poststack:%env(POSTSTACK_API_KEY)%@smtp.poststack.dev:587`. 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:587` with username `poststack` and your API key. 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.

Notes

  • Uses built-in PHP cURL — no Composer packages required
  • For Laravel, you can also configure PostStack as an SMTP transport in config/mail.php

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:587 with the API key as the password. Every WordPress email (admin, WooCommerce, contact-form-7) flows through PostStack.

What about Laravel queued mailables?

They work unchanged. The queue worker handles the SMTP connection and retries. Use Horizon for visibility.

Related guides

Ready to send emails with PHP / Laravel?

Create a free account and get your API key in under a minute.