Skip to content

A high-performance, production-ready IMAP server powering Cybertemp's email retrieval infrastructure. Built with Rust for speed, security, and reliability.

License

Notifications You must be signed in to change notification settings

sexfrance/IMAP-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📬 Cybertemp IMAP Server

A high-performance, production-ready IMAP server powering Cybertemp's email retrieval infrastructure. Built with Rust for speed, security, and reliability.

💬 Discord · 📜 ChangeLog · ⚠️ Report Bug · 💡 Request Feature


📖 Table of Contents


📚 About

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

This is the actual IMAP server currently powering Cybertemp - enabling users to access their temporary and private emails through standard IMAP clients like Thunderbird, Apple Mail, Outlook, and mobile email apps.

This server is designed as a secure IMAP retrieval server that:

  • Listens on port 143 (standard IMAP) or custom port
  • Authenticates users via token-based authentication with Supabase
  • Retrieves emails from PostgreSQL database
  • Supports subscription-based access control
  • Implements domain whitelisting and email/sender banning
  • Handles CREATE/DELETE inbox operations
  • Provides FETCH, SEARCH, LIST, and SELECT commands
  • Built with async Tokio for concurrent connections
  • Filters banned senders in real-time

🏗️ Architecture

🏗️ Architecture

┌─────────────────────┐
│  IMAP Client        │
│  (Thunderbird,      │
│   Apple Mail, etc)  │
└──────────┬──────────┘
           │ Port 143
           ▼
┌───────────────────────────────────────┐
│   Rust IMAP Server (Tokio)            │
│  - Token authentication                │
│  - Subscription validation             │
│  - Concurrent connection handler       │
│  - Email retrieval & filtering         │
│  - Inbox management (CREATE/DELETE)    │
│  - Ban list enforcement                │
└──────────┬────────────────────────────┘
           │
           ├──────────────┬──────────────┐
           ▼              ▼              ▼
┌──────────────┐ ┌────────────────┐ ┌─────────────┐
│  PostgreSQL  │ │   Supabase     │ │   Caching   │
│  (Emails,    │ │  - Auth        │ │  (Domains)  │
│   Inboxes,   │ │  - Tokens      │ │             │
│   Domains,   │ │  - Users       │ │             │
│   Bans)      │ │                │ │             │
└──────────────┘ └────────────────┘ └─────────────┘

Self-hosted mode: When USE_SUPABASE_BANS=false and USE_SUPABASE_DOMAINS=false, PostgreSQL handles domains and bans locally. Inboxes are always stored in PostgreSQL.


🔥 Features

  • Production-Ready: Currently serving Cybertemp's IMAP infrastructure
  • Token-Based Auth: Secure authentication using IMAP tokens
  • Subscription Control: Validates active subscriptions before access
  • Standard IMAP Commands: LOGIN, LIST, SELECT, FETCH, SEARCH, STATUS, NOOP, LOGOUT
  • Inbox Management: CREATE and DELETE mailboxes via IMAP
  • Domain Validation: Cached domain checking with 60s refresh
  • Ban System: Real-time sender/email/domain banning with exact/contains matching
  • Multipart MIME: Proper text extraction from multipart messages
  • Quoted-Printable: Automatic decoding of encoded content
  • Concurrent Connections: Async Tokio runtime for multiple clients
  • PostgreSQL Storage: Reliable email retrieval with indexing
  • Supabase Integration: Auth, users, domains, bans (optional for self-hosting) (optional for self-hosting)
  • Self-hosted Mode: Optional PostgreSQL-only operation without external dependencies
  • HTTP Request Filtering: Rejects HTTP requests to IMAP port
  • Subdomain Support: Create inboxes on parent and child domains
  • Graceful Error Handling: Detailed logging with tracing

📋 Prerequisites

  • Rust 1.70+ (for compilation)
  • PostgreSQL 12+ (for email storage and optional self-hosted features)
    • Supabase Account (optional, for authentication and advanced features)
  • Linux/Windows/macOS (any platform supporting Rust)
  • Port 143 Access (standard IMAP port, or use custom port)

⚙️ Installation

Using Rust

  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/imap-server.git
    cd imap-server
  3. Build the project:

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

🔧 Configuration

Create a .env file in the project root with the following variables:

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

# Supabase Configuration (OPTIONAL - set to false for self-hosted)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-service-role-key-here

# Self-hosted toggles (OPTIONAL - default true for backward compatibility)
USE_SUPABASE_BANS=true
USE_SUPABASE_DOMAINS=true

