agirem/clario-laravel

Laravel Mail transport and webhook consumer for the Clario email API.

Maintainers

Package info

github.com/Agirem/clario-laravel

pkg:composer/agirem/clario-laravel

Transparency log

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.1 2026-08-08 15:59 UTC

This package is auto-updated.

Last update: 2026-08-08 19:28:15 UTC


README

Laravel Mail transport and optional webhook consumer for the Clario email API.

Send with familiar Laravel Mailables:

Mail::to($user)->send(new OtpCodeMail($code));

Requirements

  • PHP 8.2+
  • Laravel 11 or 12
  • Clario API access (active trial, Solo, or Pro)
  • API key with emails:send

Installation

composer require agirem/clario-laravel

Publish config (optional):

php artisan vendor:publish --tag=clario-config

Configuration

.env:

MAIL_MAILER=clario
CLARIO_API_KEY=clario_live_...
# Optional when Laravel From matches a Clario address:
# CLARIO_MAIL_ADDRESS_ID=01HX...
CLARIO_BASE_URL=https://clario-mail.com/api/v1

config/mail.php:

'clario' => [
    'transport' => 'clario',
],

Sender resolution

The transport sends either mail_address_id or from to the Clario API, in this order:

  1. Message header X-Clario-Mail-Address-Idmail_address_id
  2. Map config('clario.mail_addresses')[from@email]mail_address_id
  3. Default CLARIO_MAIL_ADDRESS_IDmail_address_id
  4. Laravel / Symfony From address → from (API resolves the mailbox)

Display name is configured on the Clario address, not via Laravel from.name.

Idempotency (important for queued mail)

Every send includes an Idempotency-Key. Prefer a stable business key on critical mailables:

public function headers(): Headers
{
    return new Headers(
        text: [
            'X-Clario-Idempotency-Key' => 'otp-'.$this->user->id.'-'.$this->codeId,
        ],
    );
}

If omitted, the transport hashes the rendered message (stable across worker retries of the same content).

Attachments

Attachments are sent as multipart/form-data. Limits match the API: max 10 files, 5 MB each, allowed MIME types (PDF, JPEG/PNG/GIF, Word, Excel, CSV, plain text).

Webhooks (optional)

CLARIO_WEBHOOKS_ENABLED=true
CLARIO_WEBHOOK_SECRET=whsec_...
CLARIO_WEBHOOK_PATH=clario/webhook

Point your Clario Developer webhook to https://your-app.test/clario/webhook.

Events dispatched:

  • Clario\Laravel\Webhooks\Events\EmailQueued
  • EmailSent, EmailDelivered, EmailBounced, EmailFailed
  • EmailComplained, EmailOpened, EmailClicked, EmailReceived
Event::listen(EmailDelivered::class, function (EmailDelivered $event) {
    // $event->emailId, $event->data['metadata'], $event->eventId
});

Signatures use Clario-Signature: t=…,v1=… (HMAC-SHA256 of timestamp.rawBody). Invalid signatures return 401.

The route uses the api middleware group (no CSRF).

Metadata

public function headers(): Headers
{
    return new Headers(text: [
        'X-Clario-Metadata-order_id' => (string) $this->order->id,
    ]);
}

Exceptions

Clario\Laravel\Exceptions\ClarioTransportException exposes:

  • statusCode, errorCode, requestId
  • retryable — useful for queue $this->release() vs fail

Non-retryable examples: pro_plan_required, sender_not_allowed, quota exceeded, idempotency_conflict.

Testing

composer install
composer test

License

MIT