Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MailForge

Distributed mass-mailing infrastructure platform. Upload contacts, build templates, launch campaigns, and deliver email at scale through a throttled, retrying worker pool.

Built with:

  • Next.js (App Router) — frontend
  • Golang — backend API + delivery worker
  • PostgreSQL — persistent storage
  • Redis — job queue between backend and worker
  • MailHog — local SMTP capture
  • Docker Compose — local orchestration
  • NGINX — reverse proxy

Architecture

        Frontend (Next.js)
                │
                ▼
        NGINX Reverse Proxy
        /      → frontend
        /api/* → backend
                │
                ▼
        Backend API (Go) ──────────► PostgreSQL
                │                        ▲
                │ enqueue email jobs     │ read/write
                ▼                        │
            Redis Queue                  │
                │                        │
                ▼                        │
        Worker pool (Go) ────────────────┘
        throttle → render → send → retry
                │
                ▼
          SMTP (MailHog in dev)

The backend persists contacts, templates, and campaigns, then fans out per-recipient jobs onto a Redis queue. The worker consumes jobs with a pool of goroutines, applies a rate limiter, renders the template, sends via SMTP, and retries failures with backoff while updating campaign counters in Postgres.


Repository Structure

mailforge/
│
├── frontend/                  # Next.js app (dashboard, campaigns, contacts, templates, login)
├── backend/                   # Go API service
│   └── internal/
│       ├── campaigns/         # campaign create/list handlers
│       ├── contacts/          # CSV/Excel upload handler
│       ├── templates/         # template CRUD handlers
│       ├── stats/             # aggregate stats endpoint
│       ├── handlers/          # health, shared handlers
│       ├── queue/             # Redis producer
│       ├── database/          # Postgres + migrations
│       └── routes/            # router setup
├── worker/                    # Go delivery worker
│   └── internal/
│       ├── queue/             # Redis consumer
│       ├── renderer/          # template rendering
│       ├── sender/            # SMTP delivery
│       ├── throttling/        # send-rate limiter
│       ├── retry/             # retry/backoff logic
│       ├── campaigns/         # campaign counter updates
│       └── database/          # Postgres access
├── nginx/                     # reverse proxy config
├── deployments/               # docker-compose.yml
├── .github/                   # CI workflows
├── .env.example
└── README.md

Tech Stack

Layer Technology
Frontend Next.js (App Router), Tailwind CSS
Backend Golang, gorilla/mux
Worker Golang (goroutine pool)
Database PostgreSQL 16
Queue Redis 7
Mail (dev) MailHog
Reverse Proxy NGINX
Containers Docker Compose
CI GitHub Actions

Local Development

Configure environment

cp .env.example .env
# adjust values as needed

Start services

cd deployments
docker compose up --build

Stop services

cd deployments
docker compose down

Services

Service URL
Frontend http://localhost:3000
Backend API http://localhost:8080/api/health
NGINX Proxy http://localhost
MailHog UI http://localhost:8025
PostgreSQL localhost:5432
Redis localhost:6379

Configuration

Environment variables (see .env.example):

Variable Description
APP_ENV development or production
DATABASE_URL PostgreSQL connection string (backend + worker)
REDIS_ADDR Redis address host:port
JWT_SECRET Secret used to sign auth JWTs (backend)
SMTP_HOST / SMTP_PORT Outbound SMTP server (MailHog in dev)
NEXT_PUBLIC_API_URL Base URL the frontend uses to reach the backend

Backend API

Built with Go and gorilla/mux. All routes are served under /api.

All endpoints except /api/health, /api/auth/signup and /api/auth/login require a Authorization: Bearer <token> header. Data is scoped per-user: each account only sees its own contacts, templates and campaigns.

Method Endpoint Description
GET /api/health Health check
POST /api/auth/signup Create an account, returns a token
POST /api/auth/login Log in, returns a token
GET /api/auth/me Current authenticated user
GET /api/contacts List the user's contacts
POST /api/contacts Add a single contact
POST /api/contacts/upload Upload contacts via CSV/Excel
DELETE /api/contacts/{id} Delete a single contact
POST /api/templates Create a template
GET /api/templates List templates
POST /api/templates/preview Render a subject/body with sample values
GET /api/templates/{id} Get a template
PUT /api/templates/{id} Update a template
DELETE /api/templates/{id} Delete a template
POST /api/campaigns Create a campaign (enqueues delivery jobs)
GET /api/campaigns List campaigns
GET /api/stats Aggregate sending stats

Worker

A standalone Go service that drains the Redis queue and delivers mail.

  • Worker pool — 20 concurrent goroutines
  • Throttling — rate limited to 100 sends/second
  • Retries — up to 3 attempts with backoff (base delay 500ms)
  • Rendering — fills templates per recipient before sending
  • Counters — updates campaign sent/failed counts in Postgres
  • Graceful shutdown — drains on SIGTERM/SIGINT

Database

PostgreSQL with versioned migrations in backend/internal/database/migrations:

  • 000001 — contacts table
  • 000002 — templates table
  • 000003 — campaigns table
  • 000004 — campaign counters
  • 000005 — users table
  • 000006 — per-user ownership (user_id on contacts/templates/campaigns)

Frontend

Next.js (App Router) with Tailwind CSS. Pages:

  • Dashboard
  • Campaigns
  • Contacts
  • Templates
  • Login

NGINX

Reverse proxy routing:

/       → frontend (Next.js)
/api/*  → backend (Go API)

Docker

All services run via Docker Compose (deployments/docker-compose.yml):

  • mailforge-frontend
  • mailforge-backend
  • mailforge-worker
  • mailforge-postgres
  • mailforge-redis
  • mailforge-mailhog
  • mailforge-nginx

CI Pipeline

GitHub Actions builds and validates the frontend, backend, and worker.


License

MIT

About

Self hosted SMTP server for mass email campaigns

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages