
Complete email management UI for Filament. Built on top of jeffersongoncalves/laravel-mail, it provides a rich interface for managing email logs, database templates with multi-locale editing, delivery tracking, analytics dashboard, and suppression management.
| Package | Filament | Laravel | PHP |
|---|---|---|---|
| 1.x | 3.x | 10+ | 8.1+ |
| 2.x | 4.x | 11+ | 8.2+ |
| 3.x | 5.x | 11+ | 8.2+ |
composer require jeffersongoncalves/filament-mail
The package requires jeffersongoncalves/laravel-mail as a dependency. Make sure to run its migrations first:
php artisan vendor:publish --tag="laravel-mail-migrations"
php artisan migrate
Optionally, publish the config file:
php artisan vendor:publish --tag="filament-mail-config"
Register the plugin in your Filament panel provider:
use JeffersonGoncalves\FilamentMail\FilamentMailPlugin;
use LaraZeus\SpatieTranslatable\SpatieTranslatablePlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentMailPlugin::make(),
// Required for multi-locale template editing
SpatieTranslatablePlugin::make()
->defaultLocales(['en', 'pt_BR', 'es']),
]);
}
The SpatieTranslatablePlugin is required for multi-locale template editing. It provides a locale switcher in the header of all template pages (create, edit, view, list). Configure the locales you need in the defaultLocales() method.
FilamentMailPlugin::make()
->navigationGroup('Email')
->navigationIcon('heroicon-o-envelope')
->navigationSort(50)
->mailLogResource() // Enable/disable mail log resource
->mailTemplateResource() // Enable/disable template resource
->mailSuppressionResource() // Enable/disable suppression resource
->statsWidgets() // Enable/disable stats widgets
->analyticsWidget() // Enable/disable analytics charts
->dashboard() // Enable/disable dashboard page
->tenantScoping() // Enable/disable tenant scoping
FilamentMailPlugin::make()
->mailSuppressionResource(false) // Disable suppression management
->analyticsWidget(false) // Disable analytics charts
->dashboard(false) // Disable dashboard page
// config/filament-mail.php
return [
'resources' => [
'mail_log' => [
'enabled' => true,
'label' => 'Mail Log',
'plural_label' => 'Mail Logs',
],
'mail_template' => [
'enabled' => true,
'label' => 'Mail Template',
'plural_label' => 'Mail Templates',
],
'mail_suppression' => [
'enabled' => true,
'label' => 'Suppression',
'plural_label' => 'Suppressions',
],
],
'widgets' => [
'stats_overview' => true,
'analytics_chart' => true,
'delivery_rate_chart' => true,
],
'dashboard' => [
'enabled' => true,
],
'navigation' => [
'group' => 'Email',
'icon' => 'heroicon-o-envelope',
'sort' => 50,
],
'template_editor' => [
'driver' => env('FILAMENT_MAIL_EDITOR', 'rich_editor'),
'locales' => ['en'],
'default_locale' => 'en',
'unlayer_project_id' => env('UNLAYER_PROJECT_ID'),
'merge_tags' => [],
],
'preview' => [
'max_width' => '800px',
'sandbox' => true,
],
'tenant_scoping' => false,
];
The template editor is swappable via config. Set the FILAMENT_MAIL_EDITOR environment variable:
# Default: standard Filament RichEditor
FILAMENT_MAIL_EDITOR=rich_editor
# Visual drag-and-drop editor via Unlayer
FILAMENT_MAIL_EDITOR=unlayer
UNLAYER_PROJECT_ID=your-project-id
When using Unlayer, publish and run the migration for the body_design column:
php artisan vendor:publish --tag="filament-mail-migrations"
php artisan migrate
Implement TemplateEditorContract and bind it in a service provider:
use JeffersonGoncalves\FilamentMail\Contracts\TemplateEditorContract;
class MyEditorDriver implements TemplateEditorContract
{
public function getFormField(string $fieldName = 'html_body'): Component
{
return MyCustomField::make($fieldName)->columnSpanFull();
}
public function render(string $content, array $variables): string
{
foreach ($variables as $key => $value) {
$content = str_replace(
['{{' . $key . '}}', '{{ ' . $key . ' }}'],
(string) $value,
$content
);
}
return $content;
}
}
// In a service provider:
$this->app->bind(TemplateEditorContract::class, MyEditorDriver::class);
Send emails using database templates with variable binding:
use JeffersonGoncalves\FilamentMail\Notifications\MailNotification;
// Simple notification
$user->notify(new MailNotification(
templateKey: 'auth.welcome',
variables: [
'name' => $user->name,
'login_url' => route('login'),
],
));
// With locale, cc, and attachments
$user->notify(new MailNotification(
templateKey: 'transactional.invoice',
variables: [
'invoice_number' => $invoice->number,
'total' => number_format($invoice->total, 2, ',', '.'),
'due_date' => $invoice->due_date->format('d/m/Y'),
],
metadata: [
'locale' => 'pt_BR',
'cc' => ['finance@company.com'],
'attachments' => [storage_path("invoices/{$invoice->number}.pdf")],
],
));
// Without a notifiable (via Notification facade)
use Illuminate\Support\Facades\Notification;
Notification::route('mail', $email)->notify(
new MailNotification('auth.reset-password', ['url' => $resetUrl])
);
For traditional Mailables, use the HasMailTemplate trait:
use JeffersonGoncalves\FilamentMail\Traits\HasMailTemplate;
use Illuminate\Mail\Mailable;
class WelcomeMail extends Mailable
{
use HasMailTemplate;
public function __construct(User $user)
{
$this->templateKey = 'auth.welcome';
$this->templateVariables = ['name' => $user->name];
}
public function build(): static
{
return $this->buildContent();
}
}
You can extend the default resources by creating your own classes and updating the config:
// config/filament-mail.php
'resources' => [
'mail_log' => [
'class' => App\Filament\Resources\CustomMailLogResource::class,
],
],
composer test
Please see CHANGELOG for more information on what has changed recently.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.
How can I help you explore Laravel packages today?