Create a simple email sender app

Leader posted 2 min read

Features we can add here:

  • Compose one message
  • Send it to a list of 100 recipients
  • Work from a web interface (Angular or plain HTML)
  • Use a backend (Node.js + Nodemailer) for sending the email

Tech Stack:

  • Frontend: Angular or HTML+JS
  • Backend: Node.js + Express
  • Email: Nodemailer (SMTP)
  • SMTP Provider: Gmail, SendGrid, Mailgun, or custom

Important Notes:

  • Gmail limits bulk emails (to avoid spam). Use SendGrid, Mailgun, or a verified domain for reliable delivery.
  • Always include unsubscribe links for compliance if it's marketing-related.

Step-by-Step Guide

Project Structure:

email-app/
├── backend/
│   ├── server.js
│   ├── mailer.js
│   └── .env
└── frontend/
    └── index.html (or Angular app)

1. Backend (server.js + mailer.js)

backend/server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
require('dotenv').config();
const sendBulkEmail = require('./mailer');

const app = express();
app.use(cors());
app.use(bodyParser.json());

app.post('/send-email', async (req, res) => {
  const { subject, message, recipients } = req.body;

  try {
    await sendBulkEmail(subject, message, recipients);
    res.status(200).send('Emails sent successfully!');
  } catch (err) {
    console.error(err);
    res.status(500).send('Failed to send emails');
  }
});

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

backend/mailer.js
const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({
  service: 'gmail', // or use SendGrid SMTP, etc.
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS
  }
});

async function sendBulkEmail(subject, message, recipients) {
  const mailOptions = {
    from: process.env.EMAIL_USER,
    to: recipients.join(','), // for bulk
    subject: subject,
    text: message
  };

  await transporter.sendMail(mailOptions);
}

module.exports = sendBulkEmail;

.env
EMAIL_USER=*Emails are not allowed*
EMAIL_PASS=your-email-app-password

2. Frontend (Basic HTML Example)

<!DOCTYPE html>
<html>
<head>
  <title>Bulk Email Sender</title>
</head>
<body>
  <h2>Send Email to Multiple People</h2>
  <form id="emailForm">
    <input type="text" id="subject" placeholder="Subject" required /><br><br>
    <textarea id="message" placeholder="Message" required></textarea><br><br>
    <textarea id="recipients" placeholder="Comma-separated emails" required></textarea><br><br>
    <button type="submit">Send Email</button>
  </form>

  <script>
    document.getElementById('emailForm').addEventListener('submit', async (e) => {
      e.preventDefault();
      const subject = document.getElementById('subject').value;
      const message = document.getElementById('message').value;
      const recipients = document.getElementById('recipients').value.split(',');

      const res = await fetch('http://localhost:3000/send-email', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ subject, message, recipients })
      });

      const result = await res.text();
      alert(result);
    });
  </script>
</body>
</html>

To Run:

cd backend
npm init -y
npm install express cors nodemailer body-parser dotenv
node server.js

Then open frontend/index.html in your browser.


If you read this far, tweet to the author to show them you care. Tweet a Thanks

1 Comment

0 votes

More Posts

NodeJS Timeouts: The I'm Still Working, Just Not Talking to You Problem

David Oluwatobi Peter - Jul 14

Centralized Notifications: Unifying Email, SMS, and FCM Messaging

caleb erioluwa - Jun 16, 2024

Building the Backend of Chatty - A Real-Time MERN WebSocket Chat App

Mohammad Yasir - Feb 21

How to set up TypeScript with Node.js and Express

Sunny - Jul 13

How to set up TypeScript with Node.js and Express (2025)

Sunny - Jun 6
chevron_left