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

Laravel Mail Laravel Package

jeffersongoncalves/laravel-mail

Complete email management for Laravel: logs outgoing mail, database Blade templates with translations and versioning, webhook delivery tracking (SES/SendGrid/Postmark/Mailgun/Resend), open/click pixel tracking, suppression list, CSS inlining, List-Unsubscribe, preview, stats, retries.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require jeffersongoncalves/laravel-mail
    php artisan vendor:publish --tag="laravel-mail-migrations"
    php artisan migrate
    
  2. First Use Case: Send a logged email
    Mail::to('user@example.com')->send(new WelcomeMail($user));
    
    • Verify logs in mail_logs table.

Key Configuration

  • Publish config:
    php artisan vendor:publish --tag="laravel-mail-config"
    
  • Enable tracking (webhooks/pixels) in .env:
    LARAVEL_MAIL_TRACKING_ENABLED=true
    LARAVEL_MAIL_PIXEL_OPEN_TRACKING=true
    

First Template

// Create template via Tinker or migration
MailTemplate::create([
    'key' => 'welcome',
    'subject' => ['en' => 'Welcome!'],
    'html_body' => ['en' => '<h1>Hello!</h1>'],
]);

Implementation Patterns

1. Database-Driven Templates

Workflow:

  1. Store templates in mail_templates table (supports spatie/laravel-translatable).
  2. Extend TemplateMailable:
    class WelcomeEmail extends TemplateMailable {
        public function templateKey(): string { return 'welcome'; }
        public function templateData(): array { return ['name' => $this->user->name]; }
    }
    
  3. Send via Mail::to()->send(new WelcomeEmail($user)).

Integration Tip:

  • Use PreviewTemplateAction for admin previews:
    $preview = app(PreviewTemplateAction::class)->execute($template, ['name' => 'Alice']);
    

2. Tracking Events

Workflow:

  1. Configure provider webhooks in config/laravel-mail.php (e.g., sendgrid.signing_secret).
  2. Listen to events:
    Event::listen(MailBounced::class, function ($event) {
        $event->mailLog->suppress(); // Auto-suppress bounces
    });
    
  3. Verify webhook URLs in provider dashboards (e.g., https://app.com/webhooks/mail/sendgrid).

Integration Tip:

  • Use MailLog::find($id)->trackingEvents to query historical events.

3. Pixel Tracking

Workflow:

  1. Enable in config:
    'pixel' => [
        'open_tracking' => true,
        'click_tracking' => true,
    ],
    
  2. Add routes (auto-registered via RouteServiceProvider):
    Route::mailTracking(); // Mounts /mail/t/pixel and /mail/t/click
    
  3. Test by sending an email and checking logs for opened/clicked events.

Integration Tip:

  • Customize pixel routes/middleware in config:
    'pixel' => [
        'route_prefix' => 'track',
        'route_middleware' => ['throttle:60'],
    ],
    

4. Retry Mechanism

Workflow:

  1. Mark failed emails as failed (status: failed).
  2. Retry via Artisan:
    php artisan mail:retry --attempts=3
    
  3. Or programmatically:
    $log = MailLog::where('status', 'failed')->first();
    $log->retry();
    

Integration Tip:

  • Use MailLog::failed()->withRetryAttemptsLessThan(3) to query retryable emails.

5. Notification Channel

Workflow:

  1. Extend TemplateMailable and use with Notification:
    $user->notify(new WelcomeNotification($user));
    
  2. Configure in config/notifications.php:
    'channels' => [
        'mail' => [
            'transport' => 'laravel-mail',
        ],
    ],
    

Integration Tip:

  • Override via() in your notification:
    public function via($notifiable) {
        return ['laravel-mail'];
    }
    

Gotchas and Tips

Pitfalls

  1. Webhook Validation Failures:

    • Issue: Webhook payloads rejected due to missing signing secrets.
    • Fix: Set LARAVEL_MAIL_[PROVIDER]_SIGNING_SECRET in .env (e.g., LARAVEL_MAIL_SENDGRID_SIGNING_SECRET).
    • Debug: Check mail_webhook_attempts table for failed attempts.
  2. Pixel Tracking Blocked:

    • Issue: Open/click tracking fails if images/links are blocked (e.g., Gmail’s "Download Images").
    • Fix: Use provider webhooks (LARAVEL_MAIL_TRACKING_ENABLED=true) as a fallback.
  3. Template Versioning Overhead:

    • Issue: Frequent template updates create many mail_template_versions.
    • Fix: Disable versioning for non-critical templates via:
      $template->update(['versioned' => false]);
      
  4. CSS Inlining Performance:

    • Issue: Large HTML templates cause slow inline CSS processing.
    • Fix: Disable for non-critical emails:
      LARAVEL_MAIL_INLINE_CSS=false
      
  5. Suppression List Conflicts:

    • Issue: Accidental suppression of valid addresses.
    • Fix: Audit suppressed emails via:
      MailSuppression::with('mailLog')->get();
      

Debugging Tips

  1. Webhook Debugging:

    • Enable logging for webhook events:
      LARAVEL_MAIL_TRACKING_LOG_WEBHOOKS=true
      
    • Check mail_webhook_attempts table for payloads.
  2. Pixel Tracking:

    • Verify pixel URLs in sent emails (search for src="/mail/t/pixel/).
    • Test with curl:
      curl -v "https://app.com/mail/t/pixel/123?sig=abc"
      
  3. Template Rendering:

    • Preview templates with:
      dd(app(PreviewTemplateAction::class)->execute($template, $data));
      
    • Check for Blade syntax errors in mail_template_versions.
  4. Attachment Storage:

    • Ensure LARAVEL_MAIL_ATTACHMENT_DISK is configured if storing attachments:
      LARAVEL_MAIL_ATTACHMENT_DISK=s3
      

Extension Points

  1. Custom Tracking Events:

    • Extend MailTrackingEvent model or create custom events by listening to MailLogUpdated:
      Event::listen(MailLogUpdated::class, function ($event) {
          if ($event->mailLog->status === 'custom_status') {
              // Dispatch custom event
          }
      });
      
  2. Override Models:

    • Publish and extend models:
      php artisan vendor:publish --tag="laravel-mail-models"
      
    • Example: Custom MailLog fields:
      class CustomMailLog extends MailLog {
          protected $casts = [
              'custom_field' => 'string',
          ];
      }
      
  3. Custom Webhook Handlers:

    • Override WebhookHandler service provider:
      class CustomWebhookServiceProvider extends WebhookServiceProvider {
          protected function registerHandlers() {
              $this->app->bind(WebhookHandler::class, CustomWebhookHandler::class);
          }
      }
      
  4. Multi-Tenant Scoping:

    • Enable in config:
      'multi_tenant' => [
          'enabled' => true,
          'tenant_model' => \App\Models\Tenant::class,
          'tenant_key' => 'id',
      ],
      
    • Use MailLog::forTenant($tenant) for scoped queries.

Configuration Quirks

  1. Attachment Storage:

    • If LARAVEL_MAIL_ATTACHMENT_DISK is set, attachments are stored in mail_attachments table with files on the specified disk.
    • Note: Large attachments may bloat the database. Use S3 for scalability.
  2. Pixel Signing Key:

    • Defaults to APP_KEY if LARAVEL_MAIL_PIXEL_SIGNING_KEY is empty.
    • Security: Use a dedicated key for production to avoid exposing APP_KEY.
  3. Template Layouts:

    • Global layout in config/laravel-mail.php:
      'templates' => [
          'default_layout' => '<html><body>{!! $slot !!}</body></html>',
      ],
      
    • Override per template:
      $template->update(['layout' => '<div>{!! $slot !!}</div>']);
      
  4. Unsubscribe Headers:

    • Dynamic URLs (e.g., {email}) are replaced at
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity