1
0
mirror of https://github.com/bitwarden/server synced 2026-01-10 04:23:31 +00:00
Files
server/src/Core/MailTemplates/Mjml/README.md
Ike d722314e2d [PM-26551] MJML build script (#6417)
* docs: update readme for MJML
* docs: add readme for MailTemplates directory
* feat: add node build script for cross platform build support
2025-10-10 12:15:29 -04:00

4.9 KiB

MJML email templating

This directory contains MJML templates for emails. MJML is a markup language designed to reduce the pain of coding responsive email templates. Component based development features in MJML improve code quality and reusability.

MJML stands for MailJet Markup Language.

Implementation considerations

These MJML templates are compiled into HTML which will then be further consumed by our Handlebars mail service. We can continue to use this service to assign values from our View Models. This leverages the existing infrastructure. It also means we can continue to use the double brace ({{}}) syntax within MJML since Handlebars can be used to assign values to those {{variables}}.

There is no change on how we interact with our view models.

There is an added step where we compile *.mjml to *.html.hbs. *.html.hbs is the format we use so the handlebars service can apply the variables. This build pipeline process is in progress and may need to be manually done at times.

*.txt.hbs

There is no change to how we create the txt.hbs. MJML does not impact how we create these artifacts.

Building MJML files

npm ci

# Build *.html to ./out directory
npm run build

# To build on changes to *.mjml and *.js files, new files will not be tracked, you will need to run again
npm run build:watch

# Build *.html.hbs to ./out directory
npm run build:hbs

# Build minified *.html.hbs to ./out directory
npm run build:minify

# apply prettier formatting
npm run prettier

Development

MJML supports components and you can create your own components by adding them to .mjmlconfig. Components are simple JavaScript that return MJML markup based on the attributes assigned, see components/mj-bw-hero.js. The markup is not a proper object, but contained in a string.

When using MJML templating you can use the above commands to compile the template and view it in a web browser.

Not all MJML tags have the same attributes, it is highly recommended to review the documentation on the official MJML website to understand the usages of each of the tags.

Mjml email template development

  1. create cool-email.mjml in appropriate team directory
  2. run npm run build:watch
  3. view compiled HTML output in a web browser
  4. iterate -> while build:watch'ing you should be able to refresh the browser page after the mjml/js re-compile to see the changes

Testing with IMailService

After the email is developed from the initial step make sure the email {{variables}} are populated properly by running it through an IMailService implementation.

  1. run npm run build:minify
  2. copy built *.html.hbs files from the build directory to a location the mail service can consume them
  3. run code that will send the email

The minified html.hbs artifacts are deliverables and must be placed into the correct src/Core/MailTemplates/Handlebars/ directories in order to be used by IMailService implementations.

Custom tags

There is currently a mj-bw-hero tag you can use within your *.mjml templates. This is a good example of how to create a component that takes in attribute values allowing us to be more DRY in our development of emails. Since the attribute's input is a string we are able to define whatever we need into the component, in this case mj-bw-hero.

In order to view the custom component you have written you will need to include it in the .mjmlconfig and reference it in an mjml template file.

<!-- Custom component implementation-->
<mj-bw-hero
  img-src="https://assets.bitwarden.com/email/v1/business.png"
  title="Verify your email to access this Bitwarden Send"
/>

Attributes in Custom Components are defined by the developer. They can be required or optional depending on implementation. See the official MJML documentation for more information.

static allowedAttributes = {
  "img-src": "string", // REQUIRED: Source for the image displayed in the right-hand side of the blue header area
  title: "string", // REQUIRED: large text stating primary purpose of the email
  "button-text": "string", // OPTIONAL: text to display in the button
  "button-url": "string", // OPTIONAL: URL to navigate to when the button is clicked
  "sub-title": "string", // OPTIONAL: smaller text providing additional context for the title
};

static defaultAttributes = {};

Custom components, such as mj-bw-hero, must be defined in the .mjmlconfig in order for them to be compiled and rendered properly in the templates.

{
  "packages": ["components/mj-bw-hero"]
}

mj-include

You are also able to reference other more static MJML templates in your MJML file simply by referencing the file within the MJML template.

<!-- Example of reference to mjml template -->
<mj-wrapper padding="5px 20px 10px 20px">
  <mj-include path="../../components/learn-more-footer.mjml" />
</mj-wrapper>