finity-labs/fin-mail
FinMail adds an email template manager and composer to Filament. Create dynamic, multilingual templates with token replacement and merge tags, version templates, log sent emails with status tracking, override auth mails, and use a reusable “Send Email” action in resources.
Installation:
composer require finity-labs/fin-mail
php artisan fin-mail:install
Follow prompts for locales, migrations, and plugin registration.
Register Plugin: Add to your Filament panel:
FinMailPlugin::make()->register($panel);
First Use Case: Send an email from a resource:
use FinityLabs\FinMail\Actions\SendEmailAction;
SendEmailAction::make()
->template('welcome-email')
->recipient(fn ($record) => $record->email)
->models(fn ($record) => ['user' => $record])
->attachments(fn ($record) => [])
Email Templates to create/edit templates.Tokens tab in template editor for available variables.php artisan fin-mail:docs (if available) or refer to the README.Template Management:
Email Templates resource.{{ user.name }}) and custom blocks (e.g., CTA buttons).Sending Emails:
Mail::to($user->email)->send(
TemplateMail::make('welcome-email')
->models(['user' => $user])
->attachFile($path, 'filename.pdf')
);
SendEmailAction to table/header actions:
SendEmailAction::make()
->template('invoice-sent')
->recipient(fn ($record) => $record->customer_email)
->models(fn ($record) => ['invoice' => $record])
Dynamic Data:
{{ model.relation.attr }} (e.g., {{ order.customer.name }}).{{ user.name | 'Guest' }}.{% if user.is_premium %}Premium Content{% endif %}.->with('tracking_url', $tracking->url)
Logging and Tracking:
Sent Emails resource.HasEmailTemplates trait on models for quick access:
$invoice->sentEmails()->where('template_name', 'invoice-sent')->get();
SentEmailsRelationManager to show sent emails for a record:
public static function getRelations(): array {
return [SentEmailsRelationManager::class];
}
EmailSent/EmailFailed to trigger side effects:
Event::listen(EmailSent::class, fn ($event) => $event->sentEmail->model->update(['emailed_at' => now()]));
RichContentCustomBlock for reusable components (e.g., footers, dividers):
FinMailPlugin::make()->customBlocks([\App\Mail\Blocks\FooterBlock::class]);
Token Resolution Order:
->with() or ->models() as needed.{{ tracking_url }} (extra data) takes precedence over {{ config.tracking_url }}.Editor Blocks in Emails:
toHtml() for email rendering. Forgetting this will break email output.Locale Handling:
spatie/laravel-translatable. Ensure locales are published:
php artisan fin-mail:install --locales=en,es
Attachment Limits:
config/fin-mail.php for max_attachment_size and allowed_mime_types.Queue Configuration:
queue_connection in config/fin-mail.php:
'queue_connection' => 'redis',
'queue_name' => 'emails',
Shield Policies:
php artisan shield:generate
App\Policies\EmailTemplatePolicy.Migration Conflicts:
settings table exists, run:
php artisan migrate --path=vendor/finity-labs/fin-mail/database/migrations
fin-mail:install --seed for defaults.Token Errors:
Enable debug mode in config/fin-mail.php:
'debug' => env('FIN_MAIL_DEBUG', false),
Logs unresolved tokens to storage/logs/fin-mail.log.
Email Rendering: Preview templates in the admin panel before sending. Use the HTML source tab to inspect output.
Queue Issues:
Check failed_jobs table for queued emails:
php artisan queue:failed-table
php artisan queue:retry JOB_ID
Custom Block Styling:
Use setPreviewTheme() to sync theme colors with custom blocks:
public static function setPreviewTheme(?array $theme) {
self::$previewTheme = $theme;
}
Override Views: Publish and modify views:
php artisan vendor:publish --tag=fin-mail-views
Edit resources/views/vendor/fin-mail/....
Custom Mailer:
Extend TemplateMail for global overrides:
class CustomTemplateMail extends TemplateMail {
public function resolveExtraData(): array {
return array_merge(parent::resolveExtraData(), ['custom_key' => 'value']);
}
}
Hook into Lifecycle: Use events to modify behavior:
Event::listen(EmailSending::class, fn ($event) => $event->sentEmail->status = 'pending');
API Endpoints: Create API routes for template management:
Route::get('/api/email-templates', [EmailTemplateController::class, 'index']);
Testing:
Use the FinMailTestCase trait for assertions:
use FinityLabs\FinMail\Testing\FinMailTestCase;
public function testEmailSending() {
$this->actingAs($user);
$this->sendEmail('welcome-email', ['user' => $user])
->assertSentTo($user->email);
}
How can I help you explore Laravel packages today?