Skip to content

A new kind of Email server written in GO that uses Web of Trust versus domains for server trust relationships.

License

Notifications You must be signed in to change notification settings

steowens/stevemail

Repository files navigation

SteveMail - Multi-User SMTP Server

A full-featured SMTP server with multi-user support, local delivery, and authenticated relay.

Features

  • Dual-Port Operation

    • Port 25 (SMTP): Receives mail from other servers (no authentication required)
    • Port 587 (Submission): Accepts mail from clients (requires authentication)

    Note that 25 is the no auth service and could be configured to run on any port such as 2025. Same goes for 587, e.g. 2587. Why? because if you run this at home on a DMZ, your internet provider probably blocks 25, but they can't block all the ports or Alexa would not be able to keep tabs on you. ;-}

  • Multi-User Support

    • Multiple mailboxes with individual authentication
    • Secure password hashing with bcrypt
    • Per-user email storage
  • Multi-Domain Support

    • Host multiple domains on one server
    • Configure which domains are local vs relayed
  • Smart Routing

    • Local domains → Delivered to user mailboxes
    • External domains → Relayed through upstream SMTP server
    • Automatic routing based on recipient domain
  • Authenticated Relay

    • Support for both Let's Encrypt and self-signed certificates
    • STARTTLS support for secure connections
    • Configurable TLS settings

Installation

  1. Install dependencies:

    go get github.com/joho/godotenv
    go get golang.org/x/crypto/bcrypt
    go get github.com/emersion/go-smtp
    go get modernc.org/sqlite
  2. Create configuration:

    cp .env.example .env
    # Edit .env with your settings

Configuration

Basic Setup (.env file)

# Server Ports
SMTP_ADDR=0.0.0.0
SMTP_PORT=25                  # Incoming mail from other servers
SUBMISSION_ADDR=0.0.0.0
SUBMISSION_PORT=587           # Outgoing mail from your clients

# Your domain
SMTP_DOMAIN=mail.example.com

# Database
DB_PATH=./stevemail.db

# Relay for external domains
RELAY_HOST=smtp.gmail.com
RELAY_PORT=587
RELAY_USERNAME=[email protected]
RELAY_PASSWORD=your-app-password
RELAY_USE_TLS=true
RELAY_USE_LETSENCRYPT=true

Setting Up Domains and Users

Add a local domain:

go run cmd/mailctl/main.go domain:add example.com true

Add users:

go run cmd/mailctl/main.go user:add [email protected] password123
go run cmd/mailctl/main.go user:add [email protected] password456

List configuration:

go run cmd/mailctl/main.go domain:list
go run cmd/mailctl/main.go user:list

Usage

Start the Server

go run cmd/smtpserver/main.go

The server will listen on:

  • Port 25 - For receiving mail from other mail servers (no auth)
  • Port 587 - For sending mail from your email client (requires auth)

Email Client Configuration

Configure your email client (Thunderbird, Outlook, etc.):

Outgoing Mail (SMTP):

  • Server: localhost (or your server IP)
  • Port: 587
  • Security: STARTTLS (or None for testing)
  • Authentication: Normal password
  • Username: [email protected]
  • Password: password123

How Mail Routing Works

  1. User sends email via port 587:

  2. Server routes the email:

  3. Other servers send to port 25:

    • No authentication required
    • Email delivered to local mailboxes if domain exists
    • Otherwise rejected or relayed (based on configuration)

Architecture

                    ┌─────────────────────┐
                    │   Email Clients     │
                    │  (Thunderbird, etc) │
                    └──────────┬──────────┘
                               │
                      Port 587 │ (Auth Required)
                               ↓
                    ┌─────────────────────┐
                    │   SteveMail Server  │
                    │                     │
                    │  ┌───────────────┐  │
                    │  │ Port 25 (SMTP)│  │←── Other Mail Servers
                    │  │  No Auth      │  │    (No Auth)
                    │  └───────────────┘  │
                    │                     │
                    │  ┌───────────────┐  │
                    │  │Port 587 (Sub) │  │
                    │  │  Auth Required│  │
                    │  └───────────────┘  │
                    │                     │
                    │  ┌───────────────┐  │
                    │  │  Local DB     │  │
                    │  │  (Mailboxes)  │  │
                    │  └───────────────┘  │
                    └──────────┬──────────┘
                               │
                               ↓
                    ┌─────────────────────┐
                    │  Upstream SMTP      │
                    │  (Gmail, etc)       │
                    │  For External Mail  │
                    └─────────────────────┘

Database Schema

Users Table:

  • Email, username, domain, password_hash
  • Each user has their own mailbox

Domains Table:

  • Domain name, is_local flag
  • Determines routing (local vs relay)

Emails Table:

  • Email content, headers, raw data
  • Linked to mailbox_id for per-user storage

Security Notes

For Production:

  1. Use TLS certificates (Let's Encrypt)
  2. Enable STARTTLS on port 587
  3. Consider SPF, DKIM, and DMARC records
  4. Firewall port 25 from untrusted sources
  5. Use strong passwords for users
  6. Regular database backups

For Testing:

  • Ports 2525/2587 don't require admin/root
  • Can run without TLS for local testing

Troubleshooting

Port 25 requires root/admin:

# Option 1: Use higher ports for testing
SMTP_PORT=2525
SUBMISSION_PORT=2587

# Option 2: Run as admin/root (production)
sudo go run cmd/smtpserver/main.go

Authentication failing:

  • Check user exists: go run cmd/mailctl/main.go user:list
  • Verify password is correct
  • Check client is connecting to port 587

Mail not being relayed:

  • Verify RELAY_HOST is set in .env
  • Check relay credentials are correct
  • Test relay server is accessible

Testing

Send test email using telnet (port 587 with auth):

telnet localhost 587
EHLO localhost
AUTH PLAIN
# Base64 encoded: \[email protected]\0password123
AGFsaWNlQGV4YW1wbGUuY29tAHBhc3N3b3JkMTIz
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
DATA
Subject: Test
From: [email protected]
To: [email protected]

Test message body.
.
QUIT

Query emails from database:

sqlite3 stevemail.db "SELECT id, from_address, to_addresses, subject, received_at FROM emails ORDER BY received_at DESC LIMIT 10;"

Development

Project Structure:

stevemail/
├── cmd/
│   ├── smtpserver/     # Main SMTP server
│   └── mailctl/        # Management CLI
├── internal/
│   ├── config/         # Configuration
│   ├── models/         # Data models
│   ├── smtp/           # SMTP implementation
│   └── storage/        # Database layer
└── .env                # Configuration file

License

CC BY-NC-ND License SEE LICENSE FILE

About

A new kind of Email server written in GO that uses Web of Trust versus domains for server trust relationships.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •