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

Mail Laravel Package

nette/mail

Lightweight PHP mailer from the Nette framework: compose and send emails with SMTP support, MIME messages, attachments, HTML/text bodies, and headers. Sensible defaults, easy integration, and good testability for apps and services.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package:

    composer require nette/mail
    
  2. Configure in config/mail.php (extend Laravel’s defaults):

    'mailers' => [
        'nette' => [
            'transport' => 'smtp',
            'host' => env('MAIL_HOST'),
            'port' => env('MAIL_PORT'),
            'username' => env('MAIL_USERNAME'),
            'password' => env('MAIL_PASSWORD'),
            'encryption' => env('MAIL_ENCRYPTION'),
            'dkim' => [
                'domain' => env('MAIL_DKIM_DOMAIN'),
                'selector' => env('MAIL_DKIM_SELECTOR'),
                'privateKey' => env('MAIL_DKIM_PRIVATE_KEY'),
            ],
            'debugger' => env('MAIL_DEBUGGER', false), // New: Enable MailTracy integration
            'redirect' => env('MAIL_REDIRECT', null), // New: Interceptor redirect address
        ],
    ],
    
  3. First use case: Send a simple HTML email with embedded images using the new HtmlComposer:

    use Nette\Mail\Message;
    use Nette\Mail\SendmailMailer;
    use Nette\Mail\HtmlComposer;
    
    $mailer = new SendmailMailer();
    $message = new Message();
    
    // Use HtmlComposer for pre-processing
    $composer = new HtmlComposer();
    $html = $composer->inlineCss('<p>Hello! <img src="cid:image1"></p>')
                     ->embedImages(base_path('images'))
                     ->getHtml();
    
    $message->setFrom('sender@example.com')
            ->addTo('recipient@example.com')
            ->setSubject($composer->extractSubject($html)) // Auto-extracts <title>
            ->setHtmlBody($html)
            ->addInlinePart($mailer->createAttachment(file_get_contents('image.png'), 'image1.png'));
    
    $mailer->send($message);
    

Key First Steps

  • For Laravel devs: Use Nette\Mail\SendmailMailer for local testing and Nette\Mail\SmtpMailer for production.
  • Enable Interceptor (new): Add MAIL_REDIRECT=dev@example.com to .env to redirect all emails during development.
  • Enable MailTracy (new): Set MAIL_DEBUGGER=true to view sent emails in the Tracy Bar panel.
  • Check PHP version: Ensure PHP ≥8.2 (Laravel 10+ compatibility).

Implementation Patterns

Core Workflows

1. Building Emails with HtmlComposer

use Nette\Mail\HtmlComposer;

$composer = new HtmlComposer();
$html = $composer->inlineCss('<p>Styled content</p>')
                ->embedImages(base_path('assets'))
                ->getHtml();

// Auto-generates plain-text alternative
$message->setHtmlBody($html)
        ->setTextBody($composer->generatePlainText());

2. Interceptor for Development

// Configure in config/mail.php (see above)
// All emails sent to any address will be redirected to dev@example.com
// Original recipients are preserved in X-Original-To headers

3. MailTracy Integration

// Auto-registered when:
// 1. MAIL_DEBUGGER=true in config
// 2. Interceptor is active (MAIL_REDIRECT set)
// View sent emails in Tracy Bar panel (Tracy Debugger required)

4. Hybrid SMTP/Sendmail with Interceptor

use Nette\Mail\FallbackMailer;
use Nette\Mail\Interceptor;

$fallbackMailer = new FallbackMailer([
    new Interceptor(new SmtpMailer($smtpConfig), 'dev@example.com'),
    new SendmailMailer(),
]);

Laravel Integration Tips

  1. Extend Laravel’s Mailer with Interceptor:

    use Nette\Mail\Interceptor;
    use Nette\Mail\SmtpMailer;
    
    class NetteMailer extends \Illuminate\Mail\Mailer
    {
        public function send(NetteMessage $message, $to, $subject = null)
        {
            $netteMessage = new Message();
            $netteMessage->setFrom($message->from)
                         ->addTo($to)
                         ->setSubject($subject ?? $message->subject);
    
            // Use Interceptor for dev mode
            $mailer = env('MAIL_REDIRECT')
                ? new Interceptor(new SmtpMailer($this->getSmtpConfig()), env('MAIL_REDIRECT'))
                : new SmtpMailer($this->getSmtpConfig());
    
            $mailer->send($netteMessage);
        }
    }
    
  2. Use with Laravel Notifications and HtmlComposer:

    use Illuminate\Notifications\Notification;
    use Nette\Mail\HtmlComposer;
    
    class EmailNotification extends Notification
    {
        public function via($notifiable)
        {
            return ['mail'];
        }
    
        public function toMail($notifiable)
        {
            $composer = new HtmlComposer();
            $html = $composer->inlineCss('<h1>Hello!</h1>')
                            ->embedImages(public_path('images'))
                            ->getHtml();
    
            return (new Message())
                ->setHtmlBody($html)
                ->setTextBody($composer->generatePlainText());
        }
    }
    
  3. Queue Emails with Interceptor:

    use Nette\Mail\Interceptor;
    use Illuminate\Support\Facades\Bus;
    
    Bus::dispatch(function () use ($mailer) {
        $interceptor = new Interceptor($mailer, 'dev@example.com');
        $interceptor->send($message);
    });
    

Advanced Patterns

Dynamic HTML Processing with HtmlComposer

$composer = new HtmlComposer();
$html = $composer->inlineCss($dynamicHtmlTemplate)
                ->embedImages(base_path('dynamic_assets'))
                ->getHtml();

// Reuse across multiple messages
$message1->setHtmlBody($composer->getHtml());
$message2->setHtmlBody($composer->inlineCss($anotherTemplate)->getHtml());

Conditional Interceptor Activation

$mailer = app()->environment('local')
    ? new Interceptor(new SmtpMailer($config), 'dev@example.com')
    : new SmtpMailer($config);

MailTracy Customization

// Disable MailTracy globally
config(['mail.debugger' => false]);

// Or configure per-mailer
$mailer = new Interceptor(new SmtpMailer($config), 'dev@example.com');
$mailer->setDebugger(false);

Gotchas and Tips

Pitfalls

  1. Interceptor Header Conflicts:

    • Issue: Custom X-* headers may conflict with Interceptor’s X-Original-* headers.
    • Fix: Add headers before using Interceptor:
      $message->addHeader('X-Custom', 'value');
      $interceptor->send($message); // Preserves custom headers
      
  2. HtmlComposer CSS Inlining Limitations:

    • Issue: Complex CSS (e.g., @media queries) may not inline perfectly.
    • Fix: Pre-process CSS with a tool like Premailer for critical emails.
  3. MailTracy Tracy Dependency:

    • Issue: MailTracy requires Tracy Debugger.
    • Fix: Install Tracy if missing:
      composer require nette/tracy
      
  4. Interceptor Redirect Loop:

    • Issue: Redirecting to the same address as sender creates loops.
    • Fix: Validate redirect address:
      $interceptor = new Interceptor($mailer, 'dev@example.com');
      if ($message->getFrom() === 'dev@example.com') {
          $mailer->send($message); // Bypass interceptor
      } else {
          $interceptor->send($message);
      }
      
  5. HtmlComposer Image Embedding:

    • Issue: Relative paths in embedImages() may break in production.
    • Fix: Use absolute paths or configure base URL:
      $composer->embedImages(base_path('storage/app/public/images'));
      

Debugging Tips

  1. Inspect Interceptor Headers:

    $message->onSend[] = function ($message) {
        dd($message->getHeaders());
    };
    
  2. MailTracy Panel Debugging:

    • Check Tracy Bar for sent emails (requires MAIL_DEBUGGER=true).
    • Click emails to view raw content, headers, and status.
  3. HtmlComposer Output Validation:

    $composer = new HtmlComposer();
    $html = $composer->inlineCss($html);
    dd($composer->getErrors()); // Check for CSS inlining issues
    
  4. Interceptor Logs:

    $interceptor = new Interceptor($mailer, 'dev@example.com');
    $
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
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