Building MJML email templates with Gulp

This is the second post in the series about building email templates with MJML and deploying them on AWS. In the previous post, we learned about MJML and Handlebars.js for creating cross-browser email templates with dynamic content. In this post, I will show you how you can script the building process of MJML emails and prepare them for upload on AWS.

Building MJML email templates with Gulp

Let's do a quick recap. In the previous post, I created a simple mail template in MJML:

<mjml>
  <mj-body>
    <mj-text>Hello {{firstname}}</mj-text>
    <mj-text>Here are some movie recommendations for you:</mj-text>
    <mj-text>
      <ul>
        {{#each movies}}
        <li>{{this}}</li>
        {{/each}}
      </ul>
    </mj-text>
  </mj-body>
</mjml>

When running through the online MJML editor, we get an HTML output that should look decent in most browsers. This has been a manual process so far, so let's automate it to limit the amount of work we need to do when needing changes. I'll use Gulp for this example, but there's an MJML CLI that you can use if you prefer another scripting language. Start by creating a new npm project and install the necessary npm packages:

npm init
npm install gulp
npm install gulp-json-editor
npm install gulp-mjml
npm install html-minifier
npm install mjml

During the npm init command just accept the defaults or input values if you prefer something else. The next step is to produce HTML from the MJML file. When uploaded as an AWS template we need to produce the following template.json file:

{
  "Template": {
    "TemplateName": "test",
    "SubjectPart": "The subject",
    "HtmlPart": ""
  }
}

The HTML output from the MJML processor will need to go into the HtmlPart property in the JSON file. The Gulp script needs to:

  1. Convert MJML to HTML.
  2. Minify the HTML.
  3. Insert the minified HTML in template.json.

Here's a script that will do all steps:

const gulp = require('gulp');
const mjml = require('gulp-mjml');
const mjmlEngine = require('mjml');
const htmlMinify = require('html-minifier');
const jsonEditor = require('gulp-json-editor');

let htmlContents = null;

gulp.task('mjml-to-html', function () {
    return gulp.src('./test.mjml')
        .pipe(mjml(mjmlEngine))
        .on('data', function(file) {
            const buferFile = Buffer.from(htmlMinify.minify(file.contents.toString(), {
                collapseWhitespace: true,
                minifyCSS: true,
                processConditionalComments: true
            }));
            htmlContents = '"' + buferFile.toString() + '"';
            return file.contents = buferFile;
        })
        .pipe(gulp.dest('./html'))
});

gulp.task('update-json', function () {
    return gulp.src('./template.json')
        .pipe(jsonEditor(function(json) {
            json.Template.HtmlPart = htmlContents;
            return json;
        }))
        .pipe(gulp.dest('./'))
});

gulp.task('run', gulp.series('mjml-to-html', 'update-json'));

The Gulp script has three tasks. The mjml-to-html task will run the MJML processor and output minified HTML to a folder named html. Outputting the HTML to a file only acts as additional debug information and can be removed if you prefer. The update-json task will take the in-memory minified HTML and insert it into the template.json file. Finally, the run task will run both tasks in the right order.

Run the script using Gulp:

gulp run

You should see that the template.json file now contains a minified HTML email template:

{
  "Template": {
    "TemplateName": "test",
    "SubjectPart": "The subject",
    "HtmlPart": "\"<!doctype html><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><head><title></title><!--[if !mso]><!--><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><!--<![endif]--><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style type=\"text/css\">#outlook a{padding:0}body{margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}table,td{border-collapse:collapse;mso-table-lspace:0;mso-table-rspace:0}img{border:0;height:auto;line-height:100%;outline:0;text-decoration:none;-ms-interpolation-mode:bicubic}p{display:block;margin:13px 0}</style><!--[if mso]><noscript><xml><o:officedocumentsettings><o:allowpng><o:pixelsperinch>96</o:pixelsperinch></o:officedocumentsettings></xml></noscript><![endif]--><!--[if lte mso 11]><style type=\"text/css\">.mj-outlook-group-fix{width:100%!important}</style><![endif]--><!--[if !mso]><!--><link href=\"https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700\" rel=\"stylesheet\" type=\"text/css\"><style type=\"text/css\">@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);</style><!--<![endif]--><style type=\"text/css\"></style><style type=\"text/css\"></style></head><body style=\"word-spacing:normal\"><div style=\"\"><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\">Hello {{firstname}}</div><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\">Here are some movie recommendations for you:</div><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\"><ul>{{#each movie}}<li>{{this}}</li>{{/each}}</ul></div></div></body></html>\""
  }
}

The JSON file is ready for upload in AWS. In the next post, I'll finish the series. There we will automatically build the MJML template using the script from this post, and upload it on AWS.

elmah.io: Error logging and Uptime Monitoring for your web apps

This blog post is brought to you by elmah.io. elmah.io is error logging, uptime monitoring, deployment tracking, and service heartbeats for your .NET and JavaScript applications. Stop relying on your users to notify you when something is wrong or dig through hundreds of megabytes of log files spread across servers. With elmah.io, we store all of your log messages, notify you through popular channels like email, Slack, and Microsoft Teams, and help you fix errors fast.

See how we can help you monitor your website for crashes Monitor your website