A complete, production-ready temporary email system similar to temp-mail.org, but fully self-hosted with admin controls, user management, and complete privacy.
- Complete Mail System: Receive emails via Postfix catch-all SMTP server
- User Management: Registration with admin approval system
- Admin Dashboard: Comprehensive control panel for system management
- Inbox Management: Users can create multiple temporary email addresses
- Email Viewer: View emails with HTML rendering and attachment support
- Auto-Cleanup: Automatic email deletion based on retention policies
- Security: Password hashing, JWT authentication, rate limiting
- Production Ready: Docker-based deployment with PostgreSQL database
- Backend: Node.js 20 + TypeScript + Express
- Frontend: React + Vite
- Database: PostgreSQL + Prisma ORM
- SMTP: Postfix (catch-all configuration)
- Auth: JWT tokens
- Deployment: Docker + Docker Compose
This project uses Node.js 20 (pinned in .nvmrc and Dockerfile) for stability and compatibility:
- Node 20 + Debian: Uses a Debian-based image (bookworm-slim) for reliable Prisma compatibility
- Prisma Engine: Works correctly with Debian-based Node.js images - no additional configuration needed
If you encounter Prisma-related issues during setup:
- Ensure you're using the exact Node version specified in
.nvmrc(20) - Run
docker-compose build --no-cache backendto rebuild with fresh dependencies - Check that Prisma client generation completes during build:
npm run prisma:generate
The Docker setup handles all version compatibility automatically - manual Node/OpenSSL configuration is not required.
- Linux server (Ubuntu 22.04+ recommended)
- Root or sudo access
- Domain name with DNS access
- Minimum 2GB RAM, 10GB disk space
- Node.js 18+ (if building locally; Docker handles this automatically)
- Clone the repository
git clone https://github.com/Leopixel1/temp-mail.git
cd temp-mail- Run the installer
sudo bash installer/install.shThe installer will:
- Check system requirements
- Install Docker and Docker Compose
- Gather configuration (domain, admin credentials, limits)
- Generate secure passwords and secrets
- Build and start all services
- Configure DNS
Add these DNS records for your domain:
Type Name Value Priority
A mail.example.com YOUR_SERVER_IP -
MX example.com mail.example.com 10
Allow required ports:
# SMTP
sudo ufw allow 25/tcp
# HTTP (or use 443 for HTTPS)
sudo ufw allow 80/tcp
# SSH (if needed)
sudo ufw allow 22/tcp
# Enable firewall
sudo ufw enableFor production use with HTTPS, set up a reverse proxy:
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d mail.example.comConfigure Nginx:
server {
listen 443 ssl http2;
server_name mail.example.com;
ssl_certificate /etc/letsencrypt/live/mail.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem;
location / {
proxy_pass http://localhost:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Nginx Proxy Manager provides a user-friendly web interface for managing reverse proxies and SSL certificates.
Installation:
# Create NPM directory
mkdir -p ~/nginx-proxy-manager
cd ~/nginx-proxy-manager
# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80' # HTTP
- '81:81' # Admin interface
- '443:443' # HTTPS
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- npm-network
networks:
npm-network:
driver: bridge
EOF
# Start NPM
docker-compose up -dNote: This basic setup uses NPM's own network. For advanced Docker network integration to directly connect NPM with Temp Mail containers, see the detailed guide.
Configuration:
NPM can be deployed in two ways:
- Same Server: NPM and Temp Mail on the same machine (requires port changes)
- External Server: NPM on a separate server (recommended, no port conflicts)
For External NPM (Different Server - Recommended):
- Access NPM admin interface at
http://your-npm-server-ip:81 - Default login:
admin@example.com/changeme(change immediately) - Click "Proxy Hosts" β "Add Proxy Host"
- Configure:
- Domain Names:
mail.example.com - Scheme:
http - Forward Hostname/IP:
tempmail-server-ip(IP address of your Temp Mail server) - Forward Port:
80(Temp Mail frontend port) - Enable "Block Common Exploits"
- Enable "Websockets Support"
- Domain Names:
- Go to "SSL" tab:
- Select "Request a new SSL Certificate"
- Enable "Force SSL"
- Enable "HTTP/2 Support"
- Agree to Let's Encrypt Terms
- Click "Save"
Note: For external NPM, keep Temp Mail on port 80. Only the NPM server needs ports 80/443/81 open. Temp Mail server only needs port 80 accessible from NPM server (can be firewalled from public).
For Same Server Deployment: If running NPM on the same server as Temp Mail, you'll need to change Temp Mail's port since both use port 80 by default:
-
Edit Temp Mail's docker-compose.yml:
frontend: ports: - "8080:80" # Change from 80:80
-
Restart Temp Mail:
docker-compose down && docker-compose up -d -
In NPM proxy host configuration, use:
- Forward Hostname/IP:
your-server-iporhost.docker.internal - Forward Port:
8080
- Forward Hostname/IP:
See docs/DEPLOYMENT.md for detailed NPM setup instructions.
- Registration: Register an account (if enabled by admin)
- Wait for Approval: Admin must approve your account
- Create Inbox: Generate temporary email addresses
- Receive Emails: All emails sent to your inbox addresses appear automatically
- Auto-Refresh: Email list refreshes every 10 seconds
- Manage: View, delete individual emails or entire inboxes
Access the admin panel at /admin after logging in with admin credentials.
- Approve/reject new registrations
- Activate/deactivate user accounts
- Set custom limits per user (inboxes, emails, retention)
- Delete user accounts
- Toggle login requirement
- Enable/disable registration
- Set default retention time
- Configure global limits
- Choose deletion behavior on limit
- View total users, inboxes, emails
- Monitor login activity
- Track emails received per day
Edit .env file to customize:
# Domain
DOMAIN=mail.example.com
# Admin Account
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=secure-password
# Email Retention (in hours)
DEFAULT_RETENTION_HOURS=72
# User Limits
MAX_INBOXES_PER_USER=5
MAX_EMAILS_PER_INBOX=50
# Registration
REGISTRATION_OPEN=false
# Security
JWT_SECRET=random-secret-keyCommon configurations:
- 10 minutes: 0.17 hours (testing/high security)
- 1 hour: 1 hour (very temporary)
- 3 hours: 3 hours (short-term)
- 24 hours: 24 hours (one day)
- 3 days: 72 hours (default, recommended)
- 7 days: 168 hours (extended)
# View logs
docker-compose logs -f
# View specific service logs
docker-compose logs -f backend
docker-compose logs -f postfix
# Restart services
docker-compose restart
# Stop services
docker-compose stop
# Start services
docker-compose start
# Rebuild and restart
docker-compose up -d --build
# Remove everything (including data!)
docker-compose down -v# Backup database
docker-compose exec postgres pg_dump -U tempmail tempmail > backup.sql
# Restore database
cat backup.sql | docker-compose exec -T postgres psql -U tempmail tempmail
# Access database console
docker-compose exec postgres psql -U tempmail tempmail# Test email reception
echo "Test email" | mail -s "Test Subject" test@mail.example.com
# Check Postfix logs
docker-compose logs -f postfix
# Check email processing
docker-compose logs -f backend | grep "Email received"βββββββββββββββ
β Internet β
ββββββββ¬βββββββ
β SMTP (Port 25)
βΌ
βββββββββββββββββββ
β Postfix β
β (Catch-All) β
ββββββββββ¬βββββββββ
β Pipe
βΌ
βββββββββββββββββββ ββββββββββββββββ
β Backend βββββββΊβ PostgreSQL β
β (Node.js) β β (Database) β
ββββββββββ¬βββββββββ ββββββββββββββββ
β HTTP API
βΌ
βββββββββββββββββββ
β Frontend β
β (React) β
βββββββββββββββββββ
β
βΌ
βββββββββββββββββββ
β User Browser β
βββββββββββββββββββ
- Password Hashing: Bcrypt with salt rounds
- JWT Authentication: Secure token-based auth
- Rate Limiting: Prevent brute force attacks
- Input Validation: Express-validator on all inputs
- SQL Injection Protection: Prisma ORM with prepared statements
- XSS Protection: Helmet.js security headers
- CORS Configuration: Controlled cross-origin access
- Email Sandboxing: iframes with sandbox attribute
For home/self-hosted deployments, configure port forwarding for:
- Port 25 (SMTP) - Required for receiving emails
- Port 80 (HTTP) - Required for web interface
- Port 443 (HTTPS) - Recommended for secure access
See the FAQ for detailed router configuration instructions.
For answers to questions about:
- Router port forwarding setup
- DNS configuration
- Installation requirements
- Security best practices
- Troubleshooting
- Backup and maintenance
- Performance optimization
See the comprehensive FAQ document for detailed answers.
Before starting services, validate your docker-compose.yml:
docker compose configThis command checks for syntax errors and shows the final configuration. If you see errors about "additional properties not allowed" or YAML syntax issues, review your docker-compose.yml file for proper indentation and structure.
- Check DNS MX records:
dig MX example.com
nslookup -type=MX example.com- Test SMTP connection:
telnet mail.example.com 25- Check Postfix logs:
docker-compose logs postfix- If you see "unknown user" or "transport lookup failure" errors:
- This indicates Postfix configuration needs rebuilding
- Solution:
docker-compose build postfix docker-compose up -d
- Note: Simply restarting (
docker-compose restart) is not sufficient after configuration changes
If emails to random addresses are bounced with "unknown user":
- Verify the configuration was applied:
docker-compose exec postfix postconf mydestination
# Should show: mydestination = localhost- Check virtual alias configuration:
docker-compose exec postfix postconf virtual_alias_domains virtual_alias_maps- Rebuild Postfix container (required after any config changes):
docker-compose build postfix
docker-compose up -d- Check PostgreSQL status:
docker-compose ps postgres- Verify connection:
docker-compose exec postgres pg_isready- Check container status:
docker-compose ps frontend- Check build logs:
docker-compose logs frontendFor more troubleshooting help, see the FAQ.
# Create backup directory
mkdir -p backups
# Backup database
docker-compose exec postgres pg_dump -U tempmail tempmail > backups/db_$(date +%Y%m%d).sql
# Backup configuration
cp .env backups/env_$(date +%Y%m%d).backupAdd to crontab:
# Daily backup at 2 AM
0 2 * * * cd /path/to/temp-mail && docker-compose exec postgres pg_dump -U tempmail tempmail > backups/db_$(date +\%Y\%m\%d).sql# Stop services
docker-compose stop
# Restore database
cat backups/db_20240101.sql | docker-compose exec -T postgres psql -U tempmail tempmail
# Start services
docker-compose startTo update to a new version:
# Pull latest changes
git pull
# Rebuild and restart all containers
docker-compose up -d --build
# Check status
docker-compose ps- Configuration changes: Always use
--buildafter pulling updates that modify Dockerfiles or Postfix configuration - Postfix updates: After any changes to
postfix/main.cf,postfix/master.cf, orpostfix/virtual_alias, you must rebuild:docker-compose build postfix docker-compose up -d
- Backend updates: After dependency or code changes:
docker-compose build backend docker-compose up -d
- Simple restarts: If only environment variables changed in
.env, restart is sufficient:docker-compose restart
- Updates preserve your database and configuration (stored in Docker volumes)
- Prisma migrations run automatically on backend startup
- Always backup your database before major updates (see Backup & Restore section)
MIT License - See LICENSE file for details
Contributions welcome! Please feel free to submit issues and pull requests.
For issues and questions:
- FAQ: See docs/FAQ.md for answers to common questions
- GitHub Issues: https://github.com/Leopixel1/temp-mail/issues
Built with modern web technologies and best practices for self-hosting enthusiasts.