MCPcopy
hub / github.com/forwardemail/email-templates

github.com/forwardemail/email-templates @v13.0.1 sqlite

repository ↗ · DeepWiki ↗ · release v13.0.1 ↗
13 symbols 27 edges 9 files 0 documented · 0%
README

Email Templates

build status code style styled with prettier made with lass license

Create, [preview][preview-email] (browser/iOS Simulator), and send custom email templates for [Node.js][node]. Made for [Forward Email][forward-email] and [Lad][].

Need to send emails that land in the inbox instead of spam folder? Click here to learn how to send JavaScript contact forms and more with Node.js

Table of Contents

Install

By default we recommend [pug][] for your template engine, but you can use [any template engine][supported-engines]. Note that [preview-email][] is an optional dependency and is extremely helpful for rendering development previews of your emails automatically in your browser.

[npm][]:

npm install email-templates preview-email pug

Preview

We've added [preview-email][] by default to this package. This package allows you to preview emails in the browser and in the iOS Simulator.

This means that (by default) in the development environment (e.g. NODE_ENV=development) your emails will be rendered to the tmp directory for you and automatically opened in the browser.

If you have trouble previewing emails in your browser, you can configure a preview option which gets passed along to [open's options][open-options] (e.g. preview: { open: { app: 'firefox' } }).

See the example below for Open Email Previews in Firefox.

Usage

Debugging

Environment Flag

If you run into any issues with configuration, files, templates, locals, etc, then you can use the NODE_DEBUG environment flag:

NODE_DEBUG=email-templates node app.js

This will output to the console all debug statements in our codebase for this package.

Inspect Message

As of v3.6.1 you can now inspect the message passed to nodemailer.sendMail internally.

In the response object from email.send, you have access to res.originalMessage:

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com'
    },
    locals: {
      name: 'Elon'
    }
  })
  .then(res => {
    console.log('res.originalMessage', res.originalMessage)
  })
  .catch(console.error);

Basic

You can swap the transport option with a [Nodemailer transport][nodemailer-transport] configuration object or transport instance. We highly recommend using [Forward Email][forward-email] for your transport (it's the default in [Lad][]).

If you want to send emails in development or test environments, set options.send to true.

const Email = require('email-templates');

const email = new Email({
  message: {
    from: 'test@example.com'
  },
  // uncomment below to send emails in development/test env:
  // send: true
  transport: {
    jsonTransport: true
  }
});

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com'
    },
    locals: {
      name: 'Elon'
    }
  })
  .then(console.log)
  .catch(console.error);

The example above assumes you have the following directory structure:

.
├── app.js
└── emails
    └── mars
        ├── html.pug
        └── subject.pug

And the contents of the pug files are:

html.pug:

p Hi #{name},
p Welcome to Mars, the red planet.

subject.pug:

= `Hi ${name}, welcome to Mars`

Attachments

Please reference [Nodemailer's attachment documentation][attachments] for further reference.

If you want to set default attachments sent with every email:

const Email = require('email-templates');

const email = new Email({
  message: {
    from: 'test@example.com',
    attachments: [
      {
        filename: 'text1.txt',
        content: 'hello world!'
      }
    ]
  }
});

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com'
    },
    locals: {
      name: 'Elon'
    }
  })
  .then(console.log)
  .catch(console.error);

If you want to set attachments sent individually:

const Email = require('email-templates');

const email = new Email({
  message: {
    from: 'test@example.com'
  },
  transport: {
    jsonTransport: true
  }
});

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com',
      attachments: [
        {
          filename: 'text1.txt',
          content: 'hello world!'
        }
      ]
    },
    locals: {
      name: 'Elon'
    }
  })
  .then(console.log)
  .catch(console.error);

Automatic Inline CSS via Stylesheets

Simply include the path or URL to the stylesheet in your template's <head>:

link(rel="stylesheet", href="https://github.com/forwardemail/email-templates/raw/v13.0.1/css/app.css", data-inline)

This will look for the file /css/app.css in the build/ folder. Also see Optimized Pug Stylesheet Loading below.

If this asset is in another folder, then you will need to modify the default options when creating an Email instance:

const email = new Email({
  // <https://github.com/Automattic/juice>
  juice: true,
  // Override juice global settings <https://github.com/Automattic/juice#juicecodeblocks>
  juiceSettings: {
    tableElements: ['TABLE']
  },
  juiceResources: {
    // set this to `true` (since as of v11 it is `false` by default)
    applyStyleTags: true, // <------------ you need to set this to `true`
    webResources: {
      //
      // this is the relative directory to your CSS/image assets
      // and its default path is `build/`:
      //
      // e.g. if you have the following in the `<head`> of your template:
      // `<link rel="stylesheet" href="https://github.com/forwardemail/email-templates/raw/v13.0.1/style.css" data-inline="data-inline">`
      // then this assumes that the file `build/style.css` exists
      //
      relativeTo: path.resolve('build')
      //
      // but you might want to change it to something like:
      // relativeTo: path.join(__dirname, '..', 'assets')
      // (so that you can re-use CSS/images that are used in your web-app)
      //
    }
  }
});

Render HTML and/or Text

If you don't need this module to send your email, you can still use it to render HTML and/or text templates.

Simply use the email.render(view, locals) method we expose (it's the same method that email.send uses internally).

If you need to render a specific email template file (e.g. the HTML version):

const Email = require('email-templates');

const email = new Email();

email
  .render('mars/html', {
    name: 'Elon'
  })
  .then(console.log)
  .catch(console.error);

The example above assumes you have the following directory structure (note that this example would only render the html.pug file):

.
├── app.js
└── emails
    └── mars
        ├── html.pug
        ├── text.pug
        └── subject.pug

The Promise for email.render resolves with a String (the HTML or text rendered).

If you need pass juiceResources in render function, with this option you don't need create Email instance every time

const Email = require('email-templates');

const email = new Email();

email
  .render({
    path: 'mars/html',
    juiceResources: {
      webResources: {
        // view folder path, it will get css from `mars/style.css`
        relativeTo: path.resolve('mars')
      }
    }
  }, {
    name: 'Elon'
  })
  .then(console.log)
  .catch(console.error);

The example above will be useful when you have a structure like this, this will be useful when you have a separate CSS file for every template

.
├── app.js
└── emails
    └── mars
        ├── html.pug
        ├── text.pug
        ├── subject.pug
        └── style.css

The Promise for email.render resolves with a String (the HTML or text rendered).

If you need to render all available template files for a given email template (e.g. html.pug, text.pug, and subject.pug – you can use email.renderAll (this is the method that email.send uses).

const Email = require('email-templates');

const email = new Email();

email
  .renderAll('mars', {
    name: 'Elon'
  })
  .then(console.log)
  .catch(console.error);

If you need to render multiple, specific templates at once (but not all email templates available), then you can use Promise.all in combination with email.render:

const Email = require('email-templates');

const email = new Email();
const locals = { name: 'Elon' };

Promise
  .all([
    email.render('mars/html', locals),
    email.render('mars/text', locals)
  ])
  .then(([ html, text ]) => {
    console.log('html', html);
    console.log('text', text);
  })
  .catch(console.error);

Localization

All you need to do is simply pass an [i18n][] configuration object as config.i18n (or an empty one as this example shows to use defaults).

Don't want to handle localization and translation yourself? Just use [Lad][lad] – it's built in and uses [mandarin][] (with automatic Google Translate support) under the hood.

const Email = require('email-templates');

const email = new Email({
  message: {
    from: 'test@example.com'
  },
  transport: {
    jsonTransport: true
  },
  i18n: {} // <------ HERE
});

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com'
    },
    locals: {
      locale: 'en', // <------ CUSTOMIZE LOCALE HERE (defaults to `i18n.defaultLocale` - `en`)
      // is your user french?
      // locale: 'fr',
      name: 'Elon'
    }
  })
  .then(console.log)
  .catch(console.error);

Then slightly modify your templates to use localization functions.

html.pug:

p= `${t('Hi')} ${name},`
p= t('Welcome to Mars, the red planet.')

subject.pug:

p= `${t('Hi')} ${name}, ${t('welcome to Mars')}`

Note that if you use [Lad][], you have a built-in filter called translate:

p: :translate(locale) Welcome to Mars, the red planet.

Localization using Handlebars template engine

If you are using handlebars and you are using localization files with named values, you will quickly see that there is no way to properly call the t function in your template and specify named values.

If, for example you have this in your translation file:

{
  "greetings": "Hi {{ firstname }}",
  "welcome_message": "Welcome to Mars, the red planet."
}

And you would like to use it in your template like this:

html.hbs:



{{ t "greetings" firstname="Marcus" }}




{{ t "welcome_message" }}


This would not work because the second argument sent by handlebars to the function would be a handlebar helper options object instead of just the named values.

A possible workaround you can use is to introduce your own translation helper in your template locals:

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com'
    },
    locals: {
      locale: 'en', // <------ CUSTOMIZE LOCALE HERE (defaults to `i18n.defaultLocale` - `en`)
      // is your user french?
      // locale: 'fr',
      name: 'Elon',
      $t(key, options) {
        // <------ THIS IS OUR OWN TRANSLATION HELPER
        return options.data.root.t(
          { phrase: key, locale: options.data.root.locale },
          options.hash
        );
      }
    }
  })
  .then(console.log)
  .catch(console.error);

Then slightly modify your templates to use your own translation helper functions.

html.hbs:



{{ $t "greetings" firstname="Marcus" }}




{{ $t "welcome_message" }}


Text-Only Email (no HTML)

If you wish to have only a text-based version of your email you can simply pass the option textOnly: true.

Regardless if you use the htmlToText option or not (see next example), it will still render only a text-based version.

```js const Email = require('email-templates');

const email = new Email({ message: { from: 'test@example.com' }, transport: { jsonTransport: true }, textOnly: true // <----- HERE });

email .send({ template: 'mars', message: { to: 'elon@spacex.com' }, locals: {

Core symbols most depended-on inside this repo

send
called by 21
index.js
render
called by 7
index.js
juiceResources
called by 3
index.js
getTemplatePath
called by 2
index.js
juiceResources
called by 1
index.js
getPath
called by 1
index.js
templateExists
called by 1
index.js
checkAndRender
called by 1
index.js

Shape

Method 9
Class 2
Function 2

Languages

TypeScript100%

Modules by API surface

index.js12 symbols
test/test.js1 symbols

Used by 1 indexed graphs manifest dependencies, hub-wide

Dependencies from manifests, versioned

@commitlint/cli19.3.0 · 1×
@commitlint/config-conventional19.2.2 · 1×
@ladjs/consolidate1.0.4 · 1×
@ladjs/i18n10.0.0 · 1×
ava5.3.0 · 1×
cheerio1.0.0-rc.12 · 1×
cross-env7.0.3 · 1×
ejs3.1.10 · 1×
eslint8.42.0 · 1×
eslint-config-xo-lass2.0.1 · 1×
fixpack4.0.0 · 1×
get-paths0.0.7 · 1×

For agents

$ claude mcp add email-templates \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact