Skip to content

Commit

Permalink
Added preview-email, More documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
niftylettuce committed Sep 24, 2017
1 parent 4976c72 commit e6ca0cd
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 293 deletions.
199 changes: 188 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@
[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org)
[![license](https://img.shields.io/github/license/niftylettuce/email-templates.svg)](LICENSE)

> Create, preview, and send custom email templates for [Node.js][node]. Highly configurable and supports automatic inline CSS, stylesheets, embedded images and fonts, and much more!
> Create, [preview][preview-email], and send custom email templates for [Node.js][node]. Highly configurable and supports automatic inline CSS, stylesheets, embedded images and fonts, and much more! Made for sending beautiful emails with [Lad][].
>
> **NEW**: v3.0.0 is released! See the [2.x branch][2-x-branch] documentation if you're using an older version

## Table of Contents

* [Install](#install)
* [Preview](#preview)
* [Usage](#usage)
* [Basic](#basic)
* [Cache Pug Templates](#cache-pug-templates)
* [Localization](#localization)
* [Custom Text Template](#custom-text-template)
* [Custom Template Engine (e.g. EJS)](#custom-template-engine-eg-ejs)
* [Custom Default Message Options](#custom-default-message-options)
* [Custom Rendering (e.g. from a MongoDB database)](#custom-rendering-eg-from-a-mongodb-database)
* [Options](#options)
* [Plugins](#plugins)
* [Custom Rendering (e.g. from a MongoDB database)](#custom-rendering-eg-from-a-mongodb-database)
* [Tip](#tip)
* [Contributors](#contributors)
* [License](#license)
Expand All @@ -43,6 +48,15 @@ yarn add email-templates pug
```


## Preview

We've added [preview-email][] by default to this package!

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.

<a target="_blank" href="https://github.com/niftylettuce/preview-email/blob/master/demo.png">View the demo</a>


## Usage

### Basic
Expand Down Expand Up @@ -98,6 +112,62 @@ p Welcome to Mars, the red planet.
= `Hi ${name}, welcome to Mars`
```

### Cache Pug Templates

We strongly suggest to follow this example and pre-cache your templates with [cache-pug-templates][] (if you're using the default [Pug][] template engine).

If you do not do this, then your Pug templates will re-compile and re-cache every time you deploy new code and restart your app.

1. Ensure you have [Redis][] (v4.x+) installed:

* Mac: `brew install redis && brew services start redis`
* Ubuntu:

```sh
sudo add-apt-repository -y ppa:chris-lea/redis-server
sudo apt-get update
sudo apt-get -y install redis-server
```

2. Install the packages:

[npm][]:

```sh
npm install cache-pug-templates redis
```

[yarn][]:

```sh
yarn add cache-pug-templates redis
```

3. Configure it to read and cache your entire email templates directory:

```js
const path = require('path');
const cachePugTemplates = require('cache-pug-templates');
const redis = require('redis');
const Email = require('email-templates');
const redisClient = redis.createClient();
const email = new Email({
message: {
from: '[email protected]'
},
transport: {
jsonTransport: true
}
});
cachePugTemplates(redisClient, email.config.views.root);
// ...
```

4. For more configuration options see [cache-pug-templates][].

### 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).
Expand Down Expand Up @@ -148,25 +218,107 @@ p: :translate(locale) Hi #{name}
p: :translate(locale) Welcome to Mars, the red planet.
```

### Custom Text Template

## Options
> By default we use `html-to-text` to generate a plaintext version and attach it as `message.text`.

For a list of all available options and defaults [view the configuration object](index.js).
If you'd like to customize the text body, you can pass `message.text` or set `config.htmlToText: false` (doing so will automatically lookup a `text` template file just like it normally would for `html` and `subject`).
```js
const Email = require('email-templates');
## Plugins
const email = new Email({
message: {
from: '[email protected]'
},
transport: {
jsonTransport: true
},
htmlToText: false // <----- HERE
});
You can use any [nodemailer][] plugin. Simply pass an existing transport instance as `config.transport`.
email.send({
template: 'mars',
message: {
to: '[email protected]'
},
locals: {
name: 'Elon'
}
}).then(console.log).catch(console.error);
```
By default we include [nodemailer-base64-to-s3][] which you can enable via `options.base64ToS3`.
> `text.pug`:
We highly recommend to add to your default `config.locals` the following:
```pug
| Hi #{name},
| Welcome to Mars, the red planet.
```
* [custom-fonts-in-emails][] - render any font in emails as an image w/retina support (no more Photoshop or Sketch exports!)
* [font-awesome-assets][] - render any [Font Awesome][fa] icon as an image in an email w/retina support (no more Photoshop or Sketch exports!)
### Custom Template Engine (e.g. EJS)
1. Install your desired template engine (e.g. [EJS][])
[npm][]:
```sh
npm install ejs
```
[yarn][]:
```sh
yarn add ejs
```
2. Set the extension in options and send an email
```js
const Email = require('email-templates');
const email = new Email({
message: {
from: '[email protected]'
},
transport: {
jsonTransport: true
},
views: {
options: {
extension: 'ejs' // <---- HERE
}
}
});
```
### Custom Default Message Options
You can configure your Email instance to have default message options, such as a default "From", an unsubscribe header, etc.
For a list of all available message options and fields see [the Nodemailer mesage reference](https://nodemailer.com/message/).
> Here's an example showing how to set a default custom header and a list unsubscribe header:

```js
const Email = require('email-templates');
const email = new Email({
message: {
from: '[email protected]',
headers: {
'X-Some-Custom-Thing': 'Some-Value'
},
list: {
unsubscribe: 'https://niftylettuce.com/unsubscribe'
}
},
transport: {
jsonTransport: true
}
});
```

## Custom Rendering (e.g. from a MongoDB database)
### Custom Rendering (e.g. from a MongoDB database)

You can pass a custom `config.render` function which accepts two arguments `view` and `locals` and must return a `Promise`.

Expand All @@ -192,6 +344,23 @@ const email = new Email({
```


## Options

For a list of all available options and defaults [view the configuration object](index.js).


## Plugins

You can use any [nodemailer][] plugin. Simply pass an existing transport instance as `config.transport`.

You should add the [nodemailer-base64-to-s3][] plugin to convert base64 inline images to actual images stored on Amazon S3 and Cloudfront.

We also highly recommend to add to your default `config.locals` the following:

* [custom-fonts-in-emails][] - render any font in emails as an image w/retina support (no more Photoshop or Sketch exports!)
* [font-awesome-assets][] - render any [Font Awesome][fa] icon as an image in an email w/retina support (no more Photoshop or Sketch exports!)


## Tip

Instead of having to configure this for yourself, you could just use [Lad][] instead.
Expand Down Expand Up @@ -240,3 +409,11 @@ Instead of having to configure this for yourself, you could just use [Lad][] ins
[nodemailer-transport]: https://nodemailer.com/transports/

[postmark]: https://postmarkapp.com/

[ejs]: http://ejs.co/

[cache-pug-templates]: https://github.com/ladjs/cache-pug-templates

[redis]: https://redis.io/

[preview-email]: https://github.com/niftylettuce/preview-email
37 changes: 6 additions & 31 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
const os = require('os');
const path = require('path');
const debug = require('debug')('email-templates');
const fs = require('fs-extra');
const uuid = require('uuid');
const htmlToText = require('html-to-text');
const opn = require('opn');
const I18N = require('@ladjs/i18n');
const autoBind = require('auto-bind');
const nodemailer = require('nodemailer');
const base64ToS3 = require('nodemailer-base64-to-s3');
const consolidate = require('consolidate');
const isFunction = require('lodash.isfunction');
const isObject = require('lodash.isobject');
const isEmpty = require('lodash.isempty');
const isString = require('lodash.isstring');
const defaultsDeep = require('lodash.defaultsdeep');
const merge = require('lodash.merge');
const previewEmail = require('preview-email');

const getPaths = require('get-paths');
const juiceResources = require('juice-resources-promise');

// TODO: recommend lad in email-templates
// TODO: update lad readme to show it uses email-templates v3
// TODO: redis caching
// TODO: upgrade web-resource-inliner once <https://github.com/jrit/web-resource-inliner/pull/31> is released

class Email {
constructor(config = {}) {
debug('config passed %O', config);
Expand All @@ -48,7 +40,7 @@ class Email {
// <https://nodemailer.com/message/>
message: {},
send: !['development', 'test'].includes(process.env.NODE_ENV),
open: process.env.NODE_ENV === 'development',
preview: process.env.NODE_ENV === 'development',
// <https://github.com/ladjs/i18n>
// set to an object to configure and enable it
i18n: false,
Expand All @@ -69,9 +61,7 @@ class Email {
// pass a transport configuration object or a transport instance
// (e.g. an instance is created via `nodemailer.createTransport`)
// <https://nodemailer.com/transports/>
transport: {},
// <https://github.com/ladjs/nodemailer-base64-to-s3
base64ToS3: {}
transport: {}
},
config
);
Expand All @@ -84,9 +74,6 @@ class Email {
if (!isFunction(this.config.transport.sendMail))
this.config.transport = nodemailer.createTransport(this.config.transport);

if (isObject(this.config.base64ToS3) && !isEmpty(this.config.base64ToS3))
this.config.transport.use('compile', base64ToS3(this.config.base64ToS3));

debug('transformed config %O', this.config);

autoBind(this);
Expand Down Expand Up @@ -192,21 +179,9 @@ class Email {
this.config.juiceResources
);

// TODO: rewrite this so we have a npm package doing this
// <https://github.com/ryanb/letter_opener/blob/master/lib/letter_opener/templates/default.html.erb>
// <https://github.com/jugglinmike/srcdoc-polyfill>
// <https://github.com/davidcornu/mail-preview>
if (this.config.open && message.html) {
debug('opening in browser');
const id = uuid.v4();
const tmpHtmlPath = `${os.tmpdir()}/${id}.html`;
await fs.writeFile(tmpHtmlPath, message.html);
await opn(tmpHtmlPath, { wait: false });
if (message.text) {
const tmpTxtPath = `${os.tmpdir()}/${id}.txt`;
await fs.writeFile(tmpTxtPath, message.text);
await opn(tmpTxtPath, { wait: false });
}
if (this.config.preview) {
debug('using `preview-email` to preview email');
await previewEmail(message);
}

if (!this.config.send) {
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "email-templates",
"description":
"Create, preview, and send custom email templates for Node.js. Highly configurable and supports automatic inline CSS, stylesheets, embedded images and fonts, and much more!",
"Create, preview, and send custom email templates for Node.js. Highly configurable and supports automatic inline CSS, stylesheets, embedded images and fonts, and much more! Made for sending beautiful emails with Lad.",
"version": "3.0.2",
"author": "Nick Baugh <[email protected]> (http://niftylettuce.com)",
"bugs": {
Expand Down Expand Up @@ -29,9 +29,7 @@
"lodash.isstring": "^4.0.1",
"lodash.merge": "^4.6.0",
"nodemailer": "^4.1.0",
"nodemailer-base64-to-s3": "^0.0.3",
"opn": "^5.1.0",
"uuid": "^3.1.0"
"preview-email": "^0.0.2"
},
"devDependencies": {
"ava": "^0.22.0",
Expand Down
Loading

0 comments on commit e6ca0cd

Please sign in to comment.