Skip to main content

Command Palette

Search for a command to run...

Build Your Own SMTP Mail Server on AWS EC2 Using Node.js โ€” A Complete Hands-On Guide

Published
โ€ข8 min read
Build Your Own SMTP Mail Server on AWS EC2 Using Node.js โ€” A Complete Hands-On Guide
P
DevOps Engineer with ~3 years of hands-on experience designing, automating, and operating cloud-native infrastructure on AWS and Kubernetes (EKS). I specialize in Terraform-based IaC, CI/CD automation, GitOps with ArgoCD, observability stacks (Prometheus, Grafana, OTEL), and cloud security. I've led GCP-to-AWS migrations, built multi-environment EKS deployments for 50+ microservices, and achieved 35โ€“40% infra cost reductions using FinOps practices. Currently working at Infra360 (Gurugram) as Associate DevOps Engineer. I write about real-world DevOps challenges, cloud-native architecture, and GitOps best practices at blog.devopswithpiyush.in. ๐ŸŽ“ MCA | University Institute of Technology, Bhopal ๐Ÿ… AWS Certified Solutions Architect โ€“ Associate ๐Ÿ… Certified Kubernetes Administrator (CKA) | Linux Foundation

Introduction

Ever wondered what really happens when you click "Send" on an email? Behind the scenes, a chain of DNS lookups, protocol handshakes, and server communications takes place โ€” all orchestrated by SMTP (Simple Mail Transfer Protocol).

In this tutorial, we'll demystify email delivery by building a custom SMTP server from scratch โ€” hosted on Amazon EC2. By the end, you'll have a working mail server that can receive emails on your own domain, and a deep understanding of how email infrastructure works under the hood.

๐Ÿ”— This post is based on my video walkthrough: Build Your Own Mail Server | SMTP Server


Prerequisites

Before you begin, make sure you have:

  • An AWS account with access to the EC2 console

  • A registered domain name (with access to DNS management)

  • Basic familiarity with Linux terminal commands

  • Basic understanding of Node.js


How Email Delivery Actually Works

Let's say Piyush (using Gmail) wants to send an email to Abhay (using Outlook).

Here's the step-by-step flow:

  1. MX Record Lookup โ€” Piyush's mail server generates a DNS query on outlook.com to find the MX (Mail Exchanger) Record. This tells it which server is responsible for handling incoming mail for that domain.

  2. A Record Lookup โ€” The MX record returns a hostname (e.g., mailserver.outlook.com). A second DNS query resolves this hostname to an IPv4 address using the A Record.

  3. SMTP Connection โ€” Piyush's server opens a TCP connection to the resolved IP on port 25 and begins the SMTP handshake to deliver the message.


DNS Records Every Mail Server Needs

Before your server can send or receive email reliably, you need to configure several DNS records:

Record Purpose
MX Specifies which mail server handles email for your domain
A Maps your mail server's hostname to its public IPv4 address
SPF Defines which servers are authorized to send email on behalf of your domain (prevents spoofing)
DKIM Adds a cryptographic signature to outgoing emails, verifying sender identity and message integrity
DMARC Builds on SPF and DKIM to define how receiving servers should handle authentication failures

SMTP Protocol โ€” The Handshake

SMTP communication follows a structured command sequence. Here's how the conversation between two servers typically flows:

Command Description
HELO Initiates the SMTP session; the client introduces itself to the server
MAIL FROM Declares the sender's email address
RCPT TO Specifies the recipient's email address
DATA Requests permission to begin transmitting the email body
QUIT Terminates the SMTP session

Default SMTP Ports:

  • Port 25 โ€” Standard SMTP

  • Port 465 โ€” SMTP over SSL/TLS (secure)


Step 1 โ€” Launch an EC2 Instance on AWS

Head over to the AWS Management Console and launch a new EC2 instance.

