Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Mailer Integration With Symfony Mailer

Mailer Integration With Symfony Mailer

~16 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

To wrap up block 6, let's close the loop: Symfony Mailer sends a REAL email once our TaskAssignedEvent from chapter 36 fires.

Installing Symfony Mailer

composer require symfony/mailer

The recipe (chapter 6) adds MAILER_DSN to .env – ANALOGOUS to DATABASE_URL from chapter 4, configured via an environment variable instead of being hardcoded.

Configuring MAILER_DSN

.env
# For local development: Mailpit/Mailhog (catches emails, sends NOTHING for real)
MAILER_DSN=smtp://localhost:1025

# For production, example with an SMTP provider:
# MAILER_DSN=smtp://user:password@smtp.provider.com:587

Tipp: EXACTLY like with the database (chapter 2), a Docker container instead of real email delivery is recommended for local development – Mailpit (or the older MailHog) catches EVERY outgoing email locally and displays it in a web interface, WITHOUT actually delivering it anywhere. That way, sending can be tested risk-free.

Extending the chapter 36 listener with email sending

src/EventListener/TaskAssignedListener.php
<?php

declare(strict_types=1);

namespace App\EventListener;

use App\Event\TaskAssignedEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;

#[AsEventListener]
class TaskAssignedListener
{
    public function __construct(
        private readonly MailerInterface $mailer,
    ) {
    }

    public function __invoke(TaskAssignedEvent $event): void
    {
        $task = $event->getTask();
        $user = $event->getAssignedUser();

        $email = (new Email())
            ->from('noreply@task-manager.example')
            ->to($user->getEmail())
            ->subject(sprintf('New task: %s', $task->getTitle()))
            ->text(sprintf(
                'Hi %s,%sYou have been assigned the task "%s".',
                $user->getName(),
                "\n\n",
                $task->getTitle(),
            ));

        $this->mailer->send($email);
    }
}

EXACTLY as promised in chapter 36: TaskAssignmentService was NOT touched even once for this extension – the existing listener simply got extended with MailerInterface AND the actual email creation.

HTML emails with Twig templates

For nicer-formatted emails, Symfony Mailer uses the same Twig engine as our regular pages (chapter 13):

templates/emails/task_assigned.html.twig
<h1>New Task Assigned</h1>

<p>Hi {{ user.name }},</p>
<p>You have been assigned the task <strong>{{ task.title }}</strong>.</p>
use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
    ->from('noreply@task-manager.example')
    ->to($user->getEmail())
    ->subject(sprintf('New task: %s', $task->getTitle()))
    ->htmlTemplate('emails/task_assigned.html.twig')
    ->context([
        'task' => $task,
        'user' => $user,
    ])
;

$this->mailer->send($email);

TemplatedEmail instead of Email, htmlTemplate() instead of text(), context() passes variables to the template – EXACTLY the same principle as render() in a controller (chapter 13), just for emails instead of web pages.

A preview: asynchronous sending

Sending an email can take several seconds (network latency to the SMTP server) – if sending runs SYNCHRONOUSLY inside the dispatch() call from chapter 36, the USER waits through that entire time before the page loads. Symfony's Messenger component (deliberately outside this course's scope) would instead offload sending to a queue, processed asynchronously in the background – a sensible next step for a production system, but its own, extensive topic.

With that, block 6 (services, dependency injection & events) is FULLY complete – from the core principle (chapter 32) through custom services (chapter 33), configuration (chapter 34), the event system (chapters 35-37), to the concrete email feature. Block 7 covers console commands and testing – automation and quality assurance for our task manager.