mjml: mj-include won't work when mjml file is in subdirectory

mj-include won’t work if .mjml file is in a subdirectory.

Reproduction Steps:

  1. Create a node script for parsing in folder .../ like that:
const fs = require("fs");
const path = require('path');
const mjml = require("mjml");
const mjMail = fs.readFileSync(path.join(__dirname, "emails", "email.mjml"), "utf8");
const htmlMail = mjml.mjml2html(mjMail);
  1. Create file .../emails/email.mjml in folder .../emails/:
<mjml>
  <mj-head> <mj-include path="./emails/common-head" /> </mj-head>
  <mj-body> <mj-container> ... </mj-container> </mj-body>
</mjml>
  1. Create file .../emails/common-head.mjml:
<mj-attributes>...</mj-attributes>
<mj-style>...</mj-style>
  1. Run script from step 1

Expected behavior:

An HTML file will be created with the included common head file

Observed behavior:

The common head is not included and the script prints the error Warning: No handler found for: mj-raw, in mj-head, skipping it

MJML version:

v3.3.5

Changes which resolve the issue:

  • Putting every file in a common folder (may result in confusing)
  • Putting only the root mjml file email.mjml in the same directory as the script and including the mjml files from a subdirectory. (also not ideal)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (10 by maintainers)

Most upvoted comments

This is what worked for med:

File tree:

/mail.js
/templates/hello.mjml
/components/header.mjml
/components/footer.mjml

hello.mjml

<mjml lang="en">
  <mj-body>
    <mj-include path="__dirname/../components/header.mjml" />
    <mj-text>Hello</mj-text>
    <mj-include path="__dirname/../components/footer.mjml" />
  </mj-body>
</mjml>

mail.js

export const sendHello = () => {
  const mjmlTemplate = fs.readFileSync(`${__dirname}/templates/hello.mjml`, 'utf8');
  const { html } = mjml2html(, {
      filePath: path.join(__dirname, 'components'),
  });
  // send email..
}

Waiting for new release

In my use-case, i loaded up the template in a different folder, and this worked:

My file tree:

/emails/global/footer.mjml
/emails/welcome/html.mjml
/utils/mailer.js

My html.mjml: <mj-include path="./../global/footer.mjml" />

My mailer.js to load the template:

var templatePath = path.resolve(__dirname, '../emails/welcome/html.mjml);
var mjmlTemplate = fs.readFileSync(templatePath, 'utf8');
var htmlTemplate = mjml2html.default(mjmlTemplate, {filePath: path.resolve(__dirname, "../emails/global/email.mjml")}).html;

email.mjml does not exists, it just needs a file with an extension in order to work.

Yes, that worked 😃 But it’s not possible (anymore) to leave out the .mjml suffix. I don’t know if this is the intended behavior? 🤔

Same here