Privacy-first, token-based temporary email service — No registration, no passwords, just instant disposable emails.
A blazing-fast, fully-featured self-hosted temporary email service with real-time inbox updates, DKIM-signed outbound emails, comprehensive REST API, WebSocket support, and a beautiful dark-themed dashboard. Built for developers, privacy enthusiasts, and anyone who wants instant disposable email addresses without the hassle.
████████╗███████╗███╗ ███╗██████╗ ███╗ ███╗ █████╗ ██╗██╗ ██████╗ ██████╗ ██████╗
╚══██╔══╝██╔════╝████╗ ████║██╔══██╗████╗ ████║██╔══██╗██║██║ ██╔══██╗██╔══██╗██╔═══██╗
██║ █████╗ ██╔████╔██║██████╔╝██╔████╔██║███████║██║██║ ██████╔╝██████╔╝██║ ██║
██║ ██╔══╝ ██║╚██╔╝██║██╔═══╝ ██║╚██╔╝██║██╔══██║██║██║ ██╔═══╝ ██╔══██╗██║ ██║
██║ ███████╗██║ ╚═╝ ██║██║ ██║ ╚═╝ ██║██║ ██║██║███████╗ ██║ ██║ ██║╚██████╔╝
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
:: p r i v a c y _ f i r s t ::
🎯 Token-based authentication — No email/password required. Get a 40-character token and start receiving emails instantly.
✨ Real-time inbox — Watch emails arrive live via WebSocket streaming. No refresh needed.
🔐 DKIM-signed outbound — Send emails from your temp addresses with proper email authentication (SPF, DKIM, DMARC).
📊 Analytics dashboard — Track API usage, token consumption, and error rates in real-time.
🌐 Multi-domain support — Use multiple subdomains for different purposes.
| Feature | TempMail Pro 🦾 | Free Services 🖐️ | Paid Solutions 💸 |
|---|---|---|---|
| No registration required | ✅ | Sometimes | ❌ |
| Token-based auth (no password) | ✅ | ❌ | ❌ |
| Real-time WebSocket updates | ✅ | ❌ | Sometimes |
| Send emails (DKIM signed) | ✅ | ❌ | ✅ |
| Multiple domains | ✅ | Limited | ✅ |
| REST API + API Keys | ✅ | Limited | ✅ |
| Self-hosted, full control | ✅ | ❌ | ❌ |
| Webhooks | ✅ | ❌ | ✅ |
| Analytics dashboard | ✅ | ❌ | ✅ |
| Open source | ✅ | ❌ | ❌ |
| Dark cyberpunk UI 😎 | ✅ | ❌ | ❌ |
| Cost | $0 | Free/Limited | $10-$100/mo |
- 🎯 Instant email creation — Random or custom addresses across multiple domains
- 📥 Real-time inbox — WebSocket-powered live updates (no polling!)
- 📤 Outbound email — Send DKIM-signed emails from your temp addresses
- 🔍 Full-text search — Search through all your emails
- ⭐ Star & label — Organize important emails with custom labels
- 📎 Attachments — Full attachment support with secure storage
- 🗑️ Bulk operations — Select and delete/mark-read multiple emails
- 📧 Email forwarding — Forward incoming mail to your real address
- 🤖 Auto-reply — Set up vacation responders per email address
- 🎫 Token-based auth — 40-character tokens, no passwords needed
- 🔑 Multiple API Keys — Generate multiple keys with different scopes
- 🛡️ Rate limiting — Built-in protection against abuse
- 📊 Usage tracking — Monitor your daily API usage (200,000 calls/day default)
- 🔒 IP whitelisting — Restrict API keys to specific IPs
- 🔐 2FA Support — Optional TOTP two-factor authentication
- 📈 Usage charts — Visualize API calls over time (hourly/daily/weekly)
- 🎯 Endpoint analytics — See which endpoints are most used
- ❌ Error tracking — Monitor and debug failed requests
- 🔄 Real-time updates — Live dashboard metrics via WebSocket
- 🌍 Geo tracking — See where your API calls originate
- 🪝 Webhook support — Get notified when emails arrive
- 🔏 HMAC signatures — Secure webhook payloads with X-Signature header
- 📄 OpenAPI spec — Full OpenAPI 3.0 documentation
- 🔌 Multiple API keys — Create keys with different permissions
- 📥 Export options — Download emails as .eml or .zip
- 🌑 Dark theme default — Easy on the eyes, cyberpunk aesthetic
- ☀️ Light theme — Toggle with system preference detection
- ⚡ Fast & responsive — React-powered SPA with Vite
- 📱 Mobile-friendly — Fully responsive design
- ✨ Animations — Smooth Framer Motion transitions
- ⌨️ Keyboard shortcuts — Power user navigation (r=refresh, c=create, /=search)
- 🎯 Command palette — Quick actions with Cmd+K / Ctrl+K
┌─────────────────────────────┐
│ React Dashboard (Vite) │
│ • Real-time inbox │
│ • Analytics charts │
│ • Dark cyberpunk UI │
└──────────────┬──────────────┘
│ REST + WebSocket
│
┌──────────────────┐ ┌────────────────▼────────────────┐
│ SMTP Server │ │ Express.js Backend │
│ (Port 2525) │◄────────────►│ • JWT + API Key auth │
│ • Receive mail │ Internal │ • Token management │
│ • Parse MIME │ │ • WebSocket broadcaster │
│ • Store to DB │ │ • DKIM signing │
└──────────────────┘ └────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ PostgreSQL │
│ • tokens, emails, messages │
│ • api_logs, webhooks │
│ • Full-text search indexes │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Redis │
│ • Session cache │
│ • Rate limiting │
│ • Real-time pub/sub │
└─────────────────────────────────┘
- VPS/Server with public IP (Ubuntu 20.04+ recommended)
- Node.js 18+
- PostgreSQL 14+
- Redis 6+
- Domain with DNS access (for MX records)
- Nginx (reverse proxy + SSL)
git clone https://github.com/vikrant-project/tempmail-pro.git
cd tempmail-pro# System packages
sudo apt update
sudo apt install -y nodejs npm postgresql redis-server nginx certbot python3-certbot-nginx
# Enable services
sudo systemctl enable --now postgresql redis-server nginx# Create database and user
sudo -u postgres psql << EOF
CREATE USER mailtemp WITH PASSWORD 'YourSecurePassword123!';
CREATE DATABASE mailtemp_db OWNER mailtemp;
GRANT ALL PRIVILEGES ON DATABASE mailtemp_db TO mailtemp;
EOF# Backend configuration
cp backend/.env.example backend/.env
nano backend/.env
# Frontend configuration
cp frontend/.env.example frontend/.env
nano frontend/.envBackend .env:
NODE_ENV=production
PORT=3001
JWT_SECRET=your-super-secret-jwt-key-change-this-to-random-string
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mailtemp_db
DB_USER=mailtemp
DB_PASSWORD=YourSecurePassword123!
REDIS_HOST=localhost
REDIS_PORT=6379
SMTP_PORT=2525
DAILY_TOKEN_LIMIT=200000
EMAIL_RETENTION_DAYS=1
DOMAIN=yourdomain.com
SUBDOMAINS=temp,mail,inboxFrontend .env:
VITE_API_URL=https://api.yourdomain.com/apimkdir -p dkim
openssl genrsa -out dkim/private.key 2048
openssl rsa -in dkim/private.key -pubout -out dkim/public.key
# Get the public key for DNS TXT record (remove headers and newlines)
echo "Add this to DNS as TXT record for default._domainkey.yourdomain.com:"
cat dkim/public.key | grep -v "PUBLIC KEY" | tr -d "\n"cd backend
npm install
node migrate.jscd ../frontend
npm install -g yarn
yarn install
yarn build# Install PM2 globally
npm install -g pm2
# Start API server (clustered for performance)
pm2 start ecosystem.config.js
# Start SMTP server
pm2 start backend/smtp-server.js --name mailtemp-smtp
# Save and setup startup script
pm2 save
pm2 startup# Redirect port 25 to 2525 (allows running without root)
sudo iptables -t nat -A PREROUTING -p tcp --dport 25 -j REDIRECT --to-port 2525
sudo iptables-save > /etc/iptables.rules
# Make persistent
echo 'iptables-restore < /etc/iptables.rules' | sudo tee /etc/rc.local
sudo chmod +x /etc/rc.localReplace yourdomain.com and YOUR_SERVER_IP with your actual values.
| Type | Name | Value | Proxy | Notes |
|---|---|---|---|---|
| A | temp | YOUR_SERVER_IP | On (if Cloudflare) | Main UI subdomain |
| A | mail.temp | YOUR_SERVER_IP | Off (DNS only) | MX target - MUST be gray cloud! |
| A | api | YOUR_SERVER_IP | On (if Cloudflare) | API subdomain |
| MX | temp | mail.temp.yourdomain.com | - | Priority 10 |
| TXT | temp | v=spf1 ip4:YOUR_SERVER_IP ~all |
- | SPF record |
| TXT | _dmarc.temp | v=DMARC1; p=none; rua=mailto:admin@yourdomain.com |
- | DMARC |
| TXT | default._domainkey | v=DKIM1; k=rsa; p=YOUR_PUBLIC_KEY |
- | DKIM |
To add additional domains (e.g., inbox.yourdomain.com, mail.yourdomain.com):
- Add A records for the subdomain and
mail.subdomain - Add MX record pointing to
mail.subdomain.yourdomain.com - Add SPF, DKIM, DMARC TXT records for the subdomain
- Update
SUBDOMAINSin backend.env - Restart the backend:
pm2 reload mailtemp-api
| Subdomain | Proxy Status | Reason |
|---|---|---|
| temp | Proxied (orange) ✅ | Frontend UI |
| api | Proxied (orange) ✅ | Backend API |
| mail.temp | DNS only (gray) |
MX target - SMTP needs direct IP |
Create /etc/nginx/sites-available/tempmail:
# API Backend
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
# WebSocket support
proxy_read_timeout 86400;
}
}
# Frontend UI
server {
listen 443 ssl http2;
server_name temp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/temp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/temp.yourdomain.com/privkey.pem;
root /home/ubuntu/tempmail-pro/frontend/dist;
index index.html;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name temp.yourdomain.com api.yourdomain.com;
return 301 https://$server_name$request_uri;
}Enable the site and get SSL certificates:
sudo ln -s /etc/nginx/sites-available/tempmail /etc/nginx/sites-enabled/
sudo nginx -t
sudo certbot --nginx -d api.yourdomain.com -d temp.yourdomain.com --non-interactive --agree-tos --email admin@yourdomain.com
sudo systemctl reload nginxOption 1: Bearer Token (Session-based)
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://api.yourdomain.com/api/v1/email/listOption 2: API Key
curl -H "X-API-Key: mtak_your_api_key_here" \
https://api.yourdomain.com/api/v1/email/list| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/signup |
Generate new 40-char token |
| POST | /api/v1/auth/login |
Login with token, get JWT |
| Method | Endpoint | Tokens | Description |
|---|---|---|---|
| POST | /api/v1/email/create |
5 | Create temp email address |
| GET | /api/v1/email/list |
0 | List all your email addresses |
| DELETE | /api/v1/email/:id |
2 | Delete an email address |
| Method | Endpoint | Tokens | Description |
|---|---|---|---|
| GET | /api/v1/email/:id/messages |
1 | Get inbox (list view) |
| GET | /api/v1/email/:id/messages/:msgId |
1 | Get full message |
| PATCH | /api/v1/email/:id/messages/:msgId/read |
0 | Mark read/unread |
| Method | Endpoint | Tokens | Description |
|---|---|---|---|
| POST | /api/v1/mail/send |
5 | Send DKIM-signed email |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/keys |
List your API keys |
| POST | /api/v1/keys/create |
Create new API key |
| DELETE | /api/v1/keys/:id |
Revoke an API key |
| POST | /api/v1/keys/:id/rotate |
Rotate key secret |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/analytics/usage |
Usage statistics |
| GET | /api/v1/analytics/endpoints |
Top endpoints |
| GET | /api/v1/analytics/errors |
Error breakdown |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/webhooks |
List webhooks |
| POST | /api/v1/webhooks |
Create webhook |
| DELETE | /api/v1/webhooks/:id |
Delete webhook |
| POST | /api/v1/webhooks/:id/test |
Test webhook |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/docs/endpoints |
API catalog (public) |
| GET | /api/v1/docs/openapi.json |
OpenAPI 3.0 spec |
# Create a token
TOKEN=$(curl -s -X POST https://api.yourdomain.com/api/v1/auth/signup | jq -r '.token')
echo "Your token: $TOKEN"
# Login and get JWT
JWT=$(curl -s -X POST https://api.yourdomain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d "{\"token\":\"$TOKEN\"}" | jq -r '.session_token')
# Create an email address
curl -X POST https://api.yourdomain.com/api/v1/email/create \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"type":"random","subdomain":"temp"}'
# List emails
curl https://api.yourdomain.com/api/v1/email/list \
-H "Authorization: Bearer $JWT"
# Send an email
curl -X POST https://api.yourdomain.com/api/v1/mail/send \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"emailId":1,"to":"recipient@example.com","subject":"Hello","body":"Test message"}'const API_URL = 'https://api.yourdomain.com/api/v1';
// Create token
const signupRes = await fetch(`${API_URL}/auth/signup`, { method: 'POST' });
const { token } = await signupRes.json();
// Login
const loginRes = await fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token })
});
const { session_token } = await loginRes.json();
// Create email
const emailRes = await fetch(`${API_URL}/email/create`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${session_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ type: 'random', subdomain: 'temp' })
});
const { email } = await emailRes.json();
console.log(`Your temp email: ${email.address}`);import requests
API_URL = 'https://api.yourdomain.com/api/v1'
# Create token
token = requests.post(f'{API_URL}/auth/signup').json()['token']
# Login
session = requests.post(f'{API_URL}/auth/login', json={'token': token}).json()
jwt = session['session_token']
# Create email
headers = {'Authorization': f'Bearer {jwt}'}
email = requests.post(
f'{API_URL}/email/create',
headers=headers,
json={'type': 'random', 'subdomain': 'temp'}
).json()['email']
print(f"Your temp email: {email['address']}")
# Check inbox
messages = requests.get(
f'{API_URL}/email/{email["id"]}/messages',
headers=headers
).json()package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
const apiURL = "https://api.yourdomain.com/api/v1"
func main() {
// Create token
resp, _ := http.Post(apiURL+"/auth/signup", "application/json", nil)
var signup map[string]string
json.NewDecoder(resp.Body).Decode(&signup)
token := signup["token"]
// Login
body, _ := json.Marshal(map[string]string{"token": token})
resp, _ = http.Post(apiURL+"/auth/login", "application/json", bytes.NewBuffer(body))
var login map[string]string
json.NewDecoder(resp.Body).Decode(&login)
jwt := login["session_token"]
fmt.Printf("JWT: %s\n", jwt)
}# Install swaks (Swiss Army Knife for SMTP)
sudo apt install swaks
# Send test email
swaks --to test123@temp.yourdomain.com \
--from sender@example.com \
--server mail.temp.yourdomain.com \
--port 25 \
--header "Subject: Test Email" \
--body "This is a test message"# Check SPF record
dig TXT temp.yourdomain.com +short
# Check DKIM record
dig TXT default._domainkey.yourdomain.com +short
# Check DMARC record
dig TXT _dmarc.temp.yourdomain.com +short
# Full email authentication check
# Send email from your temp address to a Gmail account
# In Gmail, click "Show original" to see authentication results
# Look for: SPF=PASS, DKIM=PASS, DMARC=PASScurl https://api.yourdomain.com/api/v1/health
# Expected: {"status":"ok","timestamp":"..."}# View PM2 logs
pm2 logs mailtemp-api
pm2 logs mailtemp-smtp
# View nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log# Backup database
pg_dump -U mailtemp mailtemp_db > backup_$(date +%Y%m%d).sql
# Automated daily backup (add to crontab)
0 2 * * * pg_dump -U mailtemp mailtemp_db | gzip > /home/ubuntu/backups/db_$(date +\%Y\%m\%d).sql.gzcd /home/ubuntu/tempmail-pro
git pull origin main
# Backend
cd backend && npm install
pm2 reload mailtemp-api
# Frontend
cd ../frontend && yarn install && yarn buildThe system automatically cleans up expired emails. To manually trigger:
# Run cleanup
curl -X POST https://api.yourdomain.com/api/v1/admin/cleanup \
-H "Authorization: Bearer ADMIN_JWT"| Component | Technology |
|---|---|
| Backend | Node.js 20, Express.js 4.x, Socket.IO |
| Frontend | React 18, Vite 5, TailwindCSS, Framer Motion |
| Database | PostgreSQL 14+ with full-text search |
| Cache | Redis 6+ |
| smtp-server, nodemailer, mailparser | |
| Process Manager | PM2 (cluster mode) |
| Web Server | Nginx (reverse proxy + SSL) |
| SSL | Let's Encrypt (certbot) |
| DNS/CDN | Cloudflare (optional) |
tempmail-pro/
├── backend/
│ ├── server.js # Main Express app
│ ├── smtp-server.js # SMTP receiver (port 2525)
│ ├── api-v2.js # API v2 routes
│ ├── api-extra.js # Additional API endpoints
│ ├── migrate.js # Database migrations
│ ├── migrations/ # SQL migration files
│ └── .env.example # Environment template
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Main React app
│ │ ├── App.css # Styles (dark theme)
│ │ ├── AnalyticsPage.jsx
│ │ └── components/ # Reusable components
│ ├── package.json
│ ├── vite.config.js
│ └── .env.example
├── dkim/
│ ├── private.key # DKIM private key (generate this)
│ └── public.key # DKIM public key (for DNS)
├── docs/
│ └── screenshots/ # Documentation images
├── ecosystem.config.js # PM2 configuration
├── LICENSE # MIT License
└── README.md # This file
- ✅ JWT tokens with configurable expiration
- ✅ Rate limiting (1000 req/min default, configurable)
- ✅ API key scopes — limit what each key can do
- ✅ IP whitelisting — restrict API keys to specific IPs
- ✅ CORS configured for specific domains only
- ✅ Helmet.js security headers
- ✅ Input validation on all endpoints
- ✅ HMAC signatures on webhook payloads
- Use strong secrets — Generate random JWT_SECRET (64+ chars)
- Enable 2FA — For admin accounts
- Regular backups — Automated daily database backups
- Monitor logs — Watch for suspicious activity
- Keep updated — Regular security updates
Direct SMTP from VPS IPs often gets flagged. For better deliverability:
- Use SMTP relay (SendGrid, Mailgun, Amazon SES)
- Warm up IP gradually over weeks
- Proper PTR record — Reverse DNS must match server hostname
- Monitor blacklists — Check MXToolbox regularly
- Low volume — Don't send bulk from temp mail service
- Check MX record is pointing to correct hostname
- Ensure mail.* subdomain is DNS only (gray cloud) if using Cloudflare
- Check port 25 is open:
nc -zv mail.temp.yourdomain.com 25 - Check SMTP logs:
pm2 logs mailtemp-smtp
- Verify
CORS_ORIGINSin backend.envincludes your frontend domain - Check nginx isn't adding duplicate CORS headers
- Ensure API subdomain SSL certificate is valid
- Verify nginx proxy settings include WebSocket headers
- Check
proxy_read_timeoutis high enough (86400) - Verify Socket.IO origins include your domain
- Check SPF, DKIM, DMARC records are correct
- Verify DKIM signature in sent emails
- Check IP reputation on MXToolbox
- Consider using SMTP relay service
Contributions are welcome! Here's how you can help:
- 🔌 SMTP relay integration (SendGrid, Mailgun, SES)
- 📊 More analytics visualizations
- 📱 Mobile app (React Native)
- 🌍 Internationalization (i18n)
- 🧪 Test coverage (Jest, Playwright)
- 📚 Documentation improvements
- 🐛 Bug fixes
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
# Clone your fork
git clone https://github.com/YOUR_USERNAME/tempmail-pro.git
cd tempmail-pro
# Install dependencies
cd backend && npm install
cd ../frontend && yarn install
# Start development servers
# Terminal 1: Backend
cd backend && npm run dev
# Terminal 2: Frontend
cd frontend && yarn devThis project is licensed under the MIT License - see the LICENSE file for details.
- smtp-server — SMTP server for Node.js
- nodemailer — Email sending
- mailparser — Email parsing
- Socket.IO — Real-time communication
- React — UI framework
- Vite — Build tool
- TailwindCSS — Styling
- Framer Motion — Animations
If this project helped you, please give it a ⭐ — it helps others discover it!
Privacy is not optional, it's a right.
Built with ☕ caffeine, 🌑 dark mode, and a passion for privacy.