Installation
composer require sylius/mailer-bundle
Add the bundle to config/bundles.php:
return [
// ...
Sylius\Bundle\MailerBundle\SyliusMailerBundle::class => ['all' => true],
];
Configuration
Configure your mailer in config/packages/sylius_mailer.yaml:
sylius_mailer:
mailer:
dsn: '%env(MAILER_DSN)%' # e.g., 'smtp://user:pass@smtp.example.com:port'
transport: 'smtp' # or 'sendmail', 'failover', etc.
templates:
path: '%kernel.project_dir%/templates/mailer'
First Use Case
Create a template file (e.g., welcome.txt.twig in templates/mailer/):
Hello {{ name }},
Welcome to our platform!
Send an email in a controller:
use Sylius\Component\Mailer\Sender\SenderInterface;
public function sendWelcomeEmail(SenderInterface $sender, string $email, string $name): void
{
$sender->send(
new Email(
'Welcome',
$email,
'welcome.txt.twig',
['name' => $name]
)
);
}
Template Management
templates/mailer/ (supports .twig, .html.twig, .txt.twig).{# templates/mailer/order_confirmation.html.twig #}
<h1>Order #{{ order.number }}</h1>
templates/mailer/ directory.Email Sending
$sender->send(new Email('Subject', 'recipient@example.com', 'template.twig', ['var' => 'value']));
# config/packages/messenger.yaml
framework:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'Sylius\Component\Mailer\Message\SendEmailMessage': async
Then dispatch:
$bus->dispatch(new SendEmailMessage($email));
Event-Driven Emails
Subscribe to Sylius events (e.g., OrderCreatedEvent) and trigger emails:
use Sylius\Component\Core\Event\OrderCreatedEvent;
public function __invoke(OrderCreatedEvent $event): void
{
$sender->send(new Email(
'Order Confirmation',
$event->getOrder()->getCustomer()->getEmail(),
'order_confirmation.html.twig',
['order' => $event->getOrder()]
));
}
Testing
null transport for tests:
sylius_mailer:
mailer:
transport: 'null://default'
$this->assertCount(1, $this->container->get('sylius.mailer.sender')->getSentEmails());
Custom Mailer Logic:
Extend the Email class or create a decorator for SenderInterface:
class CustomSender implements SenderInterface
{
private $decorated;
public function __construct(SenderInterface $decorated) { $this->decorated = $decorated; }
public function send(Email $email): void
{
// Add custom logic (e.g., logging, analytics)
$this->decorated->send($email);
}
}
Register as a service:
services:
Sylius\Component\Mailer\Sender\SenderInterface: '@app.custom_sender'
Dynamic Templates: Use a service to resolve template paths dynamically:
$templatePath = $this->templateResolver->resolve('mailer', 'dynamic_template.twig', ['locale' => $locale]);
Localization: Combine with Symfony’s translation system for multi-language emails:
{# templates/mailer/welcome.html.twig #}
<h1>{{ 'welcome.heading'|trans }}</h1>
Template Caching:
php bin/console cache:clear
config/packages/twig.yaml for development:
twig:
cache: false
DSN Configuration:
MAILER_DSN is correctly formatted (e.g., smtp://user:pass@host:port).sylius_mailer:
mailer:
dsn: '%env(MAILER_DSN)%'
transport_options:
encryption: ssl
port: 465
Async Transport Quirks:
async transport, ensure the messenger worker is running:
php bin/console messenger:consume async -vv
php bin/console messenger:failed:list
php bin/console messenger:failed:retry <message-id>
Attachment Limits:
if ($attachment->getSize() > 10_000_000) { // 10MB
throw new \RuntimeException('Attachment too large');
}
Log Sent Emails: Add a subscriber to log emails:
public function onEmailSent(EmailSentEvent $event): void
{
$this->logger->info('Email sent', [
'subject' => $event->getEmail()->getSubject(),
'to' => $event->getEmail()->getTo(),
]);
}
Check Transport Errors:
Enable verbose logging in config/packages/monolog.yaml:
monolog:
handlers:
main:
level: debug
Custom Email Events:
Extend the EmailSentEvent or create your own:
class CustomEmailEvent extends EmailSentEvent
{
public function getCustomData(): array { /* ... */ }
}
Template Preprocessors: Add logic before rendering templates via a compiler pass or event listener:
public function onEmailRender(EmailRenderEvent $event): void
{
$event->setTemplateData(array_merge($event->getTemplateData(), ['custom_var' => true]));
}
Transport Factories: Create custom transports (e.g., for AWS SES):
class AWSSesTransportFactory implements TransportFactoryInterface
{
public function createTransport(array $options): TransportInterface
{
return new AWSSesTransport($options);
}
}
Register in config/packages/sylius_mailer.yaml:
sylius_mailer:
mailer:
transport: 'aws_ses'
Bulk Email Optimization: Use batch processing for large email lists:
foreach ($emails as $batch) {
$sender->sendBatch($batch);
}
How can I help you explore Laravel packages today?