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. Installation:

    composer require symfony/mailer
    

    For Twig integration (recommended for Laravel):

    composer require symfony/twig-bridge
    
  2. Configure .env:

    MAIL_MAILER=smtp
    MAIL_HOST=your-smtp-host
    MAIL_PORT=587
    MAIL_USERNAME=your-username
    MAIL_PASSWORD=your-password
    MAIL_ENCRYPTION=tls
    MAIL_FROM_ADDRESS="[email protected]"
    MAIL_FROM_NAME="${APP_NAME}"
    
  3. Service Provider: Register the SymfonyMailerServiceProvider in config/app.php:

    'providers' => [
        // ...
        Symfony\Component\Mailer\MailerServiceProvider::class,
    ],
    
  4. First Email (Plain Text):

    use Symfony\Component\Mailer\MailerInterface;
    use Symfony\Component\Mime\Email;
    
    public function sendWelcomeEmail(MailerInterface $mailer)
    {
        $email = (new Email())
            ->from('[email protected]')
            ->to('[email protected]')
            ->subject('Welcome!')
            ->text('Thanks for signing up!');
    
        $mailer->send($email);
    }
    
  5. First Email (HTML with Twig):

    use Symfony\Bridge\Twig\Mime\TemplatedEmail;
    
    public function sendTemplatedEmail(MailerInterface $mailer)
    {
        $email = (new TemplatedEmail())
            ->from('[email protected]')
            ->to('[email protected]')
            ->subject('Welcome!')
            ->htmlTemplate('emails/welcome.twig')
            ->context(['name' => 'John']);
    
        $mailer->send($email);
    }
    

Key Files to Review

  • config/mail.php (Laravel’s mail config, now compatible with Symfony Mailer)
  • resources/views/emails/ (Store Twig templates here)
  • app/Providers/AppServiceProvider.php (For custom mailers or transports)

Implementation Patterns

1. Dependency Injection

Leverage Laravel’s container to inject MailerInterface or TransportInterface:

use Symfony\Component\Mailer\MailerInterface;

public function __construct(MailerInterface $mailer) {
    $this->mailer = $mailer;
}

2. Dynamic Transports

Use RoundRobinTransport for failover or load balancing:

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

$transports = [
    Transport::fromDsn('smtp://user:[email protected]'),
    Transport::fromDsn('sendmail:///usr/sbin/sendmail -bs'),
];

$roundRobin = new RoundRobinTransport($transports);
$mailer = new Mailer($roundRobin);

3. Event-Driven Extensions

Attach listeners for logging, analytics, or custom logic:

use Symfony\Component\Mailer\EventListener\MessageListener;
use Symfony\Component\EventDispatcher\EventDispatcher;

$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new class implements MessageListenerInterface {
    public function onMessage(MessageEvent $event) {
        // Log or modify the message
    }
});

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

4. Twig Integration

  • Store templates in resources/views/emails/.
  • Use TemplatedEmail for dynamic content:
    $email = (new TemplatedEmail())
        ->htmlTemplate('emails/invoice.twig')
        ->context(['amount' => 99.99, 'due_date' => now()->addDays(7)]);
    

5. Attachments and Embeds

$email = (new Email())
    ->attachFromPath('/path/to/file.pdf')
    ->embedFromPath('/path/to/image.png', 'image-id')
    ->html('<img src="cid:image-id">');

6. Testing

Use NullTransport for unit tests:

use Symfony\Component\Mailer\Transport\NullTransport;

$mailer = new Mailer(new NullTransport());
$mailer->send($email); // No actual email sent

7. Queueing Emails

Pair with Laravel Queues for async sending:

use Illuminate\Support\Facades\Bus;

Bus::dispatch(function () use ($mailer, $email) {
    $mailer->send($email);
});

Gotchas and Tips

Common Pitfalls

  1. Twig Template Paths:

    • Ensure templates are in resources/views/emails/ and use htmlTemplate() with the correct path (e.g., 'emails/welcome.twig').
    • Fix: Verify TwigEnvironment is properly configured in AppServiceProvider.
  2. SMTP Authentication Failures:

    • Double-check .env credentials and encryption (tls/ssl).
    • Debug: Use NullTransport or LogTransport to inspect raw messages:
      $transport = new LogTransport();
      $mailer = new Mailer($transport);
      
  3. HTML vs. Text Conflicts:

    • Always provide both text() and html() content. Some email clients (e.g., Outlook) ignore HTML if text is missing.
    • Tip: Use ->text($email->html) as a fallback.
  4. Attachment Encoding Issues:

    • Non-ASCII filenames may cause failures. Use ->attach() with explicit encoding:
      $email->attachFromPath($path, ['as' => 'encoded-filename.pdf']);
      
  5. Event Dispatcher Scope:

    • If using custom listeners, ensure the EventDispatcher is shared across requests (e.g., via Laravel’s service container).
  6. Microsoft Graph API Quirks:

    • Bypass Return-Path and Sender headers if using MicrosoftGraphApiTransport (see release notes).

Debugging Tips

  1. Log Raw Messages:

    use Symfony\Component\Mailer\Transport\LogTransport;
    
    $transport = new LogTransport();
    $mailer = new Mailer($transport);
    

    Check Laravel logs for the raw email output.

  2. Inspect Headers: Use ->getHeaders() on the Email object to verify custom headers:

    $email->getHeaders()->get('X-Custom-Header');
    
  3. Transport-Specific Issues:

    • Sendmail: Ensure the binary path is correct in the DSN (e.g., sendmail:///usr/sbin/sendmail -bs).
    • Mailgun/SendGrid: Validate API keys and regions (e.g., api://[email protected]).

Performance Optimization

  1. Batch Sending: Use RoundRobinTransport to distribute load across multiple SMTP servers.

  2. Template Caching: Pre-compile Twig templates for faster rendering:

    $twig->addExtension(new \Twig\Extension\StringLoaderExtension());
    
  3. Async Processing: Offload email sending to a queue worker to avoid blocking HTTP responses.


Extension Points

  1. Custom Transports: Extend AbstractTransport for proprietary APIs:

    use Symfony\Component\Mailer\Transport\AbstractTransport;
    
    class CustomTransport extends AbstractTransport {
        public function __toString() {
            return 'custom://...';
        }
        public function send(RawMessage $message) { ... }
    }
    
  2. Message Modifiers: Subclass Email to add domain-specific methods:

    class NewsletterEmail extends Email {
        public function addUnsubscribeLink(string $url) {
            $this->text .= "\n\nUnsubscribe: $url";
        }
    }
    
  3. Event Subscribers: Listen for MessageEvent to log, modify, or reject messages:

    use Symfony\Component\Mailer\EventListener\MessageListenerInterface;
    
    class SpamFilterSubscriber implements MessageListenerInterface {
        public function onMessage(MessageEvent $event) {
            if (str_contains($event->getMessage()->getHtmlBody(), 'win a prize')) {
                $event->stopPropagation();
            }
        }
    }
    

Security Notes

  1. Avoid Hardcoding Credentials: Always use .env for sensitive data (e.g., SMTP passwords, API keys).

  2. Sanitize Email Inputs: Validate recipient addresses to prevent injection:

    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new \InvalidArgumentException('Invalid email address');
    }
    
  3. Rate Limiting: Implement retries with exponential backoff for transient failures (e.g., using RetryTransport).

  4. **CVE-20

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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle