Chapters
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Transport Config & Mailtrap
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
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.
39 Comments
Obviously, this is a no-related Symfony issue nor Mailer but local setting (Ubuntu)
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!
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. :)
Hey AbelardoLG,
Ah, good job! Yeah, sounds like so... and we're happy you got it working finally! :)
Cheers!
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!
I am using Windows with SQL from XAMPP. It appears that sending the email is Successful, but mailtrap is not receiving anything.
$mail = (new Email())
->from('your-email@example.com')
->to('recipient-email@example.com')
->subject('Test email')
->text('This is a test email.');
try {
$mailer->send($mail);
$this->addFlash('success', 'Email sent successfully.');
} catch (TransportExceptionInterface $e) {
$this->addFlash('error', 'An error occurred while sending the email.');
$this->addFlash('error', $e->getMessage()); // Debugging purposes only. In a production environment, you should log this error.
}
I am receiving the Success Message, but the email is not hitting mailtrap. Do you have any Idea?
Best Regards
Hi @Mahmoud-A,
Have you tried to debug it with symfony profiler? IIRC it should be registered there as sent email, also you can check if mail trap was used for it.
Cheers
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?
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!
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?
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
Sorry, this is the version I'm on- https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Messenger/Transport/TransportFactory.php#L54
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?
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.
Wow, it really messed up the formatting. In my .env I have MAILER_DSN=smtp://mailslurper:2500
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
}
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!
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
Hey Alessandro V.
Did you run php bin/console messenger:consume async
Cheers!
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 ?
Hey @Jose-M,
no problem, just tweak config/packages/messenger.yaml
framework:
messenger:
# ...
routing:
# ...
'Symfony\Component\Mailer\Messenger\SendEmailMessage': sync
Cheers!
Thank you! works like a charm now. Now i want to know more about this messenger, it seems useful
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
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!
Thank you very much. It works now.
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
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!
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
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!
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
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
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!
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?
I figured out what I could do differently, setting 'mail.example.com' in my hosts file under 127.0.1.1 seems to work!
Hey Dirk
I'm glad to hear that you could fix your problem. Thanks for sharing your solution with others :)
Cheers!
Here is another post about this service: https://blog.mailtrap.io/se...
Hey AbelardoLG,
Thank you for sharing this post!
Cheers!
"Houston: no signs of life"
Start the conversation!
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
"doctrine/annotations": "^1.0", // 1.10.1
"doctrine/doctrine-bundle": "^1.6.10", // 1.11.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"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
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.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.21.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/property-access": "4.3.*", // v4.3.4
"symfony/property-info": "4.3.*", // v4.3.4
"symfony/security-bundle": "^4.0", // v4.3.4
"symfony/sendgrid-mailer": "4.3.*", // v4.3.4
"symfony/serializer": "4.3.*", // v4.3.4
"symfony/twig-bundle": "^4.0", // v4.3.4
"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/extra-bundle": "^2.12|^3.0", // v2.12.1
"twig/inky-extra": "^2.12", // v2.12.0
"twig/twig": "^2.12|^3.0" // v2.13.1
},
"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/stopwatch": "4.3.*", // v4.3.4
"symfony/var-dumper": "^3.3|^4.0", // v4.3.4
"symfony/web-profiler-bundle": "4.3.*" // v4.3.4
}
}
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.