Skip to content

anondotli/mx

Repository files navigation

anon.li Email Server

A production-ready, secure, and privacy-focused Haraka email server for handling anonymous email forwarding.

Features

  • Anonymous Forwarding: Accepts emails for @anon.li aliases and custom domains, forwarding them to real recipients
  • Reply System: Handles replies via @reply.anon.li tokenized addresses to hide user identities
  • PGP Encryption: Automatically encrypts forwarded emails if the recipient has uploaded a public key
  • Privacy Protection: Removes tracking pixels, cleans HTML, and sanitizes dangerous content
  • SRS Support: Implements Sender Rewriting Scheme to maintain SPF compliance when forwarding
  • DKIM Signing: Signs all outbound mail to ensure deliverability
  • Rate Limiting: Redis-backed rate limiting to prevent abuse
  • Custom Domains: Supports user-verified custom domains with per-domain DKIM keys

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  External       │     │    Haraka       │     │   Next.js API   │
│  Sender         │────▶│    MTA          │────▶│   (Prisma)      │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                               │                        │
                               ▼                        ▼
                        ┌─────────────────┐     ┌─────────────────┐
                        │    Redis        │     │   PostgreSQL    │
                        │  (Rate Limit)   │     │   (Aliases)     │
                        └─────────────────┘     └─────────────────┘

Installation

Prerequisites

  • Docker and Docker Compose
  • Node.js 20+ (for local development)
  • Redis
  • Access to the Next.js frontend API

Quick Start

  1. Clone and configure:

    cp .env.example .env
    # Edit .env with your MAIL_API_SECRET
  2. Generate DKIM keys:

    ./scripts/generate-dkim.sh anon.li
    ./scripts/generate-dkim.sh reply.anon.li
  3. Add DNS records (output from script):

    default._domainkey.anon.li. IN TXT "v=DKIM1; k=rsa; p=..."
    default._domainkey.reply.anon.li. IN TXT "v=DKIM1; k=rsa; p=..."
    
  4. Place TLS certificates:

    # Place your Let's Encrypt or other TLS certs
    cat privkey.pem cert.pem chain.pem > config/tls/anon.li.pem
  5. Start the server:

    docker compose up -d --build

Configuration

Environment Variables

Variable Description Required
MAIL_API_SECRET Shared secret for API authentication Yes
FRONTEND_URL URL of Next.js API (default: http://app:3000) No
UPSTASH_REDIS_REST_URL Upstash Redis REST endpoint (rate limiting) No
UPSTASH_REDIS_REST_TOKEN Upstash Redis auth token No

Plugins

Plugin Purpose
tls STARTTLS enforcement
limit-upstash IP-based rate limiting (Redis + in-memory fallback)
mailauth Inbound SPF / DKIM / DMARC validation
rcpt_to.bounce Validates SRS bounce return-paths
rcpt_to.anonli Validates aliases + per-alias rate limiting
rcpt_to.reply Handles reply token addresses
data.loop_detect Rejects mail loops
data.tracking_remove Strips tracking pixels / UTM params
data.spam_check Spam scoring
arc.sign ARC sealing for forwarded mail
dkim.custom Per-domain DKIM signing (local keys or API-fetched)
queue.forward Main forwarding (SRS, PGP, reply rewriting)

DNS Configuration

For anon.li

; MX Record
anon.li.                IN MX   10 mx.anon.li.

; SPF
anon.li.                IN TXT  "v=spf1 mx a:mx.anon.li -all"

; DKIM (generated by script)
default._domainkey.anon.li. IN TXT "v=DKIM1; k=rsa; p=..."

; DMARC
_dmarc.anon.li.         IN TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@anon.li"

For Custom Domains

Users must add:

  1. MX record pointing to mx.anon.li
  2. SPF record including include:_spf.anon.li
  3. DKIM record (provided in dashboard)
  4. Verification TXT record

Security Features

  • TLS 1.2+ required for all connections
  • Timing-safe API secret comparison
  • Input validation on all email addresses
  • Rate limiting per IP and globally
  • DKIM/SPF/DMARC for email authentication
  • PGP encryption for enhanced privacy
  • Tracking removal for privacy protection

Monitoring

Logs are output in JSON format for easy parsing:

docker compose logs -f haraka

Health check endpoint:

nc -z localhost 25 && echo "OK"

Development

# Install dependencies
npm install

# Run locally (requires Haraka global install)
npm install -g Haraka
npm start

# Run tests
npm test

License

GNU Affero General Public License v3.0 (AGPL-3.0-only).

Because anon.li-mx is network-facing server software, the AGPL requires that anyone running a modified version on a publicly accessible server make the corresponding source code available to its users.

About

The source code for our aliasing mail server, powered by Haraka.

Topics

Resources

License

Stars

Watchers

Forks

Contributors