Skip to content

The email API built for Laravel.

Keep your Mailables and Mail::to(). Lettr adds templates your team edits without a deploy, generated types for every merge tag, and queued sends that never go out twice.

Free for 3,000 emails a month. No credit card. Laravel 10 to 13, PHP 8.4+.

From install to a typed, queued send.

Four steps. Two of them are artisan commands, and the last one is the code you already write.

  1. composer require lettr/lettr-laravel

    Laravel 10 to 13 on PHP 8.4+. Adds the lettr mail transport.

  2. php artisan lettr:init

    Writes your API key, sets MAIL_MAILER=lettr and checks your domain's DNS.

  3. php artisan lettr:generate-dtos

    Typed DTOs from your template merge tags.

  4. Mail::to($customer) ->queue(new OrderShipped(...))

    Queued and retry-safe by default. A retry replays the original send.

The template lives in Lettr. The types live in your app.

Behind this text: the enum and DTO that lettr:generate-dtos writes for you. In front: the Mailable that uses them. Your team edits the email in Lettr, your IDE and PHPStan check every variable.

Type safety guide
<?php

namespace App\Mail;

use App\Dto\Lettr\OrderShippedData;
use Illuminate\Mail\Mailables\Envelope;
use Lettr\Laravel\Mail\LettrMailable;

class OrderShipped extends LettrMailable
{
    // The design lives in Lettr. Edit it in the dashboard, no deploy needed.
    protected ?string $templateSlug = 'order-shipped';

    public function __construct(
        public OrderShippedData $data,
    ) {}

    // No subject here, so the subject set on the template in Lettr is used.
    public function envelope(): Envelope
    {
        return new Envelope;
    }

    /**
     * Merge tags sent to the Lettr template.
     *
     * @return array<string, mixed>
     */
    public function withMergeTags(): array
    {
        return $this->data->toArray();
    }
}

You own the code. Your team owns the words.

Copy changes stop being tickets. Your team edits the email in Lettr, and lettr:pull brings it into your repo as Blade.

The order-shipped email in the Lettr editor uses three merge tags. lettr:generate-dtos types each one as a string in OrderShippedData, and lettr:pull writes the Blade view, Mailable and DTO into the app.

A retried job never sends twice.

Queued sends carry an idempotency key built from the job's uuid. When the API accepted an email but the response timed out, the retry replays the original result instead of emailing your customer again. Nothing to configure.

Applies to
queued sends, by default
Key kept for
24 hours
Replay reported as
$response->replayed
// Sending synchronously? Pass your own key.
Mail::lettr()
    ->to($order->customer->email)
    ->idempotencyKey("order-{$order->id}-shipped")
    ->send(new OrderShipped($data));

A queue worker runs SendQueuedMailable, times out after 30 seconds and retries. With the idempotency key, the Lettr API answers the retry with the first result, marked replayed, and the customer's inbox holds one email. Without it, the retry sends a second email.

Eleven minutes, one real app.

Laravel Daily
Templates, DTOs, enums · 11:00

Prefer YouTube? Watch the walkthrough there.

Everything else
stays Laravel.

Lettr is a mail transport and a facade. Everything else in your app stays where it is.

  1. Mailables and notifications

    MAIL_MAILER=lettr

    Delivered over the HTTP API. No SMTP.

  2. One email at a time

    Mail::mailer('lettr')

    Keep your default mailer while you move over.

  3. Templates as Blade

    lettr:pull / lettr:push

    Move templates between the editor and your repo.

  4. Tests

    Mail::fake()

    Assertions you already write keep passing.

  5. Scheduled sends

    ->scheduleAt(now()->addDay())

    Five minutes to thirty days ahead, cancellable.

  6. Typed errors

    RateLimitException

    One exception class per failure, with retryAfter.

  7. Marketing, same account

    Lettr::campaigns()

    Audiences, segments and campaigns too.

Start free. Pay per email after.

Transactional email is billed per email, campaigns per contact, both from the same account.

50,000

Pro $15 /mo

Transactional.

Per email

3,000 emails every month, free. Scale up from $15/mo.

  • Email API & SMTP
  • No daily limit on paid plans
  • Real-time webhooks

Marketing.

Per contact

Up to 500 contacts, free. Scale up from $10/mo.

  • Unlimited campaigns
  • Drag-and-drop editor
  • Lists & segments

Questions from Laravel developers.

The package needs PHP 8.4. Until you upgrade, point Laravel's SMTP mailer at Lettr with your API key as the password. Mailables and queues keep working, and you can switch to the package later without touching them.

MAIL_MAILER=smtp
MAIL_HOST=smtp.lettr.com
MAIL_PORT=587
MAIL_USERNAME=lettr
MAIL_PASSWORD=your-lettr-api-key