# IMAP Server Settings (OPTIONAL)
IMAP_BIND=0.0.0.0:143                    # Default: 0.0.0.0:143

Environment Variables Explained

Variable Required Description
DATABASE_URL ✅ Yes PostgreSQL connection string for retrieving emails
SUPABASE_URL ❌ No Your Supabase project URL (optional)
SUPABASE_SERVICE_KEY ❌ No Supabase service role key (optional)
USE_SUPABASE_BANS ❌ No Use Supabase for bans (default: true)
USE_SUPABASE_DOMAINS ❌ No Use Supabase for domains (default: true)
IMAP_BIND ❌ No IMAP bind address (default: 0.0.0.0:143)

💾 Database Setup

PostgreSQL Schema

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

psql -U postgres < SQL/schema.sql

This creates:

  • emails table with columns:
    • id (UUID primary key)
    • mailbox_owner (email address owning the inbox)
    • mailbox (mailbox name, default 'INBOX')
    • subject, body, html
    • from_addr, to_addrs
    • timestamp, flags, size
    • created_at
  • inbox table (for self-hosted inbox management):
    • id (UUID primary key)
    • email_address (TEXT, unique)
    • user_id (UUID, nullable)
    • created_at (TIMESTAMPTZ)
  • domains table (for self-hosted domain management):
    • id (UUID primary key)
    • domain (TEXT)
    • user_id (UUID)
    • active (BOOLEAN)
    • cloudflare_domain (BOOLEAN)
    • created_at (TIMESTAMPTZ)
  • bans table (for self-hosted ban management):
    • id (UUID primary key)
    • scope ('email', 'domain', 'sender')
    • value (TEXT)
    • match_type ('exact' or 'contains')
    • status ('active' or 'inactive')
    • created_at (TIMESTAMPTZ)
  • Indexes on mailbox_owner, mailbox, timestamp, and other tables

Supabase Tables (Optional)

If using Supabase for advanced features (USE_SUPABASE_*=true), create these tables in your Supabase project:

1. imap_tokens table (Authentication)

