PHPackages                             lettermint/lettermint-laravel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. lettermint/lettermint-laravel

ActiveLibrary[API Development](/categories/api)

lettermint/lettermint-laravel
=============================

Official Lettermint driver for Laravel

2.2.0(1w ago)1190.2k↑176.7%31MITPHPPHP ^8.2CI passing

Since Apr 22Pushed 1w ago1 watchersCompare

[ Source](https://github.com/lettermint/lettermint-laravel)[ Packagist](https://packagist.org/packages/lettermint/lettermint-laravel)[ Docs](https://github.com/lettermint/lettermint-laravel)[ RSS](/packages/lettermint-lettermint-laravel/feed)WikiDiscussions main Synced 3d ago

READMEChangelog (10)Dependencies (70)Versions (25)Used By (1)

Official Lettermint driver for Laravel
======================================

[](#official-lettermint-driver-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/3d856da371743ba3bd374f4c992a152b58f004417247cf64edb42c82d216a1df/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c65747465726d696e742f6c65747465726d696e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/lettermint/lettermint-laravel)[![GitHub Tests Action Status](https://camo.githubusercontent.com/5c185e74bace7f84c49ec16eaf94b44bc1568360243904d5c407fafab039b440/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6c65747465726d696e742f6c65747465726d696e742d6c61726176656c2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/lettermint/lettermint-laravel/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/ca6c10024b4594c0ebd4489d6dbc9e2537ff4f8b15658cdd8fd639b2a3d118eb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6c65747465726d696e742f6c65747465726d696e742d6c61726176656c2f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/lettermint/lettermint-laravel/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/c5d850754e9c2f86a158bc8e1134eecd3ab3ec8f24698a5d45c82d8935f32add/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c65747465726d696e742f6c65747465726d696e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/lettermint/lettermint-laravel)[![Join our Discord server](https://camo.githubusercontent.com/53ac78394b2bfdedbab92b06b9aa0593d5334263ac202bcb761913f2cbde04c3/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f313330353531303039353538383831393033353f6c6f676f3d646973636f7264266c6f676f436f6c6f723d656565266c6162656c3d446973636f7264266c6162656c436f6c6f723d34363463653526636f6c6f723d3044304532382663616368655365636f6e64733d3433323030)](https://lettermint.co/r/discord)

Easily integrate [Lettermint](https://lettermint.co) into your Laravel application.

---

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 9 or higher

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require lettermint/lettermint-laravel
```

You can publish the config file with:

```
php artisan vendor:publish --tag="lettermint-config"
```

This creates a `config/lettermint.php` file where you can add your project and API tokens.

Configuration
-------------

[](#configuration)

### Setting your project token

[](#setting-your-project-token)

Add your Lettermint project token in your `.env` file. This token is used for sending email through Laravel mail:

```
LETTERMINT_PROJECT_TOKEN=your-lettermint-project-token
```

The legacy `LETTERMINT_TOKEN` environment variable is still supported, but `LETTERMINT_PROJECT_TOKEN` is preferred for new applications.

Or update the `config/lettermint.php` file as needed.

### Setting your API token

[](#setting-your-api-token)

Add your Lettermint API token in your `.env` file when you want to use the Team API from your Laravel application:

```
LETTERMINT_API_TOKEN=your-lettermint-api-token
```

### Setting the request timeout

[](#setting-the-request-timeout)

The default Lettermint API request timeout is 15 seconds. You can override it in your `.env` file:

```
LETTERMINT_TIMEOUT=30
```

### Add the transport

[](#add-the-transport)

In your `config/mail.php`, set the default option to lettermint:

```
        'lettermint' => [
            'transport' => 'lettermint',
        ],
```

### Add the service

[](#add-the-service)

In your `config/services.php`, add the Lettermint service:

```
    'lettermint' => [
        'token' => env('LETTERMINT_PROJECT_TOKEN', env('LETTERMINT_TOKEN')),
        'api_token' => env('LETTERMINT_API_TOKEN'),
    ],
```

### Using the Team API

[](#using-the-team-api)

Resolve the PHP SDK API client from Laravel's container:

```
use Lettermint\Client\ApiClient;

$projects = app(ApiClient::class)->projects->list();
$team = app('lettermint.api')->team->retrieve();
```

### Using Routes

[](#using-routes)

If you would like to specify the Lettermint route that should be used by a given mailer, you may add the `route_id` configuration option to the mailer's configuration array in your `config/mail.php` file:

```
'lettermint' => [
    'transport' => 'lettermint',
    'route_id' => env('LETTERMINT_ROUTE_ID'),
],
```

### Multiple mailers with different routes

[](#multiple-mailers-with-different-routes)

You can configure multiple mailers using the same Lettermint transport but with different route IDs:

```
// config/mail.php
'mailers' => [
    'lettermint_marketing' => [
        'transport' => 'lettermint',
        'route_id' => env('LETTERMINT_MARKETING_ROUTE_ID'),
    ],
    'lettermint_transactional' => [
        'transport' => 'lettermint',
        'route_id' => env('LETTERMINT_TRANSACTIONAL_ROUTE_ID'),
    ],
],
```

Then use them in your application:

```
Mail::mailer('lettermint_marketing')->to($user)->send(new MarketingEmail());
Mail::mailer('lettermint_transactional')->to($user)->send(new TransactionalEmail());
```

Idempotency Support
-------------------

[](#idempotency-support)

The Lettermint Laravel driver prevents duplicate email sends by using idempotency keys. This is especially useful when emails are sent from queued jobs that might be retried.

### Configuration Options

[](#configuration-options)

You can configure idempotency behavior per mailer in your `config/mail.php`:

```
'mailers' => [
    'lettermint' => [
        'transport' => 'lettermint',
        'idempotency' => true, // Enable automatic content-based idempotency
        'idempotency_window' => 86400, // Window in seconds (default: 24 hours)
    ],
    'lettermint_marketing' => [
        'transport' => 'lettermint',
        'route_id' => 'marketing',
        'idempotency' => false, // Disable automatic idempotency
    ],
],
```

#### Idempotency Options:

[](#idempotency-options)

- **`idempotency`**: Enable/disable automatic content-based idempotency
    - `true`: Generates idempotency keys based on email content
    - `false` (default): Disables automatic idempotency (user headers still work)
- **`idempotency_window`**: Time window in seconds for deduplication
    - Default: `86400` (24 hours to match Lettermint API retention)
    - Set to match your needs (e.g., `3600` for 1 hour, `300` for 5 minutes)
    - When set to `86400` or higher, emails with identical content are permanently deduplicated within the API retention period

### Automatic Idempotency

[](#automatic-idempotency)

When `idempotency` is `true`, the driver generates a unique key based on:

- Email subject, recipients (to, cc, bcc), and content
- Sender address (to differentiate between different sending contexts)
- Time window (if less than 24 hours)

This ensures:

- Identical emails are only sent once within the configured time window
- Retried queue jobs won't create duplicate emails
- Different emails or the same email after the time window will be sent normally

### Custom Idempotency Keys

[](#custom-idempotency-keys)

You can override any configuration by setting a custom idempotency key in the email headers:

```
Mail::send('emails.welcome', $data, function ($message) {
    $message->to('user@example.com')
        ->subject('Welcome!')
        ->getHeaders()->addTextHeader('Idempotency-Key', 'welcome-user-123');
});
```

**Priority order** (highest to lowest):

1. `Idempotency-Key` header in the email (always respected, overrides any config)
2. Automatic Message-ID (if `idempotency` is `true`)
3. No idempotency (if `idempotency` is `false`)

**Important:** The `idempotency: false` configuration only disables *automatic* idempotency. User-provided `Idempotency-Key` headers are always respected, giving users full control on a per-email basis.

Tags and Metadata
-----------------

[](#tags-and-metadata)

The Lettermint Laravel driver supports adding tags and metadata to your emails for better organization, tracking, and analytics.

### Using Tags

[](#using-tags)

Tags help you categorize and filter your emails in the Lettermint dashboard. You can add tags using Laravel's native mailable methods:

#### Method 1: Using Laravel's tag() method (Recommended)

[](#method-1-using-laravels-tag-method-recommended)

```
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;

Mail::send((new WelcomeEmail($user))
    ->tag('onboarding')
);
```

#### Method 2: Using the envelope method in your Mailable

[](#method-2-using-the-envelope-method-in-your-mailable)

```
use Illuminate\Mail\Mailables\Envelope;

class WelcomeEmail extends Mailable
{
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Welcome to our platform!',
            tags: ['onboarding'], // Only one tag is allowed
        );
    }
}
```

#### Method 3: Using custom header (backward compatibility)

[](#method-3-using-custom-header-backward-compatibility)

To minimise confusion with the way of tagging emails sent via the SMTP relay, the Lettermint Laravel driver also supports the `X-LM-Tag` header. This will be converted to the `TagHeader` envelope method automatically.

```
use Illuminate\Mail\Mailables\Headers;

class WelcomeEmail extends Mailable
{
    public function headers(): Headers
    {
        return new Headers(
            text: [
                'X-LM-Tag' => 'onboarding',
            ],
        );
    }
}
```

### Using Metadata

[](#using-metadata)

Metadata allows you to attach custom key-value pairs to your emails for enhanced tracking and analytics:

#### Method 1: Using Laravel's metadata() method (Recommended)

[](#method-1-using-laravels-metadata-method-recommended)

```
Mail::send((new OrderConfirmation($order))
    ->metadata('order_id', $order->id)
    ->metadata('customer_id', $order->customer_id)
);
```

#### Method 2: Using the envelope method

[](#method-2-using-the-envelope-method)

```
public function envelope(): Envelope
{
    return new Envelope(
        subject: 'Order Confirmation',
        metadata: [
            'order_id' => $this->order->id,
            'customer_id' => $this->order->customer_id,
            'order_total' => $this->order->total,
        ],
    );
}
```

### Combining Tags and Metadata

[](#combining-tags-and-metadata)

You can use both tags and metadata together:

```
Mail::send((new OrderShipped($order))
    ->tag('transactional')
    ->metadata('order_id', $order->id)
    ->metadata('tracking_number', $order->tracking_number)
);
```

Or in your mailable:

```
public function envelope(): Envelope
{
    return new Envelope(
        subject: 'Your order has shipped!',
        tags: ['transactional', 'shipping'],
        metadata: [
            'order_id' => $this->order->id,
            'tracking_number' => $this->order->tracking_number,
            'carrier' => $this->order->carrier,
        ],
    );
}
```

### Note on Compatibility

[](#note-on-compatibility)

- The driver supports Laravel's native `tag()` and `metadata()` methods (Laravel 9+)
- The `X-LM-Tag` header is supported for backward compatibility
- When both `TagHeader` and `X-LM-Tag` are present, the `TagHeader` takes precedence

Webhooks
--------

[](#webhooks)

The package provides built-in support for handling Lettermint webhooks with automatic signature verification.

### Configuration

[](#configuration-1)

Add your webhook signing secret to your `.env` file:

```
LETTERMINT_WEBHOOK_SECRET=your-webhook-signing-secret
```

You can optionally configure the route prefix and timestamp tolerance:

```
LETTERMINT_WEBHOOK_PREFIX=lettermint
LETTERMINT_WEBHOOK_TOLERANCE=300
```

Or publish the config file and modify the webhooks section:

```
// config/lettermint.php
'webhooks' => [
    'secret' => env('LETTERMINT_WEBHOOK_SECRET'),
    'prefix' => env('LETTERMINT_WEBHOOK_PREFIX', 'lettermint'),
    'tolerance' => env('LETTERMINT_WEBHOOK_TOLERANCE', 300),
],
```

### Webhook Endpoint

[](#webhook-endpoint)

The package automatically registers a webhook endpoint at:

```
POST /{prefix}/webhook

```

By default, this is `POST /lettermint/webhook`. Configure this URL in your Lettermint dashboard.

### Handling Webhook Events

[](#handling-webhook-events)

The package dispatches Laravel events for each webhook type. Listen to specific events in your `EventServiceProvider` or using closures:

```
use Lettermint\Laravel\Events\MessageDelivered;
use Lettermint\Laravel\Events\MessageHardBounced;
use Lettermint\Laravel\Events\MessageSpamComplaint;

// In EventServiceProvider
protected $listen = [
    MessageDelivered::class => [
        HandleEmailDelivered::class,
    ],
    MessageHardBounced::class => [
        HandleEmailBounced::class,
    ],
];

// Or using closures
Event::listen(MessageDelivered::class, function (MessageDelivered $event) {
    Log::info('Email delivered', [
        'message_id' => $event->data->messageId,
        'recipient' => $event->data->recipient,
        'status_code' => $event->data->response->statusCode,
    ]);
});

Event::listen(MessageHardBounced::class, function (MessageHardBounced $event) {
    // Handle permanent bounce - consider disabling the recipient
    $recipient = $event->data->recipient;
    $reason = $event->data->response->content;
});
```

### Available Events

[](#available-events)

Event ClassWebhook TypeDescription`MessageCreated``message.created`Message accepted for processing`MessageSent``message.sent`Message sent to recipient server`MessageDelivered``message.delivered`Message successfully delivered`MessageHardBounced``message.hard_bounced`Permanent delivery failure`MessageSoftBounced``message.soft_bounced`Temporary delivery failure`MessageSpamComplaint``message.spam_complaint`Recipient reported spam`MessageFailed``message.failed`Processing failure`MessageSuppressed``message.suppressed`Message suppressed`MessagePolicyRejected``message.policy_rejected`Rejected by sending policy`MessageUnsubscribed``message.unsubscribed`Recipient unsubscribed`MessageOpened``message.opened`Recipient opened the email`MessageClicked``message.clicked`Recipient clicked a link`MessageInbound``message.inbound`Inbound email received`WebhookTest``webhook.test`Test event from dashboard### Listening to All Events

[](#listening-to-all-events)

You can listen to all webhook events using the base class:

```
use Lettermint\Laravel\Events\LettermintWebhookEvent;

Event::listen(LettermintWebhookEvent::class, function (LettermintWebhookEvent $event) {
    Log::info('Webhook received', [
        'type' => $event->getEnvelope()->event->value,
        'id' => $event->getEnvelope()->id,
    ]);
});
```

### Event Structure

[](#event-structure)

Each event has two main properties:

- `$event->envelope` - Common webhook envelope (id, event type, timestamp)
- `$event->data` - Event-specific typed payload

```
// Envelope (common to all events)
$event->envelope->id;        // Webhook event ID (string)
$event->envelope->event;     // WebhookEventType enum
$event->envelope->timestamp; // DateTimeImmutable

// Data (typed per event)
// For MessageDelivered:
$event->data->messageId;              // string
$event->data->recipient;              // string
$event->data->response->statusCode;   // int
$event->data->response->content;      // string|null
$event->data->metadata;               // array
$event->data->tag;                    // string|null
```

### Typed Event Data

[](#typed-event-data)

Each event type has its own typed data class:

EventData Properties`MessageDelivered``messageId`, `recipient`, `response`, `metadata`, `tag``MessageHardBounced``messageId`, `recipient`, `response`, `metadata`, `tag``MessageCreated``messageId`, `from`, `to`, `cc`, `bcc`, `subject`, `metadata`, `tag``MessagePolicyRejected``messageId`, `subject`, `reason`, `score`, `spamSymbols`, `metadata`, `tag``MessageOpened``messageId`, `subject`, `recipient`, `openedAt`, `firstOpen`, `deviceType`, `clientType`, `bot``MessageClicked``messageId`, `subject`, `recipient`, `clickedAt`, `destinationUrl`, `linkIndex`, `firstClick`, `bot``MessageInbound``route`, `messageId`, `from`, `to`, `subject`, `body`, `headers`, `attachments`, `isSpam`, `spamScore``WebhookTest``message`, `webhookId`, `timestamp`### Helper Methods

[](#helper-methods)

The `WebhookEventType` enum provides helper methods:

```
$event->envelope->event->isBounce();        // true for hard/soft bounces
$event->envelope->event->isDeliveryIssue(); // true for bounces, failed, suppressed
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Bjarn Bronsveld](https://github.com/bjarn)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance98

Actively maintained with recent releases

Popularity42

Moderate usage in the ecosystem

Community16

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 80.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~25 days

Recently: every ~41 days

Total

18

Last Release

13d ago

Major Versions

0.1.1 → 1.0.02025-06-14

1.6.0 → 2.0.02026-05-11

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/14638441?v=4)[Bjarn Bronsveld](/maintainers/bjarn)[@bjarn](https://github.com/bjarn)

---

Top Contributors

[![bjarn](https://avatars.githubusercontent.com/u/14638441?v=4)](https://github.com/bjarn "bjarn (53 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (9 commits)")[![heikokrebs](https://avatars.githubusercontent.com/u/230852?v=4)](https://github.com/heikokrebs "heikokrebs (3 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

laravellettermintlettermint-laravel

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/lettermint-lettermint-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/lettermint-lettermint-laravel/health.svg)](https://phpackages.com/packages/lettermint-lettermint-laravel)
```

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k11.2M100](/packages/dedoc-scramble)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M47](/packages/spatie-laravel-pdf)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.8k3](/packages/defstudio-telegraph)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5021.9k](/packages/simplestats-io-laravel-client)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

44855.7k](/packages/harris21-laravel-fuse)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
