WEBVTT NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com 00:00:01.256 --> 00:00:04.786 align:middle The HTML content of our email will use this template... 00:00:04.786 --> 00:00:06.906 align:middle which is still totally static. 00:00:06.906 --> 00:00:10.936 align:middle For example, see this link going to #homepage? 00:00:11.476 --> 00:00:13.256 align:middle That's just a placeholder. 00:00:13.646 --> 00:00:16.926 align:middle Normally in a template, we would use the {{ path() }} function 00:00:16.926 --> 00:00:19.666 align:middle to generate a URL to the homepage route. 00:00:20.476 --> 00:00:22.546 align:middle The name of that route is... 00:00:22.546 --> 00:00:24.506 align:middle check out ArticleController... 00:00:24.906 --> 00:00:28.316 align:middle there it is: the homepage route name is app_homepage. 00:00:28.966 --> 00:00:32.826 align:middle So we would normally say path('app_homepage'). 00:00:33.376 --> 00:00:37.606 align:middle The problem is that this will generate a relative URL - 00:00:37.896 --> 00:00:40.716 align:middle it will literally generate href="/". 00:00:40.796 --> 00:00:45.016 align:middle But for an email, all paths must be absolute. 00:00:45.016 --> 00:00:49.096 align:middle To force that, change path() to url(). 00:00:49.976 --> 00:00:50.506 align:middle That's it! 00:00:50.906 --> 00:00:53.096 align:middle Symfony will detect the domain name - 00:00:53.426 --> 00:00:59.036 align:middle localhost:8000 while we're coding locally - and use that to prefix the URL. 00:00:59.946 --> 00:01:04.886 align:middle Let's fix a few other URLs: for the link to create a new article, 00:01:05.366 --> 00:01:10.996 align:middle replace the hardcoded string with url() and the name of that route, which if you looked 00:01:10.996 --> 00:01:14.156 align:middle in the app, is admin_article_new. 00:01:15.076 --> 00:01:18.116 align:middle At the bottom, there's one more link to the homepage. 00:01:18.576 --> 00:01:21.136 align:middle Say {{ url('app_homepage') }}. 00:01:22.536 --> 00:01:23.606 align:middle Links, done! 00:01:24.166 --> 00:01:28.866 align:middle But there's one other path we need to fix: the path to this image. 00:01:29.506 --> 00:01:32.186 align:middle But... forget about emails for a minute. 00:01:32.966 --> 00:01:39.966 align:middle This project uses Webpack Encore to compile its assets: I have an assets/ directory at the root, 00:01:40.646 --> 00:01:47.566 align:middle an images directory inside that, and an email/logo.png file that I want to reference. 00:01:48.686 --> 00:01:54.386 align:middle You don't need to run Encore, but if you did, I've configured it to copy that file 00:01:54.386 --> 00:01:57.806 align:middle into a public/build/images/ directory. 00:01:59.106 --> 00:02:07.706 align:middle There it is: public/build/images/email/logo.66125a81.png. 00:02:07.706 --> 00:02:11.116 align:middle If you downloaded the starting code for the tutorial, 00:02:11.276 --> 00:02:13.926 align:middle you don't need to worry about running Encore... 00:02:14.236 --> 00:02:20.766 align:middle only because we ran it for you and included the final, built public/build directory. 00:02:21.536 --> 00:02:25.476 align:middle I mean, you can run Encore if you want - you just don't need 00:02:25.476 --> 00:02:27.616 align:middle to because the built files are already there. 00:02:28.516 --> 00:02:35.396 align:middle The point is, whether you're using Encore or not, the end goal is to generate an absolute URL 00:02:35.396 --> 00:02:38.566 align:middle to a file that lives somewhere in your public/ directory. 00:02:39.976 --> 00:02:42.906 align:middle To do that in Twig, we use the {{ asset() }} function. 00:02:44.376 --> 00:02:49.076 align:middle Pass this build/images/email/logo.png. 00:02:49.966 --> 00:02:54.806 align:middle Because we're using Encore, we don't need to include the version hash that's part 00:02:54.806 --> 00:02:58.996 align:middle of the real file: the asset function will add that automatically. 00:02:59.446 --> 00:03:03.556 align:middle Go team! If you're not using Encore, it's the same process: 00:03:04.376 --> 00:03:08.686 align:middle just use asset() then include the actual path to the physical file, 00:03:08.946 --> 00:03:11.046 align:middle relative to the public/ directory. 00:03:11.786 --> 00:03:17.376 align:middle But... this leaves us with the same problem we had for the generated URLs! 00:03:18.156 --> 00:03:22.186 align:middle By default, the asset() function generates relative URLs: 00:03:22.376 --> 00:03:24.546 align:middle they don't contain the domain name. 00:03:25.086 --> 00:03:30.006 align:middle To fix that, wrap this in another function: absolute_url(). 00:03:30.626 --> 00:03:31.746 align:middle And... done! 00:03:32.726 --> 00:03:33.826 align:middle Ready to try this? 00:03:34.776 --> 00:03:40.206 align:middle Move over to the site, go back, change the email address again... 00:03:40.206 --> 00:03:41.776 align:middle we're going to do this a lot... 00:03:42.366 --> 00:03:45.546 align:middle type a new password, wave a magic wand and... 00:03:45.676 --> 00:03:46.476 align:middle hit enter. 00:03:47.766 --> 00:03:49.386 align:middle Ok... no errors... 00:03:49.466 --> 00:03:50.226 align:middle a good sign! 00:03:50.926 --> 00:03:53.986 align:middle Over in Mailtrap, it's already there! 00:03:54.476 --> 00:04:02.006 align:middle Oh, it looks so much better: we even have a working image and, if we hover over a link, 00:04:02.316 --> 00:04:07.696 align:middle the URL does contain our domain: localhost:8000. 00:04:08.376 --> 00:04:13.266 align:middle This is even more obvious in the HTML source: everything has a full URL. 00:04:14.446 --> 00:04:15.506 align:middle Woh, and... 00:04:15.506 --> 00:04:18.066 align:middle our email also has a text part! 00:04:18.436 --> 00:04:19.446 align:middle How did that happen? 00:04:19.446 --> 00:04:26.956 align:middle In the controller, we only called htmlTemplate() - we removed our call to the text() method. 00:04:27.506 --> 00:04:29.496 align:middle Well... thank you Mailer. 00:04:29.496 --> 00:04:35.336 align:middle If you set the HTML on an email but do not explicitly set the text, 00:04:35.336 --> 00:04:40.536 align:middle Symfony automatically adds it for you by calling strip_slashes() on your HTML. 00:04:41.076 --> 00:04:42.486 align:middle That's awesome. 00:04:43.116 --> 00:04:44.516 align:middle Well... awesome... 00:04:44.546 --> 00:04:49.196 align:middle but not totally perfect: it included all the styles on top! 00:04:49.866 --> 00:04:51.956 align:middle Don't worry: we'll fix that soon... 00:04:52.206 --> 00:04:53.806 align:middle kinda on accident. 00:04:54.346 --> 00:04:56.166 align:middle But the bottom looks pretty great... 00:04:56.336 --> 00:04:57.746 align:middle with zero effort. 00:04:58.636 --> 00:05:03.306 align:middle Next, the URLs and image paths in our email are now dynamic... 00:05:03.586 --> 00:05:05.356 align:middle but nothing else is! 00:05:05.856 --> 00:05:11.186 align:middle Any self-respecting email must have real data, like the name of the user... 00:05:11.356 --> 00:05:12.736 align:middle or their favorite color. 00:05:13.686 --> 00:05:17.146 align:middle Let's make the email truly dynamic by passing in variables. 00:05:17.786 --> 00:05:21.076 align:middle We'll also find out what other information is available 00:05:21.156 --> 00:05:24.206 align:middle for free from inside an email template.