jeffersongoncalves/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.

Maintainers

Package info

github.com/jeffersongoncalves/filament-mail

pkg:composer/jeffersongoncalves/filament-mail

Fund package maintenance!

jeffersongoncalves

Statistics

Installs: 9

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 0

3.3.5 2026-04-06 22:03 UTC

README

Filament Mail

Filament Mail

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Status Total Downloads

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

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+

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.