DEV Community

Cover image for Send automated reports using Nodejs
aram
aram

Posted on • Edited on

Send automated reports using Nodejs

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-cron used for scheduling tasks
  • node-mailer used 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

  1. create a folder & cd to the folder using command line something like exampleFolder
  2. run npm init this will ask you couple of questions after you finish there will be a file called package.json alternatively if you don't want to answer questions type npm init -y this will answer yes for all question,

  3. install node-cron type npm i node-cron --save in the console

  4. install nodemailer type npm i nodemailer --save in 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"
        }
    }
Enter fullscreen mode Exit fullscreen mode

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"
        }
    }

Enter fullscreen mode Exit fullscreen mode

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
                }
            },
        };
Enter fullscreen mode Exit fullscreen mode

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.js and import sendMail from reportSender.js using this syntax const {sendMail} = require('./reportSender') note that no file extension is required when importing

  • make a call to sendMail function so it can send and email example sendMail("Hello world", "this is email body it can contain html also") if you didnt update defaultMailingList to 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 βœ“')
Enter fullscreen mode Exit fullscreen mode

received email

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');
        });
Enter fullscreen mode Exit fullscreen mode

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++;
        });
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
terabytetiger profile image
Tyler V. (he/him)

This article just saved me so much time πŸŽ‰

Very well written and clearly lays out the path from start to finish.

Loved it!

Collapse
 
rattanakchea profile image
Rattanak Chea

Thanks look good. Will give it a try.