SuperGeekery: A blog probably of interest only to nerds by John F Morton.

A blog prob­a­bly of inter­est only to nerds by John F Mor­ton.

The HTML email template in Craft CMS

Craft HTML email template option screenshot

The doc­u­men­ta­tion of Craft CMS improves con­stant­ly but for a CMS that evolves at the pace we’re used to with Craft, keep­ing up with doc­u­ment­ing every nook and cran­ny doesn’t always hap­pen. The HTML Email Tem­plate is pret­ty basic and hasn’t received much love in the docs yet. 

Search­ing the Craft doc­u­men­ta­tion doesn’t turn up much infor­ma­tion. If you search the Craft Dis­cord com­mu­ni­ty, you’ll find doc­u­men­ta­tion nuggets scat­tered in con­ver­sa­tions. In this post, I’ll share what I know about using and cus­tomiz­ing the HTML email tem­plate in Craft. As with most of my posts, this is not just for you, but for future-me when I stum­ble upon this task again.

What is the HTML email tem­plate? #

Craft needs to send trans­ac­tion­al emails to users and, by default, these emails are basic. Obvi­ous­ly, they are not designed to match the brand­ing of the site you’re build­ing. You can change this though by pro­vid­ing an HTML Email Tem­plate. You’ll find this option in the Set­tings > Email sec­tion of the Craft con­trol pan­el.

Like all tem­plates in Craft, the HTML email tem­plate is writ­ten in Twig. If you don’t pro­vide a cus­tom tem­plate, Craft CMS comes with a default built-in HTML email tem­plate, which you can see in the Github repos­i­to­ry in templates/_special/email.html’.

Here’s what that tem­plate con­tains.

    <div style="max-width: 500px; font-size: 13px; line-height: 18px; font-family: HelveticaNeue, sans-serif;">
        {{ body }}

As you can see there is a sin­gle vari­able, {{ body }}, passed into the tem­plate. Know­ing that you only need a body vari­able is like­ly enough infor­ma­tion to cus­tomize your emails for your needs. Slap a nice head­er logo on there and you’re set.

Dig­ging deep­er #

What oth­er vari­ables do we have access to besides body? Let’s look into the Craft source code.

Check out this code block from the Mailer.php file. 

$variables = ($message->variables ?: []) + [
    'emailKey' => $message->key,
    'fromEmail' => Craft::parseEnv($settings->fromEmail),
    'replyToEmail' => Craft::parseEnv($settings->replyToEmail),
    'fromName' => Craft::parseEnv($settings->fromName),

Only the emailKey key is avail­able. (Try to use the oth­ers, caused a ren­der­ing error in my tests. See the Debug­ging sec­tion below for some infor­ma­tion on that top­ic.)

If you keep dig­ging into the Craft source you’ll find val­ue you can expect emailKey to con­tain.

Craft has four pre­de­fined email keys: account_​activation, verify_​new_​email, forgot_​password, and test_​email.

In the tem­plate, we can test for those val­ues and ren­der ele­ments based on what we find. Since this is just Twig, you can use oth­er Twig vari­ables, like the date. Plu­g­ins can add addi­tion­al emailKey val­ues for you to test against. You’ll need to read the doc­u­men­ta­tion of the plu­g­ins you’re using that send emails to find out what to expect in those cas­es.

Here’s a valid HTML email sam­ple tem­plate show­ing you how you can use the con­di­tion­als.

    <div>This email was sent on {{ "now"|date("m/d/Y") }}.</div>
    {% switch emailKey %}
      {% case "account_activation" %}
      <p>You're activating your email.</p>
      {% case "verify_new_email" %}
      <p>Let's verify your new email address</p>
      {% case "forgot_password" %}
      <p>Don't worry, we'll reset that password now.</p>
      {% case "test_email" %}
      <p>Testing makes perfect.</p>
      {% default %}
      <p>Unknown type of email. emailKey: {{emailKey}}</p>
    {% endswitch %}
    {{ body }}

Now you can cus­tomize wel­come email head­ers, for­got­ten pass­word head­ers, etc. You could also break this into sep­a­rate Twig files and include sub-tem­­plates based on your con­di­tion­al state­ments.

Using MJML to cre­ate your tem­plate #

HTML for emails is so cranky. I use MJML most of the time to gen­er­ate the HTML I need for email. You don’t need to install any­thing to build a basic tem­plate either, just go to the MJML Try It Live page. For exam­ple, here’s some starter MJML. Click the View HTML” but­ton in the upper-right-hand cor­ner and you’ll get valid HTML to paste into your HTML email tem­plate. 


        <mj-image width="250px" src=""></mj-image>

        <mj-divider border-color="#07d8ff"></mj-divider>

        <mj-text font-size="20px" color="#2c2c2c" font-family="helvetica">{{ body }}</mj-text>

MJML code example
MJML render example

Example MJML

Cus­tomiz­ing the con­tent of the body of your email #

What we’ve cov­ered so far lets you cus­tomize the frame sur­round­ing the body con­tent of the email being sent. Cus­tomiz­ing the body of the email is in a dif­fer­ent spot in the Craft con­trol pan­el. Go to the Util­i­ties > Sys­tem Mes­sage area and you change the text that will be gen­er­at­ed for the var­i­ous mes­sage types.

The default mes­sages start with Hey…” and I like to make that a bit more for­mal for the sites I build.

Craft customize body of email

Debug­ging #

If you’ve set your HTML Email Tem­plate and you’re not see­ing what you expect, you’ve prob­a­bly got an error in your Twig. If the sys­tem encoun­ters an error in your Twig, it will fall back to send­ing a plain text email and will dis­card your tem­plate that is throw­ing the error.

You’ll need to look into your logs to find out what’s going wrong. In your storage/logs direc­to­ry, look for Error ren­der­ing email tem­plate” in the web.log files. Here’s a link to the line in the source code show­ing where I found the text to look for.

In the screen­shot below, you’ll see I had an error in my email tem­plate when I tried to use replyEmail in my Twig code.

Email Rendering Error in Craft logs

Email Rendering Error in Craft logs

Wrap­ping up #

Are you inspired to up your email game in Craft? You can real­ly do quite a lot. For exam­ple, with what we’ve dis­cussed here, if some­one needs to reset their pass­word on a Mon­day, you could make that reset email include a ref­er­ence to how tough Mon­days are for every­one. Wel­come emails could be sea­son­al. If you come up with some­thing cool, let me know on Twit­ter. I’d love to hear about it. Good luck.