How to Create a Custom Email Transport with Symfony Mailer

Today, we're going to see how to create a custom email transport with Symfony Mailer. For the example, we'll create a transport named “pt”.

Prerequisites

Before we begin, make sure you have installed and configured Symfony Mailer and HttpClient in your project. You can add them to your project using the following commands:

composer require symfony/mailer
composer require symfony/http-client

Creating the Transport Class

The first thing to do is to create a new class that implements Symfony\Component\Mailer\Transport\TransportInterface. We will call it PtTransport. Here is an example of what this might look like:

// src/Mailer/Transport/PtTransport.php

namespace App\Mailer\Transport;

use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\RawMessage;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class PtTransport implements TransportInterface
{
    private $httpClient;
    private $username;
    private $password;
    private $endpointUrl;

    public function __construct(HttpClientInterface $httpClient, string $username, string $password, string $endpointUrl)
    {
        $this->httpClient = $httpClient;
        $this->username = $username;
        $this->password = $password;
        $this->endpointUrl = $endpointUrl;
    }

    public function send(RawMessage $message, ?Symfony\Component\Mailer\Envelope $envelope = null): ?Symfony\Component\Mailer\SentMessage
    {
        // Implémentez ici votre logique d'envoi d'e-mail
        // Vous pouvez utiliser $this->httpClient pour faire une requête HTTP à $this->endpointUrl
    }

    public function __toString(): string
    {
        return sprintf('pt://%s@%s', $this->username, $this->endpointUrl);
    }
}

Creating the Factory Class

Next, we need to create a factory class that will be responsible for creating instances of PtTransport. We'll call this class PtTransportFactory. Here is an example of what this could look like:

// src/Mailer/Transport/PtTransportFactory.php

namespace App\Mailer\Transport;

use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
use Symfony\Component\Mailer\Transport\AbstractTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class PtTransportFactory extends AbstractTransportFactory
{
    private $httpClient;

    public function __construct(HttpClientInterface $httpClient)
    {
        $this->httpClient = $httpClient;
    }

    public function supports(Dsn $dsn): bool
    {
        return 'pt' === $dsn->getScheme();
    }

    public function create(Dsn $dsn): TransportInterface
    {
        return new PtTransport(
            $this->httpClient,
            $dsn->getUser(),
            $dsn->getPassword(),
            $dsn->getOption('endpoint_url')
        );
    }
}

Configuration

After that, we need to register PtTransportFactory as a service and tag it with mailer.transport_factory. Here's how to do this in services.yaml:

services:
    App\Mailer\Transport\Pt

Next, we need to register PtTransportFactory as a service and tag it with mailer.transport_factory. Here's how to do this in services.yaml:

services:
    App\Mailer\Transport\PtTransportFactory:
        tags: ['mailer.transport_factory']
        arguments:
            $httpClient: '@http_client'

Usage

Now, you can use your new custom email transport by configuring your mailer DSN in your .env file:

MAILER_DSN=pt://username:password@default?endpoint_url=https://your-endpoint-url

And there you have it! You now have a custom email transport with Symfony Mailer. The next time you send an email, Symfony will use your new transport.

Conclusion

Symfony Mailer is a powerful and flexible tool for managing email sending in your Symfony applications. By creating a custom email transport, you can easily integrate any email sending service into your application, even if it's not directly supported by Symfony Mailer.

I hope this article has been helpful and that you now have a better understanding of how to use Symfony Mailer to create a custom email transport.