Symfony and MJML. Sending emails like a professional
Basic guide to send emails using the MJML and Symfony language
I think that one of the most tedious tasks that we have to face when we develop web pages is the creation of email templates. Yes, it seems trivial, but if you have had to face it you will know that implementing emails that look good on all email clients is, at the very least, a headache.
In fact, it is the best way to travel through time if you want to see firsthand how the websites were programmed 10 years ago.
However, recently I have encountered a language that greatly simplifies this task and that integrates seamlessly with Symfony and Twig so I decided to prepare this article to talk about it. Welcome to the wonderful world of MJML.
What is MJML?
MJML is a framework that, as announced on its own website, allows us to generate responsive email templates in a very simple way. This provides us with an XML-based format whose labels allow us to create the basic components of an email.
Once this is done, we can use your Javascript library to convert those templates into HTML that you will be ready to send and that will look perfect on any mail client. Yes, even Outlook. 🎉🎉🎉
Basic structure of an email with MJML
The basic structure of an email written about MJML is quite simple. For example, if we want to have an email with the following aspect:

We can write the following code:

Simpler impossible. Although you can delve deeper into each of the labels used in that piece of code in the MJML documentation, we will comment briefly:
- The
mjml
tag is the initial label of any template that we are going to write using this framework. Inside it can contain both themj-head
tag and themj-body
tag (but only those two). - The
mj-head
tag, which I have not used in the previous example, allows us to accommodate both the template styles and the meta tags we want to incorporate. - The
mj-body
tag contains the “magic” of this framework and is where we will design our template. - The
mj-section
tag acts as if it were a row within our email, which will allow us to structure our email. Of course, it has the limitation that we cannot nest sections within sections. - The
mj-column
tag allows us to create columns within the sections that we define, so we can put text to two columns or implement somewhat more complicated designs such as the typical image on the left and text on the right. - The
mj-image
tag allows us to embed responsive images in our emails. - Finally,
mj-text
allows us to incorporate formatted text into templates.
Each of these tags have their own attributes (and some other limitations) described in the documentation, so I advise you to take a look if you want to go deeper into this language.
In addition, there are some “surprises” such as the possibility of including accordions using the mj-accordion tag:


Or carousels using the mj-carousel
tag:


Integrating MJML with Symfony and Twig
Once we have become familiar with MJML, the following will be to integrate it with Symfony and the Twig template system so that we can work with variables within our emails.
It is true that there are a couple of bundles that allow us to perform this process automatically such as:
But I think that in this case it compensates for the manual integration since it is quite simple and we will save ourselves from relying on third-party libraries.
The first thing we will do is install the Javascript mjml library in our project using npm
or yarn
:
yarn add mjml
This library will allow us to compile our templates written using MJML to obtain the final HTML. In our case, we will need to obtain .html.twig
files for later use in our controllers or services when we send the emails.
For example, suppose we want to send the typical welcome email once the user registers on the website. The first thing we will do is create the file welcome.mjml.html.twig
within templates/emails/mjml
:

As you can see, on line 9 I am using twig language to print the name of the user, something we can do without problems (there are some, but we will talk about it later).
Next we will execute the following console command from the root of our project:
mjml templates/emails/mjml/*.mjml.html.twig -o templates/emails
This command basically invokes the Javascript mjml
library with two arguments:
- The first indicates the files to process
- The second is the directory where to place the generated HTML files.
After executing it, we will get the file welcome.html.twig
in the templates/emails
folder. This file will already have all the necessary table structure so that the email looks good on all mail clients and in different resolutions, but, most importantly, it will have preserved the Welcome {{ user.name }}
line. This will allow us to use it to send the welcome email from our controller or service as if it were a “normal” template.
Trick. If you get bored running that command constantly you can write the following shortcut in your package.json file:
"scripts": {"build:email": "mjml templates/emails/mjml/*.mjml.html.twig -o templates/emails"},
so that to compile the templates just execute this from the command line:
yarn build:email
Escape tags within MJML
So far everything great. The only problem you may face is if you want to have a template that includes Twig flow control tags such as {% if %}
or {% for %}
, for example:

In this case, when executing the command to compile the MJML template we will get an error so if we want to enter that kind of logic we will have to escape those instructions using the mj-raw
tag:

With this we will get our template .html.twig
without any problem and send perfect emails and, above all, without having squeezed our heads more than necessary. Thanks MJML!
Final thoughts
First of all I would not like to finish the article without thanking Cristian Gámez for discovering this library. Something is always learned from you!
For the rest I hope that this article has served you and that from now on when you have to program a transactional email it does not involve a great effort to achieve a good result, because as you have seen, the steps to achieve it are very very simple.
Do you want to read more articles like this?
If you liked this article I encourage you to subscribe to the newsletter that I send every Sunday with similar publications to this and more recommended content: 👇👇👇