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

Mailer Laravel Package

symfony/mailer

Symfony Mailer helps you send emails via SMTP and other transports with a clean API. Build Email/TemplatedEmail messages, add attachments and headers, and integrate with Twig templates for HTML rendering. Configure transports via DSN and send reliably.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package (if not already included in Laravel 8+):

    composer require symfony/mailer
    
  2. Configure your mail transport in .env (updated for security fixes):

    MAIL_MAILER=smtp
    MAIL_HOST=mailpit
    MAIL_PORT=1025
    MAIL_USERNAME=null
    MAIL_PASSWORD=null
    MAIL_ENCRYPTION=null
    MAIL_FROM_ADDRESS="hello@example.com"
    MAIL_FROM_NAME="${APP_NAME}"
    

    For API-based transports (e.g., SendGrid, Mailgun), use a DSN with proper encoding:

    MAIL_MAILER=smtp
    MAILER_DSN=smtp://api:$(urlencode key-123)@mailpit:1025
    
  3. First use case: Sending a simple email (unchanged):

    use Symfony\Component\Mime\Email;
    use Symfony\Component\Mailer\MailerInterface;
    
    public function sendWelcomeEmail(MailerInterface $mailer)
    {
        $email = (new Email())
            ->from('noreply@example.com')
            ->to('user@example.com')
            ->subject('Welcome!')
            ->text('Thanks for signing up!');
    
        $mailer->send($email);
    }
    

Key Starting Points

  • Laravel’s built-in Mail facade (wraps Symfony Mailer):
    use Illuminate\Support\Facades\Mail;
    
    Mail::to('user@example.com')->send(new WelcomeEmail());
    
  • Twig integration (if using Laravel’s Blade/Twig):
    Mail::to('user@example.com')->send(new WelcomeEmail($user));
    

Implementation Patterns

1. Email Composition Patterns

Basic Email with Attachments (unchanged):

$email = (new Email())
    ->from('sender@example.com')
    ->to('recipient@example.com')
    ->subject('Invoice #123')
    ->text('Please find attached.')
    ->html('<p>Please find attached.</p>')
    ->attachmentFromPath('/path/to/invoice.pdf', 'invoice.pdf')
    ->priority(Email::PRIORITY_HIGH);

Dynamic Recipients (unchanged):

$email = (new Email())
    ->from('noreply@example.com')
    ->subject('Your Order Update');

// Add recipients dynamically
$email->to('user1@example.com');
$email->cc('manager@example.com');
$email->bcc('archive@example.com');

Reply-to and Headers (unchanged):

$email = (new Email())
    ->replyTo('support@example.com')
    ->addCustomHeader('X-Priority', '1')
    ->addCustomHeader('X-Mailer', 'Laravel/Symfony');

2. Transport Strategies

Fallback Transports (RoundRobin) (unchanged):

use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mailer\Transport\RoundRobinTransport;

$primary = Transport::fromDsn('smtp://user:pass@smtp.example.com');
$fallback = Transport::fromDsn('smtp://user:pass@backup-smtp.example.com');

$transport = new RoundRobinTransport([$primary, $fallback]);
$mailer = new Mailer($transport);

API-Based Transports (updated for security):

// SendGrid (ensure API key is URL-encoded in DSN)
$transport = Transport::fromDsn('sendgrid://api:'.urlencode('key-123').'@default');
$mailer = new Mailer($transport);

// Mailgun
$transport = Transport::fromDsn('mailgun://api:'.urlencode('key-123').'@default');

Null Transport (Testing) (unchanged):

$transport = Transport::fromDsn('null://default');
$mailer = new Mailer($transport); // Emails are discarded (useful for tests).

3. Templating with Twig/Blade (unchanged):

Using Laravel’s Mailable Classes:

// app/Mail/WelcomeEmail.php
public function build()
{
    return $this->subject('Welcome!')
        ->view('emails.welcome')
        ->with(['user' => $this->user]);
}

Direct Twig Integration (Advanced) (unchanged):

use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bridge\Twig\Mime\BodyRenderer;

$twig = new \Twig\Environment($loader);
$bodyRenderer = new BodyRenderer($twig);

$email = (new TemplatedEmail())
    ->from('noreply@example.com')
    ->to('user@example.com')
    ->subject('Welcome!')
    ->htmlTemplate('emails/welcome.twig')
    ->context(['name' => 'John']);

4. Event Listeners and Logging (unchanged):

Logging Sent Emails:

use Symfony\Component\Mailer\EventListener\MessageLoggerListener;

$logger = new \Monolog\Logger('mailer');
$listener = new MessageLoggerListener($logger);

$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($listener);

$transport = Transport::fromDsn('smtp://...', $eventDispatcher);

Custom Event Subscribers (unchanged):

use Symfony\Component\Mailer\EventListener\MessageSentEvent;

$eventDispatcher->addListener(MessageSentEvent::class, function (MessageSentEvent $event) {
    $message = $event->getMessage();
    info("Sent to: {$message->getTo()[0]}");
});

5. Testing Emails (unchanged):

Using Laravel’s Mail Testing:

public function test_welcome_email()
{
    Mail::fake();

    $this->post('/register', ['email' => 'user@example.com']);

    Mail::assertSent(WelcomeEmail::class, function ($mail) {
        return $mail->hasTo('user@example.com');
    });
}

Manual Transport Verification (unchanged):

$transport = Transport::fromDsn('null://default');
$mailer = new Mailer($transport);

$mailer->send($email);
$sentMessages = $transport->getSentMessages();
$this->assertCount(1, $sentMessages);

Gotchas and Tips

1. Common Pitfalls

DSN Format Issues (updated for security):

  • Incorrect DSN: Ensure proper encoding for API keys in DSNs:
    // Wrong: smtp://user:passhost:port
    // Right: smtp://user:pass@host:port
    // For API keys: smtp://api:$(urlencode 'key-123')@host:port
    
  • SendmailTransport Security Fix: Addresses CVE-2026-45068. Ensure no addresses start with a dash (-) when using SendmailTransport.

TLS/SSL Misconfigurations (unchanged):

  • STARTTLS vs. SSL: Ensure .env matches the transport:
    MAIL_ENCRYPTION=tls  # For STARTTLS (port 587)
    MAIL_ENCRYPTION=ssl  # For implicit SSL (port 465)
    

Memory Leaks (unchanged):

  • Avoid Cloning Messages: Disable cloning in RoundRobinTransport for large emails:
    $transport = new RoundRobinTransport([$primary, $fallback], null, false);
    

Case-Sensitive Headers (unchanged):

  • Forbidden Headers: Some transports enforce case-sensitive headers (e.g., Mailjet):
    $email->addCustomHeader('X-MJ-TemplateErrorReporting', 'true');
    

2. Debugging Tips

Enable Verbose Logging (unchanged):

$transport = Transport::fromDsn('smtp://user:pass@host:port', [
    'debug' => true,
]);

Inspect Raw Messages (unchanged):

$mailer->send($email);
$sentMessages = $transport->getSentMessages();

New: SendmailTransport Security Check

  • Validate Recipient Addresses: Ensure no addresses start with a dash (-) when using SendmailTransport to avoid injection risks:
    $email->to('valid@example.com'); // OK
    $email->to('-invalid@example.com'); // Rejected by SendmailTransport
    

3. New Features in v8.1.0-BETA3

Security Hardening

  • SendmailTransport Fix: Added end-of-options separator before recipients to prevent injection attacks (CVE-2026-45
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
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