Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Transport Config & Mailtrap

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We've already learned quite a bit about how to customize a specific email... with a lot more coming. But how do we customize how an email is sent. In Symfony, the way that your messages are delivered is called a transport. Go back to your terminal and run:

git status

The Mailer dsn

When we installed the Mailer component, its recipe did a couple of interesting things. First, it created a new file called config/packages/mailer.yaml. Let's open up that up. Wow... as you can see: the mailer system doesn't really have a lot of config. The only thing here is the dsn: a URL that tells Mailer what server or cloud service to use for delivery. This references an environment variable called MAILER_DSN. Hey! That's the error we just saw:

Environment variable not found: "MAILER_DSN".

The recipe also modified the .env file. If you run

git diff .env

Yep! You'll see that it added a section with an example MAILER_DSN.

Configuring MAILER_DSN

Open up .env. And, at the bottom, uncomment that MAILER_DSN line. By default, this tries to send to a local SMTP server... and I definitely do not have one of those running. But... let's try it anyways. Refresh to resubmit the registration form and... boom!

Connection could not be established with host "tcp://localhost:25"

So how are we going to send emails? Because... there are a lot of different options. You could run your own SMTP server... which is not something I recommend... or register with a cloud email sender - like SendGrid - and use your connection details from them for Mailer. Mailer supports a bunch of the most famous cloud providers... as well as any cloud provider that implements SMTP... which is like... all of them. We're going to show how to use SendGrid a bit later.

Why are we not going to use SendGrid right now? Because... when you're developing and debugging your emails, there's a better option. Instead of sending real emails to a real email server, you can send them to a "fake" mailbox.

One of the most famous tools to do this is called MailCatcher. Basically, you download MailCatcher, start it on your machine, and it creates a temporary SMTP server that you can send to. But instead of delivering the messages, it holds onto them and you can view them all in a fake inbox in your browser. MailCatcher is written in Ruby and a similar tool - MailHog - is written in Go. Those are both great options.

Hello Mailtrap

But... to save me the headache of getting those running, I'm going to use a third option called Mailtrap. Head to mailtrap.io. This is basically a "hosted" version of those tools: it gives us a fake SMTP server and fake inbox, but we don't need to install anything. And it has an excellent free plan.

After you register, you'll end up in a spot like this: with a "Demo inbox". Click into that Demo inbox. On the right, you'll see a bunch of information about how to connect to this. At the time of recording, they do have specific instructions for Symfony 4... but these are for using Mailtrap with SwiftMailer, not Symfony Mailer.

No worries, setup is dead simple. The DSN follows a standard structure: username:password@server:port. Copy the username from Mailtrap, paste, add a colon, copy and paste the password, then @ the server - smtp.mailtrap.io - one more colon, and the port. We could use any of these. Try 2525.

Done! If we haven't messed anything up, our email should be delivered to our Mailtrap inbox. Let's try it! Refresh the form submit and... ah! Validation error. The last time we tried this, the email failed to send but the user was saved to the database. Make the email unique by adding a "2". Then click the terms, enter any password and... register!

Ok, no errors! Go check Mailtrap! There it is! It's got the subject, text content, but no HTML content because we haven't set that yet. There are also a couple of other cool debugging features in Mailtrap - we'll talk about some of these soon.

Now that we've got some success, it's time to attack the obvious shortcoming of this email... it's just text! It's not 1995 anymore people, we need to send HTML emails. And Mailer gives us a great way to do this: native integration with Twig. That's next.

Leave a comment!

37
Login or Register to join the conversation
Abelardo Avatar
Abelardo Avatar Abelardo | posted 3 years ago

Hi there:
When I set up my .env with my Mailtrap credentials, I got this error:
Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:
error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

Extra set up required? :)

I got this from Ubuntu:
SSL Version => OpenSSL/1.1.1c
openssl
OpenSSL support => enabled
OpenSSL Library Version => OpenSSL 1.1.1c 28 May 2019
OpenSSL Header Version => OpenSSL 1.1.1d 10 Sep 2019
Openssl default config => /usr/local/ssl/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Native OpenSSL support => enabled

Does anybody know if this setting is wrong? Any help would be welcome. :)

Best regards.

