Building an Email Scheduler with Node.js and React

In this blog post, we'll walk through how to build a simple email scheduler application using Node.js, Express, and React. This project demonstrates how to schedule and send emails with a user-friendly interface.

Project Overview

Our Email Scheduler application allows users to compose and schedule emails to be sent at specific times. It features a React frontend for the user interface and a Node.js backend for handling email sending and scheduling.

Tech Stack

  • Frontend: React

  • Backend: Node.js, Express

  • Email Service: Nodemailer

  • Scheduling: node-cron

  • Styling: Tailwind CSS

Setting Up the Backend

  1. Install Dependencies

    Install the required packages:

     npm install express nodemon nodemailer dotenv cors node-cron
    
  2. Create the Backend Code

    Create a file named server.js in the backend directory and add the following code:

     import express from "express";
     import nodemailer from "nodemailer";
     import dotenv from "dotenv";
     import cors from "cors";
     import cron from "node-cron";
    
     const app = express();
     dotenv.config();
    
     app.use(cors());
     app.use(express.json());
    
     app.post("/sendEmail", (req, res) => {
       const { name, email, subject, message } = req.body;
    
       const transporter = nodemailer.createTransport({
         service: "Gmail",
         auth: {
           user: process.env.EMAIL_FROM,
           pass: process.env.EMAIL_PASS,
         },
       });
    
       const mailOptions = {
         from: process.env.EMAIL_FROM,
         to: email,
         subject: subject,
         text: `${message} sent by ${name}`,
       };
    
       cron.schedule("0 9 * * *", () => {
         transporter.sendMail(mailOptions, (error, info) => {
           if (error) {
             console.log("Error occurred: ", error);
           } else {
             console.log("Email sent: " + info.response);
           }
         });
       });
    
       res.status(200).json({ message: "Email scheduled successfully" });
     });
    
     app.listen(5000, () => {
       console.log("Server is running on port 5000");
     });
    
  3. Create the .env File

    Create a .env file in the backend directory with the following content:

     EMAIL_FROM=your-email@gmail.com
     EMAIL_PASS=your-email-password
    

    Replace your-email@gmail.com and your-email-password with your actual email credentials.

Setting Up the Frontend

Create the Frontend Code

Replace the code in src/App.js with the following:

import { useState } from "react";
import "./App.css";

function App() {
  const [form, setForm] = useState({
    name: "",
    fromMail: "",
    toMail: "",
    subject: "",
    intro: "",
    body: "",
    footer: ""
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm((prevForm) => ({
      ...prevForm,
      [name]: value
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await fetch("http://localhost:5000/sendEmail", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(form)
      });
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error("Error:", error);
    }
  };

  return (
    <div>
      <h1 className="text-5xl font-semibold text-cyan-200 ml-3">Email Scheduler</h1>
      <form
        className="form p-6 max-w-full mx-auto text-white rounded-xl"
        onSubmit={handleSubmit}
      >
        <h2 className="text-lg text-cyan-400 mb-4">Send a Mail to anyone</h2>
        <div className="flex gap-4 mb-3">
          <label className="relative w-full">
            <input
              type="text"
              placeholder="Your Name"
              name="name"
              value={form.name}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none mb-1"
            />
          </label>
          <label className="relative w-full">
            <input
              type="email"
              placeholder="Your Email"
              name="fromMail"
              value={form.fromMail}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none"
            />
          </label>
          <p className="text-cyan-400 mt-3 text-lg">To</p>
          <label className="relative w-full">
            <input
              type="email"
              placeholder="Receiver Email"
              name="toMail"
              value={form.toMail}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none"
            />
          </label>
        </div>
        <div className="flex gap-4">
          <p className="text-cyan-400 mt-2 text-lg">Subject</p>
          <label className="relative mb-4 w-full">
            <input
              type="text"
              placeholder="Subject"
              name="subject"
              value={form.subject}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none"
            />
          </label>
        </div>
        <div className="flex gap-4">
          <p className="text-cyan-400 mt-2 text-lg">Intro</p>
          <label className="relative mb-3 w-full">
            <input
              type="text"
              placeholder="Email"
              name="intro"
              value={form.intro}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none"
            />
          </label>
        </div>
        <div className="flex gap-4">
          <p className="text-cyan-400 mt-2 text-lg">Body</p>
          <label className="relative mb-3 w-full">
            <textarea
              type="text"
              placeholder="Email"
              name="body"
              value={form.body}
              onChange={handleChange}
              required
              className="textarea w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none textarea-lg"
              rows={3}
            ></textarea>
          </label>
        </div>
        <div className="flex gap-4">
          <p className="text-cyan-400 mt-2 text-lg">Footer</p>
          <label className="relative mb-3 w-full">
            <input
              type="text"
              placeholder="Email"
              name="footer"
              value={form.footer}
              onChange={handleChange}
              required
              className="input w-full p-3 bg-neutral-700 text-white rounded-lg border border-neutral-600 focus:border-cyan-400 outline-none"
            />
          </label>
        </div>
        <button
          type="submit"
          className="submit w-full p-3 bg-cyan-400 text-white rounded-lg hover:bg-cyan-500 transition-transform duration-300 ease-in-out transform active:scale-95 active:shadow-lg"
        >
          Send
        </button>
      </form>
    </div>
  );
}

export default App;

Conclusion

In this tutorial, we’ve built a basic email scheduler application using Node.js, Express, and React. We’ve covered setting up the backend server to handle email sending and scheduling, as well as creating a React frontend to interact with

12
Subscribe to my newsletter

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

Written by

Rishabh Raj Verma
Rishabh Raj Verma

I’m a Full-Stack Developer skilled in the MERN stack with a strong understanding of Machine Learning. I enjoy building responsive web applications and using AI to solve problems. I’m always excited to learn new technologies and apply them to create innovative solutions.