Skip to content

A high-performance, production-ready SMTP receive-only server powering Cybertemp's temporary and private email infrastructure. Built with Rust for speed, reliability, and concurrency.

License

Notifications You must be signed in to change notification settings

sexfrance/SMTP-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

3 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš€ Cybertemp SMTP Server

A high-performance, production-ready SMTP receive-only server powering Cybertemp's temporary and private email infrastructure. Built with Rust for speed, reliability, and concurrency.

๐Ÿ’ฌ Discord ยท ๐Ÿ“œ ChangeLog ยท โš ๏ธ Report Bug ยท ๐Ÿ’ก Request Feature


๐Ÿ“– Table of Contents


๐Ÿ“š About

THIS README IS ENTIRLY GENERATED BY AI I DID NOT WRITE THIS SHIT

This is the actual SMTP server currently powering Cybertemp - a temporary email service handling thousands of emails daily. The codebase is functional and battle-tested in production, though the code quality could use some refactoring (it works, but it's a bit messy ).

This server is designed as a receive-only SMTP server that:

  • Accepts incoming emails on port 25 (or custom port)
  • Stores temporary emails in PostgreSQL
  • Manages inboxes in PostgreSQL (self-hosted)
  • Supports private email accounts (optional feature used by Cybertemp)
  • Implements domain whitelisting and email/domain banning (optional Supabase integration)
  • Handles concurrent connections efficiently with Tokio async runtime

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Incoming SMTP  โ”‚
โ”‚   Port 25/2525  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Rust SMTP Server (Tokio)      โ”‚
โ”‚  - Concurrent connection handler โ”‚
โ”‚  - Email parsing (mailparse)     โ”‚
โ”‚  - Domain whitelist checking     โ”‚
โ”‚  - Ban list filtering            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ–ผ                 โ–ผ                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   PostgreSQL    โ”‚ โ”‚   PostgreSQL โ”‚ โ”‚  Heartbeat   โ”‚
โ”‚  (Temp Emails)  โ”‚ โ”‚   (Inboxes)  โ”‚ โ”‚  Monitoring  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”ฅ Features

  • โœ… Production-Ready: Currently handling Cybertemp's email traffic
  • โœ… High Performance: Async Rust with Tokio for concurrent connections and super fast
  • โœ… Dual Email System: Supports both temporary and private emails
  • โœ… Domain Whitelisting: Accept emails only for configured domains
  • โœ… Ban System: Block emails from specific senders/domains
  • โœ… MIME Parsing: Proper handling of plain text and HTML emails
  • โœ… PostgreSQL Storage: Reliable email storage with indexing
  • โœ… Self-hosted Inboxes: Automatic inbox management in PostgreSQL
  • โœ… Connection Pooling: Efficient database connections
  • โœ… Queue Management: Prevents server overload with request limits
  • โœ… Heartbeat Monitoring: Optional uptime monitoring endpoint
  • โœ… Real-time Domain Updates: Polls for domain/ban updates every 30-60s
  • โœ… Graceful Error Handling: Detailed logging with tracing

๐Ÿ“‹ Prerequisites

  • Rust 1.70+ (for compilation)
  • PostgreSQL 12+ (for email storage and inbox management)
  • Linux/Windows/macOS (any platform supporting Rust)
  • Port 25 Access (or alternative SMTP port - requires root/admin on Linux for port 25)

โš™๏ธ Installation

Using Rust (Recommended - Active Development)

โš ๏ธ Note: The JavaScript version is NOT MAINTAINED. Use the Rust implementation in the rust/ directory.

  1. Install Rust (if not already installed):

    # Linux/macOS
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
    # Windows
    # Download from https://rustup.rs/
  2. Clone the repository:

    git clone https://github.com/sexfrance/smtp-server.git
    cd smtp-server/rust
  3. Build the project:

    # Development build
    cargo build
    
    # Production build (optimized)
    cargo build --release

๐Ÿ”ง Configuration

Create a .env file in the rust/ directory with the following variables:

# PostgreSQL Database (REQUIRED)
DATABASE_URL=postgresql://username:password@localhost:5432/cybertemp

# SMTP Server Settings (OPTIONAL)
SMTP_RECEIVE_PORT=25                    # Default: 25 (use 2525 for non-root testing)

# Heartbeat Monitoring (OPTIONAL)
HEARTBEAT_URL=https://your-monitoring-service.com/ping

Environment Variables Explained

Variable Required Default Description
DATABASE_URL โœ… Yes - PostgreSQL connection string for storing emails
SMTP_RECEIVE_PORT โŒ No 25 SMTP port (default: 25)
HEARTBEAT_URL โŒ No - Uptime monitoring ping URL
USE_SUPABASE_BANS โŒ No true Enable/disable Supabase ban system
USE_SUPABASE_DOMAINS โŒ No true Enable/disable Supabase domain whitelist

๐Ÿ’พ Database Setup

PostgreSQL Schema

Run the SQL schema located in rust/SQL/schema.sql:

psql -U your_user -d cybertemp -f rust/SQL/schema.sql

This creates:

  • emails table - stores all temporary emails
  • inbox table - stores inbox information (self-hosted)
  • private_email table - optional private email accounts (see below)
  • Necessary indexes for performance

Optional Supabase Tables (for advanced features)

If you want to use domain whitelisting and ban management, create these tables in Supabase:

1. domains table (Domain Whitelist - Optional)

CREATE TABLE domains (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  domain TEXT NOT NULL UNIQUE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Add your domains
INSERT INTO domains (domain) VALUES
  ('cybertemp.xyz'),
  ('temp-mail.xyz'),
  ('*.example.com');  -- Wildcard support

2. bans table (Email/Domain Blocking - Optional)

CREATE TABLE bans (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  scope TEXT NOT NULL,           -- 'email' or 'domain'
  value TEXT NOT NULL,            -- email address or domain
  match_type TEXT DEFAULT 'exact', -- 'exact' or 'contains'
  status TEXT DEFAULT 'active',   -- 'active' or 'inactive'
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Example bans
INSERT INTO bans (scope, value, match_type, status) VALUES
  ('email', 'spam@example.com', 'exact', 'active'),
  ('email', 'spam', 'contains', 'active'),  -- Blocks any email containing "spam"
  ('domain', 'spammer.com', 'exact', 'active');

Note: If you don't create these Supabase tables, set USE_SUPABASE_BANS=false and USE_SUPABASE_DOMAINS=false in your .env file. The server will accept all domains and have no bans by default.


๐Ÿš€ Running the Server

Development Mode

cd rust
cargo run

Production Mode

cd rust
cargo build --release
./target/release/cybertemp_smtp

Running on Port 25 (Linux)

Port 25 requires root privileges:

# Option 1: Run as root
sudo ./target/release/cybertemp_smtp

# Option 2: Grant port binding capability (recommended)
sudo setcap CAP_NET_BIND_SERVICE=+eip ./target/release/cybertemp_smtp
./target/release/cybertemp_smtp

Running as a Service (Systemd)

Create /etc/systemd/system/cybertemp-smtp.service:

[Unit]
Description=Cybertemp SMTP Server
After=network.target postgresql.service

[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/smtp-server/rust
EnvironmentFile=/path/to/smtp-server/rust/.env
ExecStart=/path/to/smtp-server/rust/target/release/cybertemp_smtp
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable cybertemp-smtp
sudo systemctl start cybertemp-smtp
sudo systemctl status cybertemp-smtp

๐Ÿ” How It Works

Email Flow

  1. Connection: External SMTP server connects to port 25
  2. SMTP Handshake: Server responds with 220 Cybertemp Mail Receiver
  3. Domain Check: Recipient domain is validated against whitelist
  4. Ban Check: Sender and domain are checked against ban list
  5. Email Receipt: Server accepts email data until . terminator
  6. Parsing: Email is parsed using mailparse crate
  7. Storage Decision:
    • If recipient is in private_email table โ†’ Store in PostgreSQL emails table
    • Otherwise โ†’ Store in PostgreSQL as temporary email + create PostgreSQL inbox entry
  8. Response: Server responds with 250 Ok: Message accepted

Domain Whitelisting

The server only accepts emails for domains listed in the configured domain source (Supabase domains table if enabled, otherwise accepts all domains). This prevents abuse and unauthorized usage.

Wildcard support:

  • example.com - matches exactly example.com
  • *.example.com - matches mail.example.com, temp.example.com, etc.

Automatic updates: Domain list is refreshed every 60 seconds.

Ban System

Protects against spam and abuse:

  • Email bans: Block specific sender addresses
    • exact match: Must match exactly
    • contains match: Blocks if sender contains substring
  • Domain bans: Block entire sending domains
  • Real-time updates: Ban list refreshes every 30 seconds

โš ๏ธ Important Notes

About Private Emails (privatemail.sql)

โš ๏ธ The private_email table is ONLY used by Cybertemp for paid features and is NOT required for basic SMTP functionality.

What it does:

  • Allows specific email addresses to have persistent storage
  • Adds an extra layer of security with passwords
  • Used for Cybertemp's paid private email accounts
  • Completely optional for self-hosted deployments

How to remove it:

  1. Delete or ignore rust/SQL/privatemail.sql
  2. Remove the private email check in main.rs (lines ~409-447):
    // Remove this entire block:
    match sqlx::query("SELECT id FROM private_email WHERE email = $1 LIMIT 1")
        .bind(&recipient_email)
        .fetch_optional(postgres_pool)
        .await
    {
        // ... entire private email handling logic
    }

Code Quality Disclaimer

โš ๏ธ This codebase is functional but not prettily written. It's a working production system that evolved organically. Known issues:

  • Long functions that should be split up
  • Some error handling could be more elegant
  • Duplicate code in fallback paths
  • Comment clutter from debugging sessions

But it works reliably and handles thousands of emails daily for Cybertemp. Refactoring PRs welcome! ๐Ÿ˜„

JavaScript Version

โš ๏ธ The javascript/ folder is NOT MAINTAINED - it was an early prototype. Use the Rust version for all deployments.


๐Ÿ› ๏ธ Troubleshooting

Common Issues

1. "mismatched types - expected &str, found &Result<String, VarError>"

Problem: Environment variable not being unwrapped properly.

Solution: Make sure .env file exists and contains required variables. The error occurs when env::var() fails.

// Fix by adding .expect() or ?
let database_url = env::var("DATABASE_URL")
    .expect("DATABASE_URL must be set in .env file");

2. "Failed to connect to PostgreSQL"

Check:

  • PostgreSQL is running: systemctl status postgresql
  • Database exists: psql -l | grep cybertemp
  • Credentials are correct in DATABASE_URL
  • Schema is initialized: psql -d cybertemp -c "\dt"

3. "Failed to load domains from Supabase" (if using Supabase features)

Check:

  • Supabase URL is correct (https://your-project.supabase.co)
  • Service role key is correct (NOT anon key)
  • domains table exists in Supabase
  • Network connectivity to Supabase

4. "Permission denied" binding to port 25

Solution:

# Option 1: Run as root
sudo ./target/release/cybertemp_smtp

# Option 2: Grant capability (Linux only)
sudo setcap CAP_NET_BIND_SERVICE=+eip ./target/release/cybertemp_smtp

# Option 3: Use alternative port
SMTP_RECEIVE_PORT=2525 ./target/release/cybertemp_smtp

5. Emails not appearing in database

Check logs for:

  • Domain whitelist rejections
  • Ban list rejections
  • Database insertion errors
  • Parsing errors

Enable debug logging:

RUST_LOG=debug ./target/release/cybertemp_smtp

๐Ÿ“Š Development Status

Component Status Notes
Rust Implementation โœ… Active Production-ready, actively maintained
JavaScript Implementation โŒ Abandoned Not maintained, use Rust version
PostgreSQL Storage โœ… Production Stable and tested
Self-hosted Inboxes โœ… Production No external dependencies
Supabase Integration โš ๏ธ Optional For advanced features only
Private Email Feature โš ๏ธ Optional Cybertemp-specific, not required
Code Quality โš ๏ธ Needs Refactoring Works but messy
Documentation โœ… Complete You're reading it!

๐Ÿ“œ ChangeLog

v0.3.0 โ‹ฎ 11/01/2025
+ Comprehensive documentation rewrite
+ Clarified private email feature is optional
+ Added extensive troubleshooting guide
+ Documented Supabase table schemas
+ Added systemd service configuration

v0.2.0 โ‹ฎ 09/2024
+ Ban system implementation (email/domain blocking)
+ Real-time domain whitelist updates
+ Improved MIME parsing with fallbacks
+ Connection queue management
+ Heartbeat monitoring support

v0.1.0 โ‹ฎ 06/2024
! Initial production deployment for Cybertemp
+ PostgreSQL storage implementation
+ Supabase integration
+ Domain whitelisting
+ Private email support
+ Async Tokio runtime

๐Ÿ“ž Support


๐Ÿ“„ License

MIT License - See LICENSE file for details


๐Ÿ™ Acknowledgments

  • Built with โค๏ธ for the Cybertemp community
  • Powered by Rust ๐Ÿฆ€, Tokio, and PostgreSQL
  • Optional Supabase integration for advanced features

โญ Star this repo if you found it helpful!
Currently powering Cybertemp's email infrastructure ๐Ÿš€

About

A high-performance, production-ready SMTP receive-only server powering Cybertemp's temporary and private email infrastructure. Built with Rust for speed, reliability, and concurrency.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published