NodeJS applications mostly use the nodemailer module for simple email sending. An essential item of sending emails using the nodemailer module is creating a transporter for sending emails (an explanation will be provided in the form of comments in the code of the function for sending emails).

In order to send an email, we need to know who is sending the email and to whom the email is being sent, then, we need to add the subject, text, and optional parameters such as the bcc list of emails, attachments, and other options.

A simple function for sending mails can have the following implementation code: 

const nodemailer = require("nodemailer");

function sendEmail(to, subject, text, html, options, attachments) {
    const sendOptions = {
        to,
        subject,
        text,
        html,
        from: FROM_INFO,
        bcc: OPTIONAL_LIST_OF_EMAILS,
        ...(options || {})
        ...(attachments && { attachments: attachments })
    };

    const transportOptions = {
        auth: {
            user: EMAIL_USERNAME,
            pass: EMAIL_PASSWORD
        },
        pool: true,
        maxConnections: 10,
    };
    
    // Lazily create new transporter. The mailConfig should contain following properties:
    // - service - List of available servies https://nodemailer.com/smtp/well-known/
    // or
    // - host & port - SMTP host and port. The service property will override this!
    // - auth object with user and pass properties - for authorization
    TRANSPORTER = nodemailer.createTransport(transportOptions);
    
    return new Promise((resolve, reject) => {
        TRANSPORTER.sendMail(sendOptions, (err, info) => {
            if (err) {
                reject(err);
            } else {
                resolve(info);
            }
        });
    });
}

Now we have everything needed to send an email.

Considering that the topic of  Tech Bite is email notification reminder, the function for creating a template for that type of email can look like this:

async function sendNotificationEmail(user) {
    const email = {
        lang: 'en',
        body: `<p>Dear ${user.name} ${user.lastname},</p><p>we remind you that ...</p>`,
        subject: 'New users reminder'
    };
    return sendEmail(
            user.email, 
            email.subject, 
            'New email from ...', 
            email.body)
        .then(
            // do something
        );
};

Finally, it remains to show how to create a cronjob that sends email reminders. Nodejs applications use the cron tool to create cron jobs. Cron is a tool that allows you to execute something on a schedule. This is typically done using the cron syntax. A classic use of this tool looks like this:

const { CronJob } = require('cron');

const TIME_OF_EXECUTION_REMINDER_CRON_JOB = '0 12 * * *'; // every day at 12 am

function reminderCronJob() {
  new CronJob(TIME_OF_EXECUTION_REMINDER_CRON_JOB, async function () {
        // notify users
  }, null, true, 'Europe/Brussels').start();
}

To complete the topic of sending email reminder notifications, it is necessary to pay attention to the type of email reminder. Suppose we want to send an email reminder notification only once (for example, after user registration). In that case, we need to add information to the database about whether the user has been notified. You can add a migration to your application that adds the following field:

reminderEmail: {
    notified: boolean
}

The “reminderEmail.notified” field has a default value of false. After the email reminder notification has been successfully sent, this field is updated, and its value is set to true.

Therefore, we can update the function in the following way:

const { CronJob } = require('cron');

const TIME_OF_EXECUTION_REMINDER_CRON_JOB = '0 12 * * *'; // run every time in 12:00 am

function reminderCronJob() {
  new CronJob(TIME_OF_EXECUTION_REMINDER_CRON_JOB, async function () {
    
    // get all unnotified users
    const usersToNotify = await User.find({ 'reminderEmail.notified': false });
    
    for (let i = 0; i < usersToNotify.length; i++) {
        const user = usersToNotify[i];
        await sendNotificationEmail(user);
        // update reminderEmail.notified field
        await User.updateOne({ _id: user._id }, { $set: { 'reminderEmail.notified': true } }).exec();
    }
    
  }, null, true, 'Europe/Brussels').start();
}

 


“Email reminder notifications with Nodejs, Mongodb and cron jobs” Tech Bite was brought to you by Lejla Mujić, Junior Software Engineer at Atlantbh.

Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.

oban
Software DevelopmentTech Bites
February 23, 2024

Background Jobs in Elixir – Oban

When and why do we need background jobs? Nowadays, background job processing is indispensable in the world of web development. The need for background jobs stems from the fact that synchronous execution of time-consuming and resource-intensive tasks would heavily impact an application's  performance and user experience.  Even though Elixir is…

Want to discuss this in relation to your project? Get in touch:

Leave a Reply