Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fin Mail Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require finity-labs/fin-mail
    php artisan fin-mail:install
    

    Follow prompts for locales, migrations, and plugin registration.

  2. Register Plugin: Add to your Filament panel:

    FinMailPlugin::make()->register($panel);
    
  3. 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) => [])
    

Where to Look First

  • Admin Panel: Navigate to Email Templates to create/edit templates.
  • Token Syntax: Check the Tokens tab in template editor for available variables.
  • Documentation: Run php artisan fin-mail:docs (if available) or refer to the README.

Implementation Patterns

Core Workflows

  1. Template Management:

    • Create templates via the Email Templates resource.
    • Use the RichEditor with merge tags ({{ user.name }}) and custom blocks (e.g., CTA buttons).
    • Organize templates with categories, tags, and themes.
  2. Sending Emails:

    • Programmatic:
      Mail::to($user->email)->send(
          TemplateMail::make('welcome-email')
              ->models(['user' => $user])
              ->attachFile($path, 'filename.pdf')
      );
      
    • From Resources: Add SendEmailAction to table/header actions:
      SendEmailAction::make()
          ->template('invoice-sent')
          ->recipient(fn ($record) => $record->customer_email)
          ->models(fn ($record) => ['invoice' => $record])
      
  3. Dynamic Data:

    • Tokens: Use {{ model.relation.attr }} (e.g., {{ order.customer.name }}).
    • Fallbacks: {{ user.name | 'Guest' }}.
    • Conditionals: {% if user.is_premium %}Premium Content{% endif %}.
    • Extra Data: Pass variables directly to Blade:
      ->with('tracking_url', $tracking->url)
      
  4. Logging and Tracking:

    • View sent emails via the Sent Emails resource.
    • Filter by template, status, or associated model.
    • Use HasEmailTemplates trait on models for quick access:
      $invoice->sentEmails()->where('template_name', 'invoice-sent')->get();
      

Integration Tips

  • Filament Resources: Add SentEmailsRelationManager to show sent emails for a record:
    public static function getRelations(): array {
        return [SentEmailsRelationManager::class];
    }
    
  • Events: Listen for EmailSent/EmailFailed to trigger side effects:
    Event::listen(EmailSent::class, fn ($event) => $event->sentEmail->model->update(['emailed_at' => now()]));
    
  • Custom Blocks: Extend RichContentCustomBlock for reusable components (e.g., footers, dividers):
    FinMailPlugin::make()->customBlocks([\App\Mail\Blocks\FooterBlock::class]);
    
  • Themes: Apply themes to templates for consistent branding. Themes support dynamic color updates.

Gotchas and Tips

Pitfalls

  1. Token Resolution Order:

    • Tokens are resolved in this order: extra data > models > config.
    • Override with ->with() or ->models() as needed.
    • Example: {{ tracking_url }} (extra data) takes precedence over {{ config.tracking_url }}.
  2. Editor Blocks in Emails:

    • Custom blocks must implement toHtml() for email rendering. Forgetting this will break email output.
    • Test blocks in preview mode before sending.
  3. Locale Handling:

    • Translatable templates require spatie/laravel-translatable. Ensure locales are published:
      php artisan fin-mail:install --locales=en,es
      
    • Fallback to default locale if a translation is missing.
  4. Attachment Limits:

    • Check config/fin-mail.php for max_attachment_size and allowed_mime_types.
    • Large attachments may fail silently; validate files before uploading.
  5. Queue Configuration:

    • Emails are queued by default. Configure queue_connection in config/fin-mail.php:
      'queue_connection' => 'redis',
      'queue_name' => 'emails',
      
    • Monitor queues for stuck emails (e.g., failed attachments).
  6. Shield Policies:

    • If using Filament Shield, ensure policies are generated:
      php artisan shield:generate
      
    • Customize policies in App\Policies\EmailTemplatePolicy.
  7. Migration Conflicts:

    • If settings table exists, run:
      php artisan migrate --path=vendor/finity-labs/fin-mail/database/migrations
      
    • Avoid manual table edits; use fin-mail:install --seed for defaults.

Debugging Tips

  • 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;
    }
    

Extension Points

  1. Override Views: Publish and modify views:

    php artisan vendor:publish --tag=fin-mail-views
    

    Edit resources/views/vendor/fin-mail/....

  2. Custom Mailer: Extend TemplateMail for global overrides:

    class CustomTemplateMail extends TemplateMail {
        public function resolveExtraData(): array {
            return array_merge(parent::resolveExtraData(), ['custom_key' => 'value']);
        }
    }
    
  3. Hook into Lifecycle: Use events to modify behavior:

    Event::listen(EmailSending::class, fn ($event) => $event->sentEmail->status = 'pending');
    
  4. API Endpoints: Create API routes for template management:

    Route::get('/api/email-templates', [EmailTemplateController::class, 'index']);
    
  5. 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);
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai