Creating emails with the Maily API — A how to (part 1)
These blogpost will be different from my previous ones, as I will show you how to setup a beautiful maily environment on which you can develop you HTML and text emails, using React and MJML. In this how-to I will guide you through all the required steps.
At the end of all how tos, you will have:
- Componentized emails, so you can easily reuse code
- Fluid layouts, so things render well from phone to iMac
- An email API service which generates HTML and text emails based on input JSON
- Open tracking in your HTML email
- Translated emails for every user
- A command to easily generate all emails for you to check designs
- A Docker image to move it to production easily
For this how-to I’ll assume your are familiar with Node.js (version 6+) and npm. If not, please familiarize yourself with these concepts first. Apart from that, we will use mjml itself, so you should be familiar what the different tags do (or willing to look it up in the mean time). It might be our emails are not technically valid mjml (componentization is a bit hard), but they will render correctly.
A repository for this blog is available on Github.
This code will depend on having a Node.js 6+ version, so ensure you are using at least Node.js 6!
Once done, you will have an internationalized email which renders perfectly on any device and client, and is generated by your very own API service. Additionally, it might be the first time you are having fun building HTML emails!
Getting started
First we will setup our development environment, consisting of a few folders. The structure will look like this
<your project folder>
└── components
| └── html
| └── text
└── test-results
└── json
We have a dedicated folder for HTML and text components. In general these might look alike a lot, but they have significant differences as well. Since a wrong abstraction is worse than code duplication, we will simply have some duplicate code. We might figure out a great abstraction later on!
Additionally we create a folder for our tests results (our final HTML, mjml, and text emails). Since we need input for those emails, we create an additional json
folder as well.
Installing our dependencies
Node.js being Node.js, we definitely need some additional packages. Lets start of with the easy ones: react
and maily
.
npm init && npm install --save react@15.4.1 maily@3.1.1
In order to make our build chain slightly more efficient, we will also setup some babel stuff.
npm install --save babel-preset-es2015 babel-preset-react && npm install --save-dev babel-cli
Next we will ensure that babel properly loads these, so we add a .babelrc
file with the following contents.
{
"presets": ["es2015","react"]
}
Now we are ready to build!
Creating our first component
For this email, assume that our designers have given us the following MJML code to work with (including some placeholder values).
When our devvy eyes look at this email, we notice some redundancies which will appear in other emails as well. So we can break this email down in different sections, which is exactly what I’ve done below
So lets start out with our header, since that component seems relatively easy.
In order to make our React code as simple as possible, we will be wrapping some of mjmls components with our own, so we can supply our own default values easily. For that, we start with the divider in the header.
Before we do that, we create a style.js
file in the components
folder. Here we will put some basic style later on so we can reference them. For now its enough to fill it with the following content
module.exports = {
colors: {
},
distance: {
},
fontSize: {
},
width: {
},
fonts: {
}
};
OK, now it is really time for our first component! Create divider.js
in components/html
with the following basic structure.
As you can see, we have made it possible to set the color of the divider using a React prop. The paddings on the left and right are taken from the style.js
file.
So let’s update that file to resemble the proper values
module.exports = {
colors: {
green: '#8BC43F'
},
distance: {
small: 8,
},
fontSize: {
},
width: {
},
fonts: {
}
};
There it is, our first component! But to be honest, it is not that exciting yet. But that will come (trust me!).
Now we can continue building the header :)
OMG, now we have a completely cutomizable header (with a logo you can click), properly wrapped in the mjml syntax.
We can just put <Header />
anywhere to apply it to an email. We are getting somewhere!
The footer component
In the footer we notice that the mj-section
and mj-column
are repeated quite a lot in order to become full width. So we make that a component as well. Technically it’s not required, but I have to maintain this later: readable code is a plus.
Next up is the contact section (I’m leaving out the social section, you can add it yourself while practising). Since we will probably be rendering a lot of text in our emails as well, I made a convenience component for that as well.
Writing the envelope
mjml requires some basic stuff to be available, and we want our headers and footers in there anyway. So we create an envelope.js
file.
By now we have written all boiler plate which we can forever reuse in our emails. Give yourself a drink, you have come far by now!
Time to create the actual content
Remember the actual content at the top? That one is now quite easy to implement.
Wiring it all up
Now we will add the final index.js
file for HTML generation, and create the service index.js
. We will also create a nice generation scripts so you can see everything easily. See for details this Github commit :)
Where do we stand
Now we have an REST API which emits email compatible HTML by using mjml. You can clone the repo, run npm install
and babel-node test.js
and open the test-results/invoice.html
in your browser :)
Next up: adding text components, and localizing everything! Be ready for those follow ups in a few days.
Edit: See part two!