Symfony Mailer it’s a cool way for sending emails from PHP applications. It has a bunch of predefined transports that allow you to send emails through SMTP, Sendgrid, SES, … and may more options. But sometimes we need to do something special that hasn’t been done before.

There is a way to easily create your own custom transport factory which will allow us to do anything required before creating the actual transport. For example I needed to get the AWS SES credentials.

The new factory needs to implement Symfony\Component\Mailer\Transport\TransportFactoryInterface. To remove some boilerplate you can even extend from Symfony\Component\Mailer\Transport\AbstractTransportFactory which will simplify the new factory:

final class CustomTransportFactory extends AbstractTransportFactory
    public function create(Dsn $dsn): TransportInterface
        // create and return the transport

    protected function getSupportedSchemes(): array
        return ['custom_schema'];

Finally, declare the new factory in setting tag the tag mailer.transport_factory with one of the following methods:

# config/services.yaml
    class: App\CustomTransportFactory
    parent: mailer.transport_factory.abstract
      - {name: mailer.transport_factory}
<!-- config/services.xml -->
<service id="mailer.transport_factory.custom" class="App\CustomTransportFactory" parent="mailer.transport_factory.abstract">
    <tag name="mailer.transport_factory"/>
// config/services.php
$services->set('mailer.transport_factory.custom', App\CustomTransportFactory::class)

I opened a pull request to add this info to the official Symfony Mailer documentation.