Recommended Configuration:

  • AMI: Ubuntu Server 22.04 LTS (or latest)

  • Instance Type: t2.micro (Free Tier eligible โ€” perfect for this project)

  • Key Pair: Create or select an existing SSH key pair

  • Network: Ensure the instance has a public IP address (we'll configure the security group shortly)

๐Ÿ’ก Why EC2? Amazon EC2 gives you full control over your server environment โ€” including the operating system, network configuration, and security policies. It's ideal for running custom services like an SMTP server where you need to open specific ports and manage DNS records pointing to your instance's public IP.


Step 2 โ€” Install Node.js and npm

SSH into your EC2 instance and install Node.js:

sudo apt update
sudo apt install nodejs npm -y
node -v

You should see output similar to:

v18.x.x

Tip: For the latest LTS version, consider using nvm (Node Version Manager) instead of the default apt package.


Step 3 โ€” Install the SMTP Server Package

Create a project directory and install the smtp-server npm package:

mkdir smtp-server && cd smtp-server
npm init -y
npm install smtp-server

Step 4 โ€” Write the SMTP Server Code

Create a file called index.js:

nano index.js

Paste the following Node.js code:

const { SMTPServer } = require("smtp-server");

const server = new SMTPServer({
  allowInsecureAuth: true,
  authOptional: true,

  onConnect(session, cb) {
    console.log(`[CONNECT] Session ID: ${session.id}`);
    cb();
  },

  onMailFrom(address, session, cb) {
    console.log(`[MAIL FROM] \({address.address} | Session: \){session.id}`);
    cb();
  },

  onRcptTo(address, session, cb) {
    console.log(`[RCPT TO] \({address.address} | Session: \){session.id}`);
    cb();
  },

  onData(stream, session, cb) {
    let emailData = "";
    stream.on("data", (chunk) => {
      emailData += chunk.toString();
    });
    stream.on("end", () => {
      console.log(`[DATA] Email content:\n${emailData}`);
      cb();
    });
  },
});

server.listen(25, () => {
  console.log("โœ… SMTP Server is running on port 25");
});

This creates a minimal SMTP server that logs every incoming email connection, sender, recipient, and message body โ€” great for understanding the protocol in action.


Step 5 โ€” Configure the EC2 Security Group

Back in the AWS EC2 Console, navigate to your instance's Security Group and add the following inbound rule:

Type Protocol Port Range Source
Custom TCP TCP 25 0.0.0.0/0 (or restrict as needed)

โš ๏ธ Security Note: Opening port 25 to 0.0.0.0/0 is fine for testing, but in production you should restrict access and implement authentication. AWS also throttles port 25 by default on EC2 โ€” you may need to submit a request to remove the restriction for outbound SMTP traffic.


Step 6 โ€” Configure DNS Records

Go to your domain registrar (or Amazon Route 53 if you manage DNS through AWS) and add the following records:

Record Type Host Value TTL
A mail.yourdomain.com <Your EC2 Public IP> 300
MX yourdomain.com mail.yourdomain.com (Priority: 10) 300

๐Ÿ”‘ Pro Tip: If you're using Amazon Route 53 for DNS management, you can associate an Elastic IP with your EC2 instance. This ensures your server's IP remains static, even if you stop/start the instance โ€” critical for reliable mail delivery.


Step 7 โ€” Start the Server

You can start the server directly with Node:

sudo node index.js

For production persistence, use PM2 (a Node.js process manager):

sudo npm install -g pm2
sudo pm2 start index.js
sudo pm2 save
sudo pm2 startup

You should see:

โœ… SMTP Server is running on port 25

Step 8 โ€” Test by Sending an Email

Open any email client (Gmail, Yahoo, Outlook) and send a test email to:

anything@yourdomain.com

Check your EC2 terminal โ€” you should see the SMTP handshake logs appear in real time:

[CONNECT] Session ID: abc123
[MAIL FROM] sender@gmail.com | Session: abc123
[RCPT TO] anything@yourdomain.com | Session: abc123
[DATA] Email content:
Subject: Test Email
Hello from Gmail!

๐ŸŽ‰ Congratulations! You've just built a working SMTP server on AWS EC2.


AWS Services Used

Service Purpose
Amazon EC2 Hosts the SMTP server on a virtual Linux machine in the cloud
Security Groups Acts as a virtual firewall to control inbound/outbound traffic on port 25
Elastic IP (optional) Provides a static public IP for consistent DNS resolution
Amazon Route 53 (optional) Managed DNS service for configuring MX and A records

What's Next?

This tutorial sets up a basic receive-only SMTP server for learning purposes. To take it further, consider:

  • Adding TLS encryption with Let's Encrypt certificates for secure communication

  • Configuring SPF, DKIM, and DMARC records for email authentication

  • Using Amazon SES alongside your custom server for reliable outbound email delivery

  • Implementing Postfix or Haraka for a production-grade mail transfer agent

  • Monitoring server health with Amazon CloudWatch


Wrapping Up

Building an SMTP server from scratch is one of the best ways to understand how email really works at the protocol level. By hosting it on Amazon EC2, you get the flexibility of full server access combined with the reliability and scalability of AWS infrastructure.

If this post helped you, feel free to drop a โค๏ธ and share it with someone learning about cloud infrastructure!


Have questions or want to connect? Find me on LinkedIn.

More from this blog

DevOps with Piyush

12 posts