Skip to content

Hownameee/mail-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

High-Performance gRPC Mail & OTP Server

A high-concurrency microservice built with Go and gRPC to handle email delivery and OTP management.

📂 Project Structure

  • go_server/: The core gRPC server (Go).
  • node_client/: A TypeScript client for functional and performance testing.

🎯 Core Problem & Solution

  • The Problem: Standard net/smtp is slow because it creates a new connection (TCP handshake + TLS + Auth) for every single email sent.
  • Our Solution: Implements a Worker Pool with Persistent Connections. Workers pre-dial and stay authenticated, allowing emails to be dispatched instantly with zero handshake latency.

⚡ Key Features

  • Zero-Latency Sending: Persistent SMTP connections eliminate handshake overhead.
  • Concurrency: Configurable worker pool (default: 5) handles multiple clients simultaneously without blocking.
  • Thread-Safe OTP: In-memory storage protected by sync.RWMutex with atomic validation logic to prevent race conditions.
  • Auto-Cleanup: Background "Janitor" worker removes expired OTPs to prevent memory leaks.
  • Graceful Shutdown: Completes active jobs before closing connections on SIGINT or SIGTERM.

⚙️ Configuration (.env)

Create a .env file inside the go_server/ directory:

PORT=40700
WORKERS=5                 # Concurrent SMTP connections
OTP_CLEANUP_SECONDS=180   # Expiry check interval
OTP_LIFESPAN_SECONDS=120  # Duration before OTP expires

# SMTP Settings (e.g., Gmail)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=465
EMAIL=your_email@gmail.com
APP_PASSWORD=xxxx-xxxx-xxxx-xxxx

# For test in node_client
TARGET=example@gmail.com

Recommended for Testing: Use these values to ensure the Node.js client tests (which check for expiration) finish quickly without long waits.

# Test Settings (Short durations to speed up client tests)
OTP_CLEANUP_SECONDS=15    # Run cleanup every 15s
OTP_LIFESPAN_SECONDS=5    # OTP expires after 5s

🚀 Server Usage

Setup

cd go_server
go mod tidy
make generate  # Re-generates Protobuf code

Run

go run main.go

🧪 Client Usage

The client performs functional tests (OTP flow, Email sending) and benchmarks performance.

⚠️ Important: The client relies on Protocol Buffers code generated by the server. You must run the server generation step first.

Install Dependencies

cd node_client
npm install

Run Tests

npm start

📚 API Overview

OtpService

Method Inputs Description
SendCode email Generates a 6-digit code, stores it in memory, and dispatches an email via the worker pool.
ValidateCode email, otp Thread-safe validation. Automatically deletes the code upon success to prevent replay attacks.

MailService

Method Inputs Description
SendMail to, subject, body Asynchronously queues a raw email to be processed by the next available worker.

📊 Performance Benchmark (15 Concurrent Clients)

Here is the average response time per request based on the worker pool size:

1 Worker: ~1700ms (High Latency)

2 Workers: ~800ms

3 Workers: ~700ms

≥ 4 Workers: ~500ms - 700ms (Saturation Point)

💡 Conclusion

4 Workers is the optimal configuration.

The data shows that performance improves significantly up to 4 workers but plateaus afterwards. Beyond this point, the bottleneck shifts from our application to the external Gmail SMTP server. Since the upstream provider handles requests sequentially or enforces rate limits, adding more workers (5-10) adds system overhead without reducing the average wait time.

About

A stand alone mail server.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors