Automate and deploy a script for managing and cleaning up emails using Node.js.

GabrielGabriel
4 min read

Introduction

Automating and deploying a script to manage and clean up emails using Node.js is a great way to simplify your email management tasks. Here’s a quick introduction to help you get started:

Project Setup

  1. Setup your environment

    To get started, ensure Node.js is installed on your machine. You can download it from the official Node.js website.

  2. Setup project and install required packages

    You’ll need to setup a new project and install all the relevant packages to handle email management operations and scheduling tasks.

     npm init -y
     npm install dotenv node-imap node-schedule
     npm install --save-dev nodemon
    
    1. Create your script

      Create an app.js file in the root directory of your project and add the following code

       require("dotenv").config({ path: `${process.cwd()}/.env` });
      
       const Imap = require("node-imap");
       const inspect = require("util").inspect;
       const schedule = require("node-schedule");
       const http = require("http");
      
       const userEmail = process.env.USER_EMAIL;
       const userPassword = process.env.USER_PASSWORD;
       const emailHost = process.env.EMAIL_HOST;
       const emailPort = parseInt(process.env.EMAIL_PORT);
       const cronSchedule = process.env.CRON_EXPRESSION;
      
       let emails = process.env.BLACKLISTED_EMAILS;
      
       let searchCriteriaArray = [];
       let blackListedEmailCollection = emails.split(",");
      
       blackListedEmailCollection.forEach((email) => {
         searchCriteriaArray.push(["FROM", email.trim()]);
       });
      
       const imap = new Imap({
         user: userEmail,
         password: userPassword,
         host: emailHost,
         port: emailPort,
         tls: true,
       });
      
       async function run() {
         imap.once("ready", function () {
           openInbox(async function (err, box) {
             if (err) {
               console.log("Error opening mailbox:", err);
               return;
             }
             console.log("Search Criteria:", searchCriteriaArray);
             for (let searchCriteria of searchCriteriaArray) {
               console.log("Searching with criteria:", searchCriteria);
               await new Promise((resolve, reject) => {
                 imap.search([searchCriteria], function (err, results) {
                   if (err) {
                     reject(err);
                     return;
                   }
      
                   if (!results || !results.length) {
                     console.log("No emails found for criteria:", searchCriteria);
                     resolve();
                     return;
                   }
      
                   imap.setFlags(results, "\\Deleted", function (err) {
                     if (err) {
                       reject(err);
                       return;
                     }
                     console.log(
                       "Marked emails for deletion for criteria:",
                       searchCriteria
                     );
                     imap.expunge(results, function (err) {
                       if (err) {
                         reject(err);
                         return;
                       }
                       console.log("Deleted emails for criteria:", searchCriteria);
                       resolve();
                     });
                   });
                 });
               }).catch((err) => {
                 console.error("Error processing criteria:", searchCriteria, err);
               });
             }
      
             imap.end();
           });
         });
      
         imap.once("error", function (err) {
           console.log(err);
         });
      
         imap.once("end", function () {
           console.log("Connection ended");
         });
      
         imap.connect();
       }
      
       function openInbox(cb) {
         imap.openBox("INBOX", false, cb);
       }
      
       // Schedule the script to run every 15 minutes
      
       schedule.scheduleJob(cronSchedule, async function () {
         console.log("Running script...");
         await run();
       });
      
       const PORT = process.env.APP_PORT || 4000;
       const HOSTNAME = process.env.APP_HOSTNAME;
      
       const server = http.createServer((req, res) => {
         res.statusCode = 200;
         res.setHeader("Content-Type", "text/plain; charset=UTF-8");
         res.end("Email cleaner script is running now... 🚀🚀🚀\n");
       });
      
       server.listen(PORT, HOSTNAME, () => {
         console.log(`Server listening on port ${PORT}!`);
       });
      

      The node-imap library is a popular choice for interacting with IMAP servers in Node.js. It offers a reliable and flexible way to connect to an IMAP server, such as Gmail, Yahoo, or Outlook, fetch emails, and perform various email-related tasks.

      Next, we have our scheduler, which we can set up with a cron expression to determine how often we want our scripts to run.

      Additionally, we create our .env file in the root directory to define all our secrets. For this project, your .env file should look like this:

       APP_PORT=3000
       APP_HOSTNAME=127.0.0.1
      
       # Email Credentials
       EMAIL_HOST=imap.gmail.com
       EMAIL_PORT=993
       USER_EMAIL=
       USER_PASSWORD=
      
       BLACKLISTED_EMAILS=subscribe@uk.jooble.org,CWJobs@jobs.cwjobs.co.uk,email@m.fragrancex.com,noreply@medium.com,admin@jobs.cv-library.co.uk,support@metawin.com,alert@indeed.com,newsletter@aisecret.me,jobalerts-noreply@linkedin.com,crew@morningbrew.com,hello@email.canadianvisa.org,premium@academia-mail.com
      
       # Cron schedule
       CRON_EXPRESSION=*/5 * * * *
      

      In the .env file above, enter the email address of the account you want to configure this script for in the USER_EMAIL property.

      For the USER_PASSWORD, you'll need to set up 2FA on your account if you plan to use Gmail as your email service. Only then will Gmail allow you to create an app password, which you'll enter as USER_PASSWORD. This article will help you set up IMAP, 2FA, and app passwords on your Gmail account.

      The BLACKLISTED_EMAILS are the emails you want to delete, while the CRON_EXPRESSION is the schedule you want to run. You can learn more about scheduling your cron jobs here.

      The script above can delete all the emails listed in the BLACKLISTED_EMAILS property.

      Here are other tasks you can perform using the node-imap library:

      • IMAP Client: Connects to an IMAP server to fetch emails.

      • Fetch Emails: Retrieves email headers, bodies, and attachments.

      • Search Emails: Searches based on criteria like date, sender, subject, etc.

      • Mark as Read/Unread: Marks emails as read or unread.

      • Delete Emails: Deletes emails from the server.

    2. Deploy Script to Render (or Any Cloud Service Provider)

      Create a Render account if you don't have one yet. It offers a free tier on some services, which is great for small projects.

      Next, create a web service and choose Node.js as the runtime. Set up the build and start commands (npm install and npm start). Make sure to add the .env variables to the project before deploying.

You can check out the code on Github

2
Subscribe to my newsletter

Read articles from Gabriel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Gabriel
Gabriel

I am Gabriel, a software developer from Uyo, Nigeria. I'm a graduate of Chemical Engineering but my passion for tech led me into a career in software development.