CREATE TABLE imap_tokens (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  token TEXT NOT NULL UNIQUE,
  expires_at TIMESTAMPTZ NOT NULL,
  last_used_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_imap_tokens_token ON imap_tokens(token);
CREATE INDEX idx_imap_tokens_user_id ON imap_tokens(user_id);

2. users table (Subscription Management)

CREATE TABLE users (
  id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  subscription_status TEXT DEFAULT 'inactive',  -- 'active', 'trialing', 'past_due', 'inactive'
  subscription_end_date TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

3. domains table (Domain Whitelist)

CREATE TABLE domains (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  domain TEXT NOT NULL,
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  active BOOLEAN DEFAULT true,
  cloudflare_domain BOOLEAN DEFAULT false,  -- Global domain accessible by all users
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_domains_user_id ON domains(user_id);
CREATE INDEX idx_domains_domain ON domains(domain);

4. inbox table (User Inboxes)

CREATE TABLE inbox (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  email_address TEXT NOT NULL UNIQUE,
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_inbox_user_id ON inbox(user_id);
CREATE INDEX idx_inbox_email ON inbox(email_address);

5. bans table (Email/Domain/Sender Blocking)

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

CREATE INDEX idx_bans_scope_status ON bans(scope, status);

Example bans:

-- Block specific sender
INSERT INTO bans (scope, value, match_type, status) VALUES
  ('sender', 'spammer@example.com', 'exact', 'active');

-- Block any sender containing 'spam'
INSERT INTO bans (scope, value, match_type, status) VALUES
  ('sender', 'spam', 'contains', 'active');

-- Block entire domain
INSERT INTO bans (scope, value, match_type, status) VALUES
  ('domain', 'spamhaus.com', 'exact', 'active');

-- Block specific email address from being created
INSERT INTO bans (scope, value, match_type, status) VALUES
  ('email', 'admin@yourdomain.com', 'exact', 'active');

🚀 Running the Server

Development Mode

cargo run

Production Mode

cargo build --release
./target/release/imap-server

Running on Port 143 (Linux)

Port 143 requires root privileges:

# Option 1: Run as root
sudo ./target/release/imap-server

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

# Option 3: Use alternative port
IMAP_BIND=0.0.0.0:1143 ./target/release/imap-server

Running as a Service (Systemd)

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

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

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

[Install]
WantedBy=multi-user.target

Enable and start:

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

📨 IMAP Commands

Supported Commands

Command Description Example
CAPABILITY List server capabilities CAPABILITY
LOGIN Authenticate with email and token LOGIN user@domain.com your-imap-token
LIST List all mailboxes (inboxes) for authenticated user LIST "" "*"
SELECT Select a mailbox to work with SELECT inbox@domain.com
FETCH Retrieve email content FETCH 1 (BODY[])
SEARCH Search emails in selected mailbox SEARCH ALL
STATUS Get mailbox statistics STATUS "inbox@domain.com" (MESSAGES)
CREATE Create a new inbox CREATE newbox@domain.com
DELETE Delete an inbox DELETE oldbox@domain.com
NOOP No operation (keep-alive) NOOP
LOGOUT Close connection LOGOUT

Command Examples

FETCH Examples

# Fetch entire message body
FETCH 1 (BODY[])

# Fetch text part only (peek without marking as seen)
FETCH 1 (BODY.PEEK[TEXT])

# Fetch multiple messages
FETCH 1:5 (BODY[])

# Fetch all messages
FETCH 1:* (BODY[])

SEARCH Examples

# Search all emails
SEARCH ALL

# Search by sender
SEARCH FROM "sender@example.com"

# Search by subject
SEARCH SUBJECT "Important"

🔐 Authentication

How Authentication Works

  1. User generates IMAP token in Cybertemp web interface
  2. Token is stored in Supabase imap_tokens table with expiration
  3. User connects via IMAP client using:
    • Username: user@example.com
    • Password: generated-imap-token
  4. Server validates:
    • Token exists and hasn't expired
    • Token belongs to the provided email
    • User has active subscription (active, trialing, or past_due with future end date)
  5. Access granted if all checks pass
  6. Last used timestamp updated on successful login

Subscription Status

The IMAP server enforces subscription checks:

  • Active: Full access
  • Trialing: Full access (trial period)
  • ⚠️ Past Due: Access granted if subscription_end_date is in the future
  • Inactive/Canceled: Access denied

Users must have an active subscription to use IMAP.


⚠️ Important Notes

Domain Ownership & Validation

  • Users can only create inboxes on domains they own (linked via user_id in domains table)
  • Cloudflare domains (cloudflare_domain = true) are accessible by all users
  • Subdomains are supported: If user owns example.com, they can create anything@sub.example.com
  • Domains must be active (active = true) to allow inbox creation
  • Domain cache refreshes every 60 seconds for performance

Ban System

The server implements a 3-tier ban system:

  1. Email bans (scope=email): Prevents specific email addresses from being created
  2. Domain bans (scope=domain): Blocks mailbox creation on banned domains
  3. Sender bans (scope=sender or legacy scope=email): Filters emails from banned senders in FETCH/SEARCH

Match types:

  • exact: Must match exactly (case-insensitive)
  • contains: Blocks if value is substring of sender/email/domain

Legacy support: Old format contains:value in ban value is automatically normalized.

Security Features

  • HTTP request rejection: Rejects HTTP requests sent to IMAP port
  • Echoed response filtering: Ignores client-echoed server responses
  • Subscription validation: Enforces active subscription requirement
  • Token expiration: Tokens have expiration dates
  • User isolation: Users can only see their own inboxes
  • Domain ownership: Users can only create inboxes on their domains
  • Real-time bans: Sender bans applied during email retrieval

Performance Optimizations

  • Connection pooling: PostgreSQL connection pool for efficiency
  • Domain caching: 60-second cache to reduce Supabase queries
  • Concurrent handling: Tokio async runtime for multiple simultaneous clients
  • Indexed queries: Database indexes on mailbox_owner, timestamp

🛠️ Troubleshooting

Common Issues

1. "Failed to connect to database"

Check:

# Verify PostgreSQL is running
systemctl status postgresql  # Linux
# or
pg_ctl status  # Windows/macOS

# Test connection
psql -U admin -d cybertemp -c "SELECT 1;"

# Verify DATABASE_URL format
echo $DATABASE_URL  # Should be: postgresql://user:pass@host:port/dbname

2. "Invalid IMAP token" or "IMAP token has expired"

Solution:

  • Generate a new token in Cybertemp web interface
  • Check imap_tokens table for token existence and expires_at
  • Verify token hasn't been deleted
-- Check token in Supabase
SELECT * FROM imap_tokens WHERE token = 'your-token';

3. "Your subscription is not active"

Check:

-- Verify user subscription status
SELECT u.id, u.subscription_status, u.subscription_end_date, au.email
FROM users u
JOIN auth.users au ON u.id = au.id
WHERE au.email = 'user@example.com';

Fix: Update subscription status to active or trialing:

UPDATE users SET subscription_status = 'active' WHERE id = 'user-uuid';

4. "Domain not found or not active"

Check:

-- Verify domain exists and is active
SELECT * FROM domains WHERE domain = 'yourdomain.com';

Fix: Add domain or activate it:

-- Add domain
INSERT INTO domains (domain, user_id, active, cloudflare_domain)
VALUES ('yourdomain.com', 'user-uuid', true, false);

-- Or activate existing domain
UPDATE domains SET active = true WHERE domain = 'yourdomain.com';

5. "Permission denied" binding to port 143

Solution:

# Linux: Grant capability
sudo setcap CAP_NET_BIND_SERVICE=+eip ./target/release/imap-server

# Or use non-privileged port
export IMAP_BIND=0.0.0.0:1143
./target/release/imap-server

6. "No mailboxes found" in email client

Check:

  • User is authenticated correctly
  • inbox table has entries for the user:
SELECT * FROM inbox WHERE user_id = 'user-uuid';
  • Create an inbox manually:
INSERT INTO inbox (email_address, user_id)
VALUES ('test@yourdomain.com', 'user-uuid');

7. Client shows connection but no emails

Check:

  • Emails exist in PostgreSQL for the selected mailbox:
SELECT COUNT(*) FROM emails WHERE mailbox_owner = 'inbox@domain.com';
  • Check if sender is banned:
SELECT * FROM bans WHERE scope IN ('sender', 'email') AND status = 'active';

8. "Mailbox is banned" when creating inbox

Solution: Check if email address is explicitly banned:

SELECT * FROM bans WHERE scope = 'email' AND value = 'your-inbox@domain.com';

Remove the ban if necessary:

DELETE FROM bans WHERE id = 'ban-uuid';
-- or deactivate
UPDATE bans SET status = 'inactive' WHERE id = 'ban-uuid';

Enable Debug Logging

RUST_LOG=debug ./target/release/imap-server

This provides detailed logs for:

  • Authentication attempts
  • Token validation
  • Subscription checks
  • Domain lookups
  • Email retrieval
  • Ban filtering

📊 Development Status

Component Status Notes
Rust Implementation Production Actively maintained
Token Authentication ✅ Production Stable and secure
Subscription Validation ✅ Production Enforces active subscriptions
PostgreSQL Storage ✅ Production Stable and indexed
Supabase Integration ✅ Production Auth, users, domains, inboxes, bans
Domain Caching ✅ Production 60s refresh cycle
Ban System ✅ Production Email, domain, sender filtering
IMAP Commands ✅ Production LOGIN, LIST, SELECT, FETCH, SEARCH, etc
Inbox Management ✅ Production CREATE/DELETE via IMAP
MIME Parsing ✅ Production Multipart, quoted-printable support
Concurrent Connections ✅ Production Tokio async runtime
Documentation ✅ Complete You're reading it!

📜 ChangeLog

v0.1.0 ⋮ 11/01/2025
! Initial production release for Cybertemp IMAP
+ Token-based authentication with Supabase
+ Subscription validation (active, trialing, past_due)
+ Domain validation with caching (60s refresh)
+ Ban system (email, domain, sender with exact/contains matching)
+ IMAP commands: LOGIN, LIST, SELECT, FETCH, SEARCH, STATUS
+ Inbox management: CREATE/DELETE via IMAP
+ Multipart MIME parsing with text extraction
+ Quoted-printable decoding
+ Subdomain support for inbox creation
+ HTTP request filtering
+ PostgreSQL email storage with indexing
+ Concurrent connection handling with Tokio
+ Real-time sender ban filtering in FETCH/SEARCH
+ Last used timestamp tracking for tokens
+ Graceful error handling and logging
+ Self-hosted mode support (optional PostgreSQL-only operation)

📞 Support


📄 License

MIT License - See LICENSE file for details


🙏 Acknowledgments

  • Built with ❤️ for the Cybertemp community
  • Powered by Rust 🦀, Tokio, PostgreSQL, and Supabase
  • IMAP RFC 3501 compliant (subset)

⭐ Star this repo if you found it helpful!
Currently powering Cybertemp's IMAP infrastructure 📬

About

A high-performance, production-ready IMAP server powering Cybertemp's email retrieval infrastructure. Built with Rust for speed, security, and reliability.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages