nodemailer-mjml is a plug-and-play solution for sending MJML mail using nodemailer. It not only bring a compatibility layer between MJML and nodemailer it also allow to render dynamic content using mustache templating
yarn add nodemailer-mjml
# or using npm install nodemailer-mjml
import { createTransport } from "nodemailer";
import { nodemailerMjmlPlugin } from "nodemailer-mjml";
const transport = createTransport({...});
// Register nodemailer-mjml to your nodemailer transport
transport.use('compile', nodemailerMjmlPlugin({/*Pass desired plugin options here*/}));
using
nodemailer-mjml
with a template is the simplest to start
import { createTransport } from "nodemailer";
import { nodemailerMjmlPlugin } from "../src/index";
import { join } from "path";
const transport = createTransport({
host: "localhost",
port: 25
});
transport.use(
"compile",
nodemailerMjmlPlugin({ templateFolder: join(__dirname, "mailTemplates") })
);
const sendTemplatedEmail = async () => {
await transport.sendMail({
from: '"John doe" <[email protected]>',
to: "[email protected]",
subject: "Welcome",
templateName: "simpleTemplate", // <- Targeted template name
templateData: { // <- Data to be injected in the template
companyLogoURL: "https://www.kadencewp.com/wp-content/uploads/2020/10/alogo-2.png",
heroImageURL: "https://www.kadencewp.com/wp-content/uploads/2020/10/alogo-2.png",
articles: [
{
articleImageURL: "https://api.lorem.space/image/watch?w=150&h=150",
articleName: "Watch 1",
articleDescription: "lorem ipsum dolor sit amet",
},
{
articleImageURL: "https://api.lorem.space/image/watch?w=150&h=150",
articleName: "Watch 2",
articleDescription: "lorem ipsum dolor sit amet"
},
{
articleImageURL: "https://api.lorem.space/image/watch?w=150&h=150",
articleName: "Watch 3",
articleDescription: "lorem ipsum dolor sit amet"
},
]
},
});
};
sendTemplatedEmail();
This complete example can be found in the examples folder
Template layout allow to reuse the same layout for multiple templates
import { createTransport } from "nodemailer";
import { nodemailerMjmlPlugin } from "../src/index";
import { join } from "path";
const transport = createTransport({
host: "localhost",
port: 25
});
transport.use(
"compile",
nodemailerMjmlPlugin({ templateFolder: join(__dirname, "mailTemplates") })
);
const sendTemplatedEmail = async () => {
await transport.sendMail({
from: '"John doe" <[email protected]>',
to: "[email protected]",
subject: "Welcome",
templateLayoutName: "layoutTemplate",
templateLayoutSlots: {
header: "partials/header",
content: "partials/content",
footer: "partials/footer",
},
templateData: {
content: {
imageURL: "http://5vph.mj.am/img/5vph/b/1g8pi/068ys.png"
}
}
});
};
sendTemplatedEmail();
This complete example can be found in the examples folder
Plugin options are defined by the IPluginOptions interface
option | type | description | default |
---|---|---|---|
templateFolder | string | Path of the dir containing your MJML template | undefined |
templatePartialsFolder? | string | Path relative to templateFolder, if defined when using a template layout it will be folder where nodemailer-mjml while try to find fallback slots if one or more is undefined | undefined |
mjmlOptions? | MJMLParsingOptions | Options that would be passed to MJML compiler (see more) mjml doc | {validationLevel: "strict"} |
minifyHtmlOutput? | boolean | use to enable/disable html minification using html-minifier | true |
htmlMinifierOptions? | Options | Options that would be passed to html-minifier (see more) html-minifier doc | undefined |
nodemailer-mjml bring 4 new params to the
sendMail
function
options | type | description | default |
---|---|---|---|
templateName? | string | Name of the file relative to templateFolder (without extension) corresponding to your template | undefined |
templateLayoutName? | string | Name of the file relative to templateFolder (without extension) corresponding to your template layout file | undefined |
templateLayoutSlots? | Object | Object containing path of partial file relative to templateFolder (without extension) that will be injected to the corresponding slot | undefined |
templateData? | Object | Object containing data that would be used by mustache template compiler | undefined |
This plugin, have multiple tests suites (unit, integration) to ensure that everything is working as expected You can run the tests locally by running the following command
# watch mode
docker compose run --rm tests yarn test:watch
#single run
docker compose run --rm tests yarn test
This software uses the following open source packages:
All contributions are welcome 🫡