Introduction
In this article we will explain how you can send reports automatically and periodically using a NodeJs whether you embed the logic inside your application or you make it a separate script its up to the developer but separate script is recommended(we use this approach), before you start you should know what is NodeJs you can benefit from this A Quick Guide to Node.js in 2019
Requirements
Two packages is required for this tutorial
-
node-cronused for scheduling tasks -
node-mailerused to send emails to some user list using some SMTP providers googles Gmail will be used for this purpose as it is free and easy to setup
Project setup
Start by creating new NodeJs project
- create a folder & cd to the folder using command line something like
exampleFolder run
npm initthis will ask you couple of questions after you finish there will be a file calledpackage.jsonalternatively if you don't want to answer questions typenpm init -ythis will answer yes for all question,install
node-crontypenpm i node-cron --savein the consoleinstall
nodemailertypenpm i nodemailer --savein the console
After the installation you should see a folder called node_modules and generated package.json should look something like this
{
"name": "exampleFolder",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"node-cron": "^2.0.3",
"nodemailer": "^6.3.0"
}
}
Let's start coding
We need an entry point for our application(script) start by creating a file called main.js and add "start": "node main.js" line to package.json under "scripts" property so it becomes like this
{
"name": "exampleFolder",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node main.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"node-cron": "^2.0.3",
"nodemailer": "^6.3.0"
}
}
Add console.log("Hello world") inside main.js then in the console type npm start this should output Hello world to the console this is used to make sure our application runs
Configure nodemailer
We will start by configuring nodemailer follow these steps
- create a file called
reportSender.js - paste this script inside the file
const nodemailer = require('nodemailer');
const defaultMailingList = "example1@vultr.com,example2@vultr.com";
const senderEmail = "sender.example@gmail.com";
const senderPassword = "gmail_app_password"; // gmail app password
module.exports = {
sendMail: async (subject, text, to = defaultMailingList) => {
try {
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: senderEmail,
pass: senderPassword,
},
});
const message = {
from: `report sender <${senderEmail}>`,
to,
subject,
text: subject,
html: text,
};
transporter.sendMail(message, () => {});
} catch (e) {
// handle errors here
}
},
};
Note that nodemailer provides handful of transports including custom ones
Values are hardcoded i would recommend using something like dotenv which loads .env file and creates environment variables based on the environment variable but for sake of simplicity we did that here,
What this file does is that it exports an object with key sendMail which is a function that configures node mailer and setup a generic method for sending our reports as we please for future uses you can add extra keys to main object for example you want the report to be sended via telegram by a bot you can add the logic in this file
you can get gmail app password following this link get app password
Test if node mailer can send emails for us
- after you change these variables in a correct way [
senderEmail,senderPassword,defaultMailingList] open
main.jsand importsendMailfromreportSender.jsusing this syntaxconst {sendMail} = require('./reportSender')note that no file extension is required when importingmake a call to
sendMailfunction so it can send and email examplesendMail("Hello world", "this is email body it can contain html also")if you didnt updatedefaultMailingListto contain your email you can pass the email after msg body
the complete body of our main.js is something like this
const {sendMail} = require('./reportSender');
console.log('sending email...')
sendMail("Hello world", "this is email body it can contain html also")
console.log('email sent ✓')
With this we can send emails to some specific emails as you can predict that you can somehow generate a string which contains a valid html and this html is generated using data from our database then you can send reports or even data to your mailing list
if you are wondering what is a good module for database connection i would recommend using kenxjs
the only thing remains is to automate sending reports(emails) with that comes node-cron module
Configure node-cron
Configuring node-cron is an easy task you tell it when do you want for some action to take place then you provide the action definition and whenever the call triggers it will call this action, ction is a function
for sake of this tutorial let's say i want to receive a report every 1 min
what you can do according to their documentation is something like this
var cron = require('node-cron');
cron.schedule('* * * * *', () => {
console.log('running a task every minute');
});
You can test this code just comment everything inside main.js then wait for 1 min and you should see running a task every minute output every 1 min on the console as you can see the callback is our action and its the place that we want to implement and generate our reports then send the emails (generated reports)
Combine our nodemailer and node-cron
As you can see by combining just two modules we could make an automated system that can send reports or even anything that we want periodically so lte's show our final main.js
const {sendMail} = require('./reportSender');
var cron = require('node-cron');
let counter = 1;
cron.schedule('* * * * *', () => {
/*
generate your report here then send the report using
any reportSender logic that you implemnted email, telegram bot,...
*/
sendMail(`hello world ${counter}`, "this is email body it can contain html also");
counter++;
});
Final words
The idea have alot of potential so you could get creative and make anything you want, the reason i recommended making this as a separate script is that it become another process on the CPU so simply terminate the process if you want to stop the service, in production you have your separate system this script works as an assistant and provides a nice simple feature it could be run using something like pm2 which is strongly recommend.

Top comments (2)
Thanks look good. Will give it a try.
This article just saved me so much time 🎉
Very well written and clearly lays out the path from start to finish.
Loved it!