15

I'm configuring a mail server (postfix), with a self signed certificate, and it seems this self signed certificate is a problem for the Symfony Mailer component.

On Swiftmailer, using some configuration such as:

transport:
    stream_options:
        ssl:
            allow_self_signed: true

or

stream_options:
    ssl:
        verify_peer: false
        verify_peer_name: false

might fix it, but I can't find a way to do that on mailer (I want to use the YAML configuration files if possible).

yivi
  • 42,438
  • 18
  • 116
  • 138
FTW
  • 922
  • 1
  • 7
  • 19

3 Answers3

15

This option will been enabled when this pull request, which has been already merged into master, is tagged and released.

So it seems you would have to wait for the next Symfony release (this was merged into the 5.1 branch, so it doesn't look like it's going to be available in the 4.x branch at all), and then you will able to do this by adding verify_peer to your Mailer DSN configuration.

Regularly, you'll be able configure Mailer, you need only to create a MAILER_DSN environment variable (usually setting the value on one of your .env files is enough).

In a near future, you'll be able to do this:

MAILER_DSN=smtp://user:pass@localhost?verify_peer=false

But right now (as of 4.4.4 and 5.0.4) you can't do this natively with Symfony Mailer.

yivi
  • 42,438
  • 18
  • 116
  • 138
  • It seems perfect ! But it doesn't seem to be under a tag yet, is it ? I'm currently on 4.4, no update available and I don't have this... – FTW Feb 21 '20 at 18:26
  • You are right, it doesn't appear to have been merged. It exists on [master's changelog](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Mailer/CHANGELOG.md), but not on [4.4.4 changelog](https://github.com/symfony/symfony/blob/v4.4.4/src/Symfony/Component/Mailer/CHANGELOG.md). I'll amend the answer to reflect that. I'm sure 4.4.5 should be released soonish. – yivi Feb 21 '20 at 18:32
  • You mean that the issue will be fixed just in 4.4.5 , not 4.4.4 ? because I have the same problem and I'm using the last lTS (4.4.4) – hous Feb 25 '20 at 10:28
  • @hous Yup, as explained in the answer and comments; 4.4.4 does not include this feature yet. Since it has been merged to master, next release should include it. – yivi Feb 25 '20 at 10:30
  • @yivi , yes I'll do ;) but do you know when 4.4.5 will be released ? because I'm about making project with 4.4.4 and I don't like to use SwiftMailer – hous Feb 25 '20 at 10:41
  • No idea, @hous. It should be too long now, but there is no preset release schedule for minor versions that I know of. – yivi Feb 25 '20 at 10:43
8

Unfortunatly verify_peer feature is not in symfony 4.4 (yet) as @yivi states correctly.

I tried updating symfony/mailer in composer to dev-master but symfony flex constraints doesnt allow this due to:

Restricting packages listed in "symfony/symfony" to "4.4.*"

So i ended up overriding mailer.transport_factory.smtp:

mailer.transport_factory.smtp:
    class: App\Mailer\EsmtpTransportFactory
    tags:
      - { name: 'mailer.transport_factory', priority: "-100" }

with a custom EsmtpTransportFactory that contains this feature:

<?php


namespace App\Mailer;

use Symfony\Component\Mailer\Transport\AbstractTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mailer\Transport\TransportInterface;

final class EsmtpTransportFactory extends AbstractTransportFactory
{
    public function create(Dsn $dsn): TransportInterface
    {
        $tls = 'smtps' === $dsn->getScheme() ? true : null;
        $port = $dsn->getPort(0);
        $host = $dsn->getHost();

        $transport = new EsmtpTransport($host, $port, $tls, $this->dispatcher, $this->logger);

        if (!$dsn->getOption('verify_peer', true)) {
            /** @var SocketStream $stream */
            $stream = $transport->getStream();
            $streamOptions = $stream->getStreamOptions();

            $streamOptions['ssl']['verify_peer'] = false;
            $streamOptions['ssl']['verify_peer_name'] = false;

            $stream->setStreamOptions($streamOptions);
        }

        if ($user = $dsn->getUser()) {
            $transport->setUsername($user);
        }

        if ($password = $dsn->getPassword()) {
            $transport->setPassword($password);
        }

        return $transport;
    }

    protected function getSupportedSchemes(): array
    {
        return ['smtp', 'smtps'];
    }
}

Note the bool value if verify_peer in the DSN can't be a string.
This will not work: MAILER_DSN=smtp://foo@default?verify_peer=false
This will work: MAILER_DSN=smtp://foo@default?verify_peer=0
or as mentioned in this comment:

parameters:
  env(verify): 'false'

framework:
  mailer:
  dsn: '%env(MAILER_DSN)%?verify_peer=%env(bool:verify)%'

I guess it would be better if this feature was ported to 4.4 but so long i use this workaround.

ivoba
  • 5,780
  • 5
  • 48
  • 55
  • Where do you configure "mailer.transport_factory.smtp"? In mailer.yaml I get a **Invalid type for path "framework.mailer.transports.smtp". Expected scalar, but got array.** when adding framework: mailer: dsn: '%env(MAILER_DSN)%' transports: smtp: class: App\Mailer\EsmtpTransportFactory tags: - { name: 'mailer.transport_factory', priority: "-100" } – circulosmeos May 18 '22 at 08:24
  • 1
    @circulosmeos this must happen under `services:` section. I suppose you did add it to bundle config. Better place it into services.yaml. – ivoba May 18 '22 at 11:31
  • Really solid solution. It worked for me. For others that struggled with it, then the `mailer.transport_factory.smtp` should go in `config/services.yaml` (in the `services`-section of that file). And the class should be created in `src/Mailer/EsmtpTransportFactory.php`. <3 – Zeth Nov 11 '22 at 14:13
0

You can use:

MAILER_DSN="smtp://user:pass@localhost?encryption=ssl&stream_options[ssl][verify_peer]=false&stream_options[ssl][verify_peer_name]=false&stream_options[ssl][allow_self_signed]=true"
Pawel
  • 11
  • 1