PHPackages                             leadm/leadmail - 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. [Mail &amp; Notifications](/categories/mail)
4. /
5. leadm/leadmail

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

leadm/leadmail
==============

Laravel SDK for leadMail email sending and verification service

v2.2.1(2mo ago)011↓81%MITPHPPHP ^8.2

Since Mar 4Pushed 2mo agoCompare

[ Source](https://github.com/leadmnik/leadmail-sdk)[ Packagist](https://packagist.org/packages/leadm/leadmail)[ Docs](https://git.leadmagnet.dev/LeadMagnet/leadmail-sdk)[ RSS](/packages/leadm-leadmail/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (17)Versions (8)Used By (0)

LeadMail SDK for Laravel
========================

[](#leadmail-sdk-for-laravel)

Laravel package for sending emails and verifying email addresses through the [leadMail](https://mail.leadmagnet.dev) service.

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

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13

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

[](#installation)

```
composer require leadm/leadmail
```

Add these to your `.env`:

```
LEADMAIL_URL=https://mail.leadmagnet.dev
LEADMAIL_TOKEN=lm_your_api_token_here
MAIL_MAILER=leadmail
```

Then run the installer:

```
php artisan leadmail:install
```

That's the whole setup. The command publishes the config, registers this app's failure-webhook URL with the service, and writes the generated `LEADMAIL_WEBHOOK_SECRET` into your `.env` — no secret to copy by hand. It runs without prompts, so it's safe in CI/Ploi deploy hooks. See [Receiving Failure Webhooks](#receiving-failure-webhooks) for what it wires up.

> If you only need sending/verification and not webhooks, you can skip the installer and just publish the config with `php artisan vendor:publish --tag=leadmail-config`.

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

[](#configuration)

Everything is configured by environment variables; the published `config/leadmail.php` reads from them. All of these are optional and have sensible defaults:

```
LEADMAIL_TIMEOUT=30
LEADMAIL_VERIFY_SSL=true
LEADMAIL_AUTO_TENANT=true

# Retry transient failures (connection errors, 429/5xx) on idempotent calls.
# Sends are never retried automatically, to avoid duplicate emails.
LEADMAIL_RETRIES=2
LEADMAIL_RETRY_DELAY_MS=200

# Set automatically by `php artisan leadmail:install` — you normally don't edit
# these by hand. The secret signs incoming webhooks; the route is where they land.
LEADMAIL_WEBHOOK_SECRET=whsec_...
LEADMAIL_WEBHOOK_ROUTE=/webhooks/leadmail
```

Usage
-----

[](#usage)

### Send Emails via Mail Driver

[](#send-emails-via-mail-driver)

Set `leadmail` as your mail driver in `.env`:

```
MAIL_MAILER=leadmail
```

Then use Laravel's `Mail` facade as usual:

```
Mail::to('user@example.com')->send(new WelcomeMail());
```

### Send Emails via API

[](#send-emails-via-api)

```
LeadMail::sendEmail([
    'from' => ['email' => 'hello@yourdomain.com', 'name' => 'Your App'],
    'to' => [['email' => 'user@example.com', 'name' => 'User']],
    'subject' => 'Welcome!',
    'html_body' => 'Welcome to our app',
]);
```

### Verify Email Addresses

[](#verify-email-addresses)

```
$result = LeadMail::verifyEmail('user@example.com');

if ($result['data']['valid']) {
    // Email is deliverable
}
```

### Validation Rule

[](#validation-rule)

Use the `leadmail_verify` rule in your form requests:

```
public function rules(): array
{
    return [
        'email' => ['required', 'email', 'leadmail_verify'],
    ];
}
```

### Get Allowed Sender Domains

[](#get-allowed-sender-domains)

```
$domains = LeadMail::getDomains();
// ['yourdomain.com', 'anotherdomain.com']
```

Error Handling
--------------

[](#error-handling)

Every API failure is raised as a typed exception so you can handle it reliably from the client side. `LeadMail::verifyEmail()` is the exception — it fails open (returns `status: "unknown"`) so a verification outage never blocks sign-ups.

ExceptionWhen`LeadM\LeadMail\Exceptions\LeadMailRequestException`The service returned an error response (4xx/5xx).`LeadM\LeadMail\Exceptions\LeadMailConnectionException`The service could not be reached (DNS/connection/timeout).`LeadM\LeadMail\Exceptions\LeadMailException`Base class for both of the above; catch this to handle any failure.```
use LeadM\LeadMail\Exceptions\LeadMailRequestException;
use LeadM\LeadMail\Exceptions\LeadMailConnectionException;

try {
    LeadMail::sendEmail([...]);
} catch (LeadMailRequestException $e) {
    $e->statusCode();        // e.g. 422, 502
    $e->errorCode();         // e.g. "TRANSPORT_ERROR" (from the API envelope)
    $e->logId();             // the email log id, when available
    $e->validationErrors();  // ['from.email' => ['...']] on a 422
    $e->isValidationError();
    $e->isAuthenticationError();
} catch (LeadMailConnectionException $e) {
    // Service unreachable — safe to queue and retry yourself.
}
```

Idempotent calls (`getDomains`, `verifyEmail`) automatically retry transient failures (connection errors and `429`/`5xx`) with exponential backoff. **Sends are never retried automatically** — a retry after a dropped connection could deliver the same email twice. Retry sends yourself via a queued job if you need to.

Receiving Failure Webhooks
--------------------------

[](#receiving-failure-webhooks)

leadMail POSTs a signed `email.failed` webhook to your app when a send ultimately fails. **This works out of the box — no route or config required.**

### Setup: one command

[](#setup-one-command)

With `LEADMAIL_TOKEN` set in your `.env`, run:

```
php artisan leadmail:install
```

It runs without prompts (safe for Ploi/CI) and:

1. publishes the config,
2. registers your webhook URL with the leadMail service over the API (authenticated by your token), derived from `APP_URL` + the configured webhook route,
3. writes the generated `LEADMAIL_WEBHOOK_SECRET` into your `.env`.

That's it. The SDK **auto-registers the receiving route** (`/webhooks/leadmail` by default), which verifies the HMAC signature and **logs every failure by default**. Nothing else to wire up.

Options:

- `--url=https://your-app.com/custom/path` — override the derived URL.
- `--rotate` — generate and store a fresh signing secret.

The secret is generated server-side and returned only once, at registration.

### Custom handling

[](#custom-handling)

To do more than log (e.g. flag a contact, alert a channel), listen for the `LeadMailWebhookReceived` event:

```
use LeadM\LeadMail\Events\LeadMailWebhookReceived;

Event::listen(function (LeadMailWebhookReceived $received) {
    $event = $received->event;

    if ($event->isFailure()) {
        // $event->logId, $event->errorCode, $event->errorMessage,
        // $event->from, $event->to, $event->subject, $event->metadata
    }
});
```

### Customising or replacing the route

[](#customising-or-replacing-the-route)

- `LEADMAIL_WEBHOOK_ROUTE` — change the path (keep it in sync with the registered URL via `leadmail:install`).
- Set `leadmail.webhook_route` to `null` to disable auto-registration and handle the request yourself with `LeadMailWebhook::parse($request)` (verifies the signature against the raw body, throws `InvalidWebhookSignatureException` on mismatch; `verify()` returns a boolean instead).

Multi-Tenancy
-------------

[](#multi-tenancy)

If your app uses [stancl/tenancy](https://tenancyforlaravel.com), the SDK automatically includes the current tenant ID in API requests via the `X-Tenant-Id` header. Disable this with:

```
LEADMAIL_AUTO_TENANT=false
```

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance86

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 85.7% 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 ~16 days

Recently: every ~23 days

Total

7

Last Release

70d ago

Major Versions

v0.1.0 → v2.0.02026-03-04

1.x-dev → v2.1.02026-06-08

PHP version history (2 changes)v0.1.0PHP ^8.2

v1.0.0PHP ^8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/244831156?v=4)[Niklas](/maintainers/leadmnik)[@leadmnik](https://github.com/leadmnik)

---

Top Contributors

[![netlas](https://avatars.githubusercontent.com/u/2729682?v=4)](https://github.com/netlas "netlas (6 commits)")[![leadmnik](https://avatars.githubusercontent.com/u/244831156?v=4)](https://github.com/leadmnik "leadmnik (1 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/leadm-leadmail/health.svg)

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

###  Alternatives

[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

79227.1M228](/packages/laravel-mcp)[spatie/laravel-export

Create a static site bundle from a Laravel app

679153.2k7](/packages/spatie-laravel-export)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k161.4k2](/packages/mike-bronner-laravel-model-caching)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

265.2k](/packages/aedart-athenaeum)[forjedio/inertia-table

Backend-driven dynamic tables for Laravel + Inertia.js

272.0k](/packages/forjedio-inertia-table)[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.

5226.7k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

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