Filament Mail
Complete email management UI for Filament: mail logs with preview, database templates with multi-locale editing, delivery tracking, analytics dashboard, and suppression management.
#Filament Mail
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.
#Compatibility
#Features
- Mail Logs — Browse, search, and view all sent emails with HTML preview, attachments, headers, and metadata
- Resend & Retry — Resend any email or retry failed deliveries directly from the UI
- Mail Templates — Create and edit database-driven email templates with multi-locale support (via spatie/laravel-translatable)
- Swappable Template Editor — Use Filament RichEditor (default) or Unlayer visual drag-and-drop editor
- MailNotification — Send template-based notifications with variable binding, cc, bcc, attachments
- Template Versioning — Automatic version history with change tracking
- Live Preview — Preview rendered templates with example data in an iframe sandbox
- Send Test Email — Send test emails from any template with locale selection
- Delivery Tracking — View tracking events (delivered, bounced, opened, clicked, complained) from 5 providers
- Analytics Dashboard — Stats overview, daily analytics chart, and delivery rate chart with period filters
- Suppression Management — Manage suppressed emails (hard bounces, complaints, manual suppressions)
- Multi-tenant — Optional tenant scoping for all queries
- Configurable — Disable/enable individual resources, widgets, and pages
#Installation
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"
#Usage
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.
#Customization
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
#Disabling Features
FilamentMailPlugin::make() ->mailSuppressionResource(false) // Disable suppression management ->analyticsWidget(false) // Disable analytics charts ->dashboard(false) // Disable dashboard page
#Configuration
// 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, ];
#Template Editor
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
#Creating a Custom Editor Driver
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);
#MailNotification
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]) );
#HasMailTemplate Trait
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(); } }
#Extending Resources
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, ], ],
#Testing
composer test
#Changelog
Please see CHANGELOG for more information on what has changed recently.
#Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
#Credits
#License
The MIT License (MIT). Please see License File for more information.