Different ways to send emails with Lettr for Laravel
Lettr integrates seamlessly with Laravel’s mail system. This page covers every approach — from the standard Mail facade to the low-level email builder — so you can choose the one that fits your use case.
If you’ve set Lettr as your default mailer, use Laravel’s standard Mail facade:
use App\Mail\OrderShipped;use Illuminate\Support\Facades\Mail;Mail::to('customer@example.com')->send(new OrderShipped($order));
This is the simplest approach if you’re migrating from another mail provider. Your existing Mailable classes work without modification — just change the mailer in your .env and all emails route through Lettr.If Lettr isn’t your default mailer, specify it explicitly:
The array keys map to merge tags in your Lettr template. For example, 'name' => 'John' fills the {{name}} merge tag. See Merge Tags & Template Language for the full syntax.With additional options:
Use version to pin a specific template version in production. Omit it to always use the active (published) version. See Template Versioning for details.
use Lettr\Laravel\Facades\Lettr;Lettr::emails()->sendHtml( from: 'hello@yourdomain.com', to: 'recipient@example.com', subject: 'Hello from Lettr', html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>');
Lettr::emails()->sendText( from: 'hello@yourdomain.com', to: ['user1@example.com', 'user2@example.com'], subject: 'Plain text update', text: 'This is a plain text email.');
The to parameter accepts both a single email string and an array of recipients.
The builder is useful when you need to combine multiple features in a single email — for example, HTML content with a plain text fallback, tracking, metadata, and attachments.
Custom Mailables are the best choice when you send the same template from multiple places in your application. They encapsulate the template slug, merge tag mapping, and subject line in one class, keeping your controllers and jobs clean.
You can auto-generate Mailable classes from your Lettr templates. See Mailable Classes for details.
Lettr::emails()->send( Lettr::emails()->create() ->from('marketing@yourdomain.com') ->to(['subscriber@example.com']) ->subject('Check out our new features') ->html($htmlContent) ->withOpenTracking(true) ->withClickTracking(true));
When tracking is enabled, Lettr inserts a tracking pixel for opens and rewrites links for click tracking. You can view tracking data in the Analytics dashboard or receive events via webhooks. See Tracking for details on how tracking works and privacy considerations.
Tags let you group emails for analytics. You can filter and break down metrics by tag in the Analytics dashboard, and the home dashboard shows per-tag Sent, Opened, and Rate stats automatically. See Tags for the full reference.In most cases you don’t need to set a tag yourself — the Laravel package resolves it automatically using this priority:
Explicit tag — if you call ->tag() on the Mailable, that value wins.
Template slug — if you use ->template('slug'), the server uses the slug as the tag.
Class name — if neither of the above applies, the package generates a kebab-case tag from the Mailable class name (e.g., OrderConfirmation becomes order-confirmation).
When you use ->template('slug') on a LettrMailable, the server automatically uses the template slug as the tag. No code needed — your analytics are grouped by template out of the box. The Emails page in the dashboard shows Sent, Opened, and Rate per template.
When sending raw HTML (without a Lettr template) through a LettrMailable, the package auto-generates a kebab-case tag from the class name. For example, OrderConfirmation becomes order-confirmation.
Call ->tag('my-tag') on any Mailable to override the automatic tag:
class WeeklyNewsletter extends LettrMailable{ public function build(): static { return $this ->template('newsletter') ->tag('welcome'); // overrides the automatic 'newsletter' tag }}
If multiple tags are set (via Laravel’s tag() method), they are joined with _ into a single string. The combined string must not exceed 64 characters.
The sendTemplate method accepts a tag parameter. If omitted, the template slug is used automatically:
Mail::lettr() ->to('user@example.com') ->sendTemplate('welcome-email', 'Welcome!', [ 'name' => 'John', ], tag: 'onboarding'); // omit to use 'welcome-email' as the tag
use Illuminate\Support\Facades\Mail;use Lettr\Laravel\Mail\InlineLettrMailable;public function test_welcome_email_is_sent(){ Mail::fake(); // Trigger the email $this->post('/register', ['email' => 'user@example.com']); Mail::assertSent(InlineLettrMailable::class, function ($mail) { return $mail->hasTo('user@example.com'); });}
Mail::fake() intercepts all outbound mail, so no real emails are sent during tests. This works identically to testing any other Laravel mailer.For custom Mailable classes, assert against the class directly:
Mail::assertSent(OrderConfirmation::class, function ($mail) { return $mail->hasTo('customer@example.com') && $mail->order->id === 42;});