2 Reply
Abelardo Avatar

Obviously, this is a no-related Symfony issue nor Mailer but local setting (Ubuntu)

2 Reply

Yo Abelardo L.!

Hmm. Well, you were thinking about the same thing I was already - is the openssl php extension running. And yes, it appears it is ;). Because you're using Mailtrap... my guess is that your Mailtrap does not have a valid SSL certificate... which totally makes sense, as this is just a local server :). In fact, I think (?) that Mailtrap might not have a secure connection setup - https://github.com/sj26/mai.... Basically, I think (?) that Mailer should be communicating to Mailtrap in a non-secure manner. If I'm reading Mailer's code correctly, as long as you use port "25" to connect to Mailtrap, it *should* connect *without* "tls".

If you need to do some extra debugging, I would do some "dumping and die'ing" inside this class - https://github.com/symfony/... - to see if tls is ultimately set to false or not.

Let me know if that helps!

Cheers!

2 Reply
Abelardo Avatar

Hi there!
I have reinstalled my Ubuntu copy and all it worked!

What I told you: it was a misconfiguration from my [past] Ubuntu copy. :)

Reply

Hey AbelardoLG,

Ah, good job! Yeah, sounds like so... and we're happy you got it working finally! :)

Cheers!

Reply
Abelardo Avatar

Hi there!

I'm afraid it's not related to Mailtrap since I have tested it with a virtual machine and it worked (althought it was with my own email server data).
I think is due to a misconfiguration of my Ubuntu.

Anyway, thanks for your response. :)

Best regards and happy New Year!

Reply
Cheshire Avatar
Cheshire Avatar Cheshire | posted 5 months ago | edited

Hi, I'm having a really strange error trying to configure this. The error is happening in my CI step when I try to set up the DB schema for the test database.

I'm using mailslurper instead of mailtrap by the way. In my .env file I have:
MAILER_DSN=smtp://mailslurper:2500

However, when I try to create the test DB, I get this error message:

$ php bin/console doctrine:schema:create -e test

 !
 ! [CAUTION] This operation should not be executed in a production environment!
 !

 Creating database schema...


In TransportFactory.php line 54:

  No transport supports the given Messenger DSN ""..

Do you have any idea what could be going on here? Why does it think the DSN is an empty string?

Reply

Hey Cheshire,

That's odd. Is it possible that you are overwriting that env var in a .env.test file (or .env.local.test)?
By the way, I fixed your comment format :)

Cheers!

Reply
Cheshire Avatar

Looking at the source code where the error comes from... https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/Messenger/Transport/TransportFactory.php#L54

It looks like it simply doesn't support smtp:// protocol in the DSN? How can that be right?

Reply

Hey Cheshire,

Sorry for my late reply. I just realized there is confusion. You got an error about the MESSENGER DSN but changed the MAILER DSN env var. Those env vars serve different purposes. Can you double-check that the MESSENGER_TRANSPORT_DSN env var is not empty? Besides that, do you have problems with any other env var? What happens if you use any other built-in transport?
If nothing works, try clearing the cache manually rm -r var/cache/* and upgrade those components

Reply
Cheshire Avatar

Yeah, looks like the DSN is blank for some reason. Something must be wrong with the environmental variables, I just wish I could figure out what! Any ideas aside from the .env.test? Why would it not be seeing what's in the .env file if it's not overridden anywhere?

Reply
Cheshire Avatar

Thanks for replying. No, there is no MAILER_DSN in my .env.test file. Even when I add MAILER_DSN=smtp://mailslurper:2500 to my .env.test file, I get the same error message.

Reply
Cheshire Avatar

Wow, it really messed up the formatting. In my .env I have MAILER_DSN=smtp://mailslurper:2500

Reply
Ali-G Avatar
Ali-G Avatar Ali-G | posted 8 months ago | edited

Good morning, in my case, I have a problem, symfony does not autowrite the transport configuration in mailer.yml but uses the default configuration:

    "main" => Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport {#679 â–¼
      -authenticators: array:4 [â–¶]
      -username: "user"
      -password: "pass"
      -started: false
      -restartThreshold: 100
      -restartThresholdSleep: 0
      -restartCounter: null
      -pingThreshold: 100
      -lastMessageTime: 0
      -stream: Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream {#713 â–¶}
      -domain: "[127.0.0.1]"
      -dispatcher: Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher {#141 …8}
      -logger: Symfony\Bridge\Monolog\Logger {#692 …8}
      -rate: 0
      -lastSent: 0
    }
Reply

Hey Ali!

Hmm. What does your mailer.yaml look like? And what config do you have in that file that you don't see here? Also, can you tell me where exactly this dump is coming from?

Cheers!

Reply
Alessandro V. Avatar
Alessandro V. Avatar Alessandro V. | posted 1 year ago

hi, i'm using symfony6 and mailtrap. With the same configuration, the mail doesn't work. In the log says "Sending message Symfony\Component\Mailer\Messenger\SendEmailMessage with async sender using Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineTransport" but the smtp server is silent and mailtrap doesn't receive anything. There is something new that i must do? thanks

Reply

Hey Alessandro V.

Did you run php bin/console messenger:consume async

Cheers!

2 Reply
Jose-M Avatar

i used to send email without this command, please is there's any way that i can send mails without having to run php bin/console messenger:consume async in the background ?

Reply

Hey @Jose-M,

no problem, just tweak config/packages/messenger.yaml

framework:
    messenger:
        # ...
        routing:
            # ...
            'Symfony\Component\Mailer\Messenger\SendEmailMessage': sync

Cheers!

1 Reply
Alessandro V. Avatar
Alessandro V. Avatar Alessandro V. | sadikoff | posted 1 year ago

Thank you! works like a charm now. Now i want to know more about this messenger, it seems useful

Reply

Awesome!

BTW i have a tip for you https://symfonycasts.com/sc... ;)

Cheers!

Reply
Viktoriia K. Avatar
Viktoriia K. Avatar Viktoriia K. | posted 3 years ago

Hi everybody, I am having en issue with Symfony 4 mailer. I have decided to migrate from Swiftmailer (which works just fine) but symfony mailer doesn't accept my DNS. The error comes up "mailer DSN is invalid". Digging into problem, I figured out than Symfony mailer doens't accept in password "#" simbol.

In file vendor\symfony\mailer\Transport\Dsn.php (line 42) this line is fail if (false === $parsedDsn = parse_url($dsn))
Example password "dfg4_d#dfg"
We can't not change email password, so we have to keep using Switfmailer. I think thant symfony team has fix it.
Best regards

Reply

Hi Viktoriia K.!

Excellent debugging to track down the issue! Here's aa PHP bug report describing your problem: https://bugs.php.net/bug.php?id=73754

Basically, your password is "supposed to be" URL encoded... and the new code is "enforcing" this. The fix should be easy though - URL encode the password. So, change # into %23.

Let me know if that helps!

Cheers!

Reply
Viktoriia K. Avatar

Thank you very much. It works now.

Reply
Steve-D Avatar
Steve-D Avatar Steve-D | posted 3 years ago

HI. I've moved over to Mailer from SwiftMailer but can't find any option to use Office 365, is it possible to configure to use O365 or are hte options the ones listed in the main Symfony docs?

Cheers

Reply

Hey Steve,

Unfortunately I know very little about Office 365. Does Swiftmailer has an integration with it? Do you attach some docs directly from Office 365? Symfony Mailer allows you to attach files as attachments, so the whole doc will be sent to your addressee. And you can set that attachement via PHP resource, i.e. you don't need to get the content of the file with file_get_content() and add it to the email. Here's where we create a PDF file and attach it to the email: https://symfonycasts.com/sc... - I suppose you can do the same with your docs reading them from Office 365.

I hope this helps!

Cheers!

Reply
Steve-D Avatar

Thanks Victor however I may not have been 100% clear, it's about using O365 as a transport option rather than attachments. In SM I can use this:

MAILER_URL=smtp://smtp.office365.com:587?encryption=tls&username=user@domain.tld&password=password1234

Does that make sense?

Steve

Reply

Hey Steve,

Oh, now I see :) Yeah, unfortunately, Symfony Mailer has native integration only with the next several transports: https://symfony.com/doc/current/mailer.html#using-a-3rd-party-transport . But it does not mean you can't use it for other services like Office 365. As long as they work via SMTP - it just should work. You just need to set the correct value for MAILER_DSN env var, see https://symfony.com/doc/current/mailer.html#transport-setup. So, you need to change the format a bit, e.g. username/password should be before the host. Try this one:


MAILER_DSN=smtp://user:password1234@smtp.office365.com:587?encryption=tls

Does it work for you?

Cheers!

Reply
Steve-D Avatar

Hi Victor, thank you for help and sorry for delay, I hadn't seen the notification.

This doesn't work unfortunately, it is something I had tried.

Steve

Reply
Steve-D Avatar

In fact it does work but the password has issues with certain characters... $ and or ^ are not good.

Thank you for the help. Have a great day

Steve

Reply

Hey Steve,

Ah, yes... I remember something like this, and if I'm not wrong, we even talked about it in the video? Yes, that's limitation of environment variables itself. You can easily replace them with other chars, like "*" or brackets I suppose.

Anyway, I'm glad you figured it out yourself!

Cheers!

Reply
Dirk Avatar
Dirk Avatar Dirk | posted 3 years ago | edited

I do have a local STMP-server that I wish to send emails from. When I was using swiftmailer, I could use:
MAILER_URL=smtp://localhost
Now when I try MAILER_DSN=smtp://localhost, I get an error:
<blockquote>
Warning: stream_socket_enable_crypto(): Peer certificate CN=mail.example.com' did not match expected CN=localhost'
</blockquote>
I tried just about everything, and when using this smtp-server from another machine (and providing all required credentials) I <u>can</u> use Symfony Mailer. But from the same machine... no luck. Any ideas what I could do differently?

Reply
Dirk Avatar

I figured out what I could do differently, setting 'mail.example.com' in my hosts file under 127.0.1.1 seems to work!

1 Reply

Hey Dirk

I'm glad to hear that you could fix your problem. Thanks for sharing your solution with others :)

Cheers!

Reply
Abelardo Avatar
Abelardo Avatar Abelardo | posted 3 years ago

Here is another post about this service: https://blog.mailtrap.io/se...

Reply

Hey AbelardoLG,

Thank you for sharing this post!

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built on Symfony 4.3, but will work well with Symfony 4.4 or 5.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "aws/aws-sdk-php": "^3.87", // 3.110.11
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-snappy-bundle": "^1.6", // v1.6.0
        "knplabs/knp-time-bundle": "^1.8", // v1.9.1
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.23
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "league/html-to-markdown": "^4.8", // 4.8.2
        "liip/imagine-bundle": "^2.1", // 2.1.0
        "nexylan/slack-bundle": "^2.1,<2.2.0", // v2.1.0
        "oneup/flysystem-bundle": "^3.0", // 3.1.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.4.1
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.3.4
        "symfony/console": "^4.0", // v4.3.4
        "symfony/flex": "^1.9", // v1.17.6
        "symfony/form": "^4.0", // v4.3.4
        "symfony/framework-bundle": "^4.0", // v4.3.4
        "symfony/mailer": "4.3.*", // v4.3.4
        "symfony/messenger": "4.3.*", // v4.3.4
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.3.4
        "symfony/sendgrid-mailer": "4.3.*", // v4.3.4
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "^4.0", // v4.3.4
        "symfony/twig-pack": "^1.0", // v1.0.0
        "symfony/validator": "^4.0", // v4.3.4
        "symfony/web-server-bundle": "^4.0", // v4.3.4
        "symfony/webpack-encore-bundle": "^1.4", // v1.6.2
        "symfony/yaml": "^4.0", // v4.3.4
        "twig/cssinliner-extra": "^2.12", // v2.12.0
        "twig/extensions": "^1.5", // v1.5.4
        "twig/inky-extra": "^2.12" // v2.12.0
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.2.2
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/browser-kit": "4.3.*", // v4.3.5
        "symfony/debug-bundle": "^3.3|^4.0", // v4.3.4
        "symfony/dotenv": "^4.0", // v4.3.4
        "symfony/maker-bundle": "^1.0", // v1.13.0
        "symfony/monolog-bundle": "^3.0", // v3.4.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.4
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "^3.3|^4.0" // v4.3.4
    }
}
userVoice