Build an Email Scheduler with Express, Vue, Nodemailer, Node-cron and MongoDB

Toluarejibadey
4 min readApr 7, 2023

--

Hi,

This article covers sending emails in a Node JS application. If you want to send a simple email with attached docs, this article covers it

Here are some simple steps to follow for that:

This is the project structure of the application

Step #1: Install the module needed for the project in your app

To do so, we need to use a package manager, either NPM or Yarn as you want:

npm install nodemailer body-parser cors node-cron express dotenv mutler

Step #2: Add this in your server.js file

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const dotenv = require("dotenv");

const PORT = process.env.PORT || 3000;
dotenv.config();

const app = express();
const router = express.Router();
const cronsRoutes = require("./routes/cron");

app.use(morgan("combined"));
app.use(bodyParser.json());
app.use(cors());
app.use("/api", cronsRoutes);
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
app.get("/h", (req, res) => {
res.send("Successful response.");
});
app.use("/", router);

in this file all we did was to import all the files / dependencies we’ll be using for the application

Step #3: we’ll be using multer for file upload Add this in your upload-file.js in middlewares folder

const multer = require("multer");

var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './images')
},
filename: function (req, file, callback) {
callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname)
}
})
var upload = multer({
storage: Storage
}).single('file')
module.exports = upload;

here we created a storage path in which the uploaded images would be stored

Step #4: Create a .env file at the root of your folder and add this


GOOGLE_APP_EMAIL=
GOOGLE_APP_PW=

in order to use gmail for sending mail you need to create a temporary password which is an app password ,in order to get the app password you’ll need to enable 2 step verification on your google account

Step #5: Add this in your cron.js in routes folder

before adding the file lets take a look at cron functions

there are 6 options which one can use in scheduling

cron.schedule('* * * * * *', () => {
console.log("runs in every second")
});
# ┌────────────── second (optional)
# │ ┌──────────── minute
# │ │ ┌────────── hour
# │ │ │ ┌──────── day of month
# │ │ │ │ ┌────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *

now add this is your cron.js file…. in this file we require the dependencies we’ll be using…event emitter is use to emit event each time a function has been called



const cronJob = require('node-cron');
const express = require("express");
const router = express.Router();
const nodemailer = require('nodemailer');
const EventEmitter = require('events');
const emitter = new EventEmitter()
emitter.setMaxListeners(0)
const upload = require("../middlewares/upload-file");
const event = new EventEmitter();

// create an instance to send a mail
let mailTransporter = nodemailer.createTransport({
service: "gmail",
auth: {user: process.env.GOOGLE_APP_EMAIL,
pass: process.env.GOOGLE_APP_PW
}
});
// make a post request
router.post(`/crons`, async (req, res) => {
upload(req, res, function (err) {
try {
// data that would be sent
const data = {
to: req.body.to,
subject: req.body.subject,
second: req.body.second,
minute: req.body.minute,
hour: req.body.hour,
day: req.body.day,
month: req.body.month,
week: req.body.week,
html: req.body.html,
attachments: [{
path: req.file.path
}]
};
console.log(data.minute, data.hour, data.day, data.month, data.week)
//create a scheduler using node-cron each cron option we need to Use template literal back ticks and dollar sign to pass in the variable
const task = cronJob.schedule(`*/${data.minute} ${data.hour} ${data.day} ${data.month} ${data.week}`, () => {
// collect the data and send an email
mailTransporter.sendMail(data, err => {
if (err) {
console.log(err)
} else {
res.json({
status: true,
message: "email sent",
});
console.log("email sent");
event.emit('JOB COMPLETED');
}

});
})
event.on('JOB COMPLETED', () => {
// stop task immeditely an email, has been sent
task.stop();
});

} catch (error) {
}
})
});
module.exports = router;

this how i send the data using post man, you need use form-data because your sending a file

in my gmail i get the mail and attachment

the final code is available here https://github.com/ajibssss/email-sender

front-end using vue is in this post https://medium.com/@toluarejibadey/how-to-build-an-email-scheduler-with-express-vue-nodemailer-node-cron-and-mongodb-front-end-8a903b65baeb

--

--