A production-ready, secure, and privacy-focused Haraka email server for handling anonymous email forwarding.
- Anonymous Forwarding: Accepts emails for
@anon.lialiases and custom domains, forwarding them to real recipients - Reply System: Handles replies via
@reply.anon.litokenized 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
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ External │ │ Haraka │ │ Next.js API │
│ Sender │────▶│ MTA │────▶│ (Prisma) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Redis │ │ PostgreSQL │
│ (Rate Limit) │ │ (Aliases) │
└─────────────────┘ └─────────────────┘
- Docker and Docker Compose
- Node.js 20+ (for local development)
- Redis
- Access to the Next.js frontend API
-
Clone and configure:
cp .env.example .env # Edit .env with your MAIL_API_SECRET -
Generate DKIM keys:
./scripts/generate-dkim.sh anon.li ./scripts/generate-dkim.sh reply.anon.li
-
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=..." -
Place TLS certificates:
# Place your Let's Encrypt or other TLS certs cat privkey.pem cert.pem chain.pem > config/tls/anon.li.pem
-
Start the server:
docker compose up -d --build
| 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 |
| 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) |
; 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"
Users must add:
- MX record pointing to
mx.anon.li - SPF record including
include:_spf.anon.li - DKIM record (provided in dashboard)
- Verification TXT record
- 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
Logs are output in JSON format for easy parsing:
docker compose logs -f harakaHealth check endpoint:
nc -z localhost 25 && echo "OK"# Install dependencies
npm install
# Run locally (requires Haraka global install)
npm install -g Haraka
npm start
# Run tests
npm testGNU 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.