node-ed-mailer
A node.js event driven service to send emails. The Mailer instance will consume messages from the configured AMQP queue,
and for each message it sends the corresponding email using the registered mail template.
Overview
+-----------------+
| |
| events producer |
| |
+-------+---------+
|
|
|
+----------------v------------------+ +------------------+
| | | | 1. consume event
| AMQP events queue (a.e. RabbitMQ) +---------------> node-ed-mailer | 2. compile template
| | | | 3. send email
+-----------------------------------+ +--------+---------+
|
|
+--v---+
| SMTP |
+------+
Installation
Using npm:
$ npm install --save node-edmailer
using Yarn:
$ yarn add node-ed-mailer
Usage
'use strict';
const build = require('node-mu');
const Mailer = require('../../lib');
const start = async () => {
try {
const mailerService = build(Mailer);
mailerService.templatesConfig = require('./templates-config');
await mailerService.run();
} catch (err) {
throw err;
}
};
start()
.then(() => {
console.log(`\uD83D\uDE80 node-\u03BC service started [pid: ${process.pid}]... bring me some \uD83C\uDF7A \uD83C\uDF7A \uD83C\uDF7A`);
}).catch(err => {
console.error(`\uD83D\uDD25 service crashed at startup: ${err}`);
process.exit(1);
});
configuration
########################################################################
# Service configuration.
#
# This configuration will be overridden by the NODE_ENV profile you use,
# for example development.yml for development profile or production.yml
# for production a so on.
#
########################################################################
service:
group: Examples
name: SimpleMailer
version:
major: 0
minor: 0
status: 0 # 0: alpha, 1: beta, 2: release, 3: final
amqp:
url: amqp://<USER>:<PWD>@localhost:5672/zzzzxxxxyyyyyooooo
queue:
name: <QUEUE_NAME>
management:
endpoint:
port: 5201
baseRoutingPath: /mgmt
health:
path: /health
full: [true|false]
smtp:
host: <STMP.HOST>
port: <SMTP.PORT>
secure: [true|false]
reject:
unauthorized: [true|false]
auth:
user: <USER>
password: <PWD>
nodemailer:
logger: [true|false]
debug: [true|false]
mailDefault:
from: <FROMADDRESS>
replyTo: <NOREPLY>
log:
path: ./logs
console: [true|false]
level: debug
json: [true|false]
requests:
console: [true|false]
errors:
console: [true|false]
# should match your Git repo version
info:
version: 0.0.2
You can use node-ed-mailer as module in your app or as a standalone service. The option mailTemplates is a configuration object and could be in the same .js file or in a separate module (like here in the sample).
Events and email templates
Events, as AMQP message, must have the following fields and format:
{
type: <your-application-custom-event-type>,
spec: <your-custom-event-specification>,
producer: <name-or-id-or-whatever-to-recognize-the-producer>,
timestamp: <timestamp-of-the-publication-into-the-queue>,
mailto: <the-address-to-send-email-to>
payload: {
....
....
....
}
The event payload will be filled with the event data. Here you set, at least,the fields to be used in the email template. This fields will be used during the Handlebars compilation of the template.
event example
{
type: "NewUser",
spec: "NormalUser",
producer: "user-service",
timestamp: "2018-05-10T07:35:04.806Z",
mailto: "frank.zappa@this-is-an-example.com"
payload: {
id: 1833,
username: "frank.zappa",
name: "Frank",
surname: "Zappa"
}
Later you can see how to specify the fields mapping function to specify which one has to be used to compile the template. Templates can be stored in any path you want, usually a path under your __dirname.
mailTemplates configuration example
You can configure templates in your service exporting the configuration object as in the following example.
You specify the templates base path and an array of templates configuration. Each template configuration will specify:
-
name: the name of the template used in the templates map to retrieve the template when an event is consumed.
The name MUST be composed as event_type:[event_spec] (a.e. "NewUser:NormalUser") -
params
- htmlTemplate: the name of the handlebars template (a.e. "new-user.hbs")
- subject: the mail subject text
-
attachments: the array of the attachment files for this temaplate, if any. Each entry in the array will specify:
- filename: the filename showed in the attachment list
- path: the real file name (path is relative to the basePath)
- contentType: optional MIME type of the attachment file
- templateData: a function to specify which of the event's payload fields have to be used in the template compilation
// template-config.js
'use strict';
module.exports = {
basePath: `${__dirname}/templates`,
templates: [
{
name: 'NewUser:NormalUser',
params: {
htmlTemplate: 'new-user.hbs',
subject: 'User registration',
attachments: [
{
filename: 'Privacy.pdf',
path: 'attachments/Privacy.pdf',
contentType: 'application/pdf'
},
{
filename: 'TermsAndConditions.pdf',
path: 'attachments/TermsAndConditions.pdf',
contentType: 'application/pdf'
}
],
templateData: (evtData) => {
return {
username: evtData.username,
name: `${evtData.name} ${evtData.surname}`
};
}
}
},
{
// ...
// ...
},
{
// ...
// ...
}
]
};
Default directory scaffold for your Mailer project
Your Mailer project (or module) should have the following common scaffolding structure:
your-mailer-project/
├── templates/
│ ├── attachments/
│ │ ├── Privacy.pdf
│ │ └── TermsAndConditions.pdf
│ └── new-user.hbs
├── config/
│ ├── default.yml
│ ├── development.yml
│ └── production.yml
├── index.js
└── template-config.js
License
Licensed under the MIT license.