Messaging
Messaging System Guide
Mu includes a built-in messaging system. Direct messages between users work out of the box — no configuration needed.
This guide covers additional setup for receiving external email.
Quick Start
Direct Messages (Default)
# Works immediately, no configuration needed
./mu
Users can send messages to each other by username. Messages are stored locally.
External Email Support
# Set SMTP port (optional, defaults to 2525)
export MAIL_PORT="2525"
./mu --serve --address :8080
The SMTP server always runs to receive mail. Configure DNS MX records to route mail to your server.
Production Setup
# Use standard SMTP port
export MAIL_PORT="25"
# Set your mail domain
export MAIL_DOMAIN="yourdomain.com"
# DKIM signing (optional but recommended)
./scripts/generate-dkim-keys.sh yourdomain.com
export MAIL_SELECTOR="default"
./mu --serve --address :8080
Table of Contents
- How It Works
- Environment Variables
- SMTP Server Setup (Receiving)
- Message Delivery (Sending)
- DKIM Setup
- DNS Configuration
- Testing
- Troubleshooting
How It Works
Sending Messages
Internal recipient (username only):
To: alice
→ Stored in mail.json
→ Appears in alice's inbox
External recipient (email with @):
To: bob@gmail.com
→ Sent via SMTP
→ Copy stored in sender's sent folder
Receiving Messages
SMTP Server (when enabled):
Internet → SMTP Server (port 2525/25)
↓
Validate User Exists?
↓ Yes
Store in mail.json
↓
User's Inbox
Security:
- Not an open relay
- Only accepts mail for existing mu users
- Rejects unknown recipients with “550 User not found”
- Rate limiting:
- 10 connections per hour per IP address
- 100 messages per day per sender email
- SPF verification: Checks sender domain SPF records (logs failures, doesn’t reject)
- Blocklist: Block abusive senders by email or IP address
Anti-spam protections:
- Connection timeouts (10s read/write)
- Message size limit (10 MB)
- Recipient limit (50 per message)
- Automatic cleanup of rate limit tracking
- Admin interface for managing blocklist
Environment Variables
| Variable | Default | Description |
|---|---|---|
MAIL_PORT |
2525 |
Port for receiving mail (use 25 for production) |
MAIL_DOMAIN |
localhost |
Domain for email addresses (e.g., user@domain.com) |
MAIL_SELECTOR |
default |
DKIM selector (DNS record name) |
SMTP server always runs - no enable flag needed. Just configure DNS to route mail.
Access Control:
- Internal messaging is free for all users
- External email costs 4 credits per message (SMTP delivery cost)
- Set user roles via the admin interface
How Message Delivery Works:
- Internal messages (username only) are stored directly in the local database
- External messages (@domain) are sent via SMTP protocol to recipient mail servers using MX lookups
- DKIM signing is applied automatically if configured
- No external SMTP relay needed - direct delivery to recipient servers
SMTP Server Setup (Receiving Messages)
The messaging system uses SMTP protocol to receive messages from the internet.
Configure Port
export MAIL_PORT="2525" # Development
# export MAIL_PORT="25" # Production
Default is :2525 for local testing without requiring root privileges.
Status Messages
On startup:
smtp: Starting SMTP server (receive only) on :2525
How It Works
- Receives email from internet
- Extracts username from recipient (before @)
- Validates user exists in mu
- Stores message if valid, rejects if not
- Sender’s email preserved in message
Example:
Email to: alice@yourdomain.com
→ Looks up user: alice
→ If exists: stores message
→ If not: rejects with 550 error
Not an Open Relay
The server only accepts mail for valid local users. It cannot be used to relay spam.
Message Delivery (Sending)
The messaging system delivers messages using SMTP protocol. External messages are sent directly to recipient mail servers using MX lookups. No external relay required.
How It Works
- User sends message to external address (e.g., bob@gmail.com)
- System looks up MX records for gmail.com
- Connects directly to Gmail’s mail servers via SMTP
- Delivers message with DKIM signature (if configured)
- Stores copy in sender’s sent folder
DKIM Signing
DKIM signatures are automatically added to outbound emails if keys are configured. This improves deliverability and prevents spam filtering.
# Generate keys
./scripts/generate-dkim-keys.sh yourdomain.com
# Configure
export MAIL_DOMAIN="yourdomain.com"
export MAIL_SELECTOR="default"
No SMTP credentials needed - Direct delivery handles everything.
DKIM Setup
DKIM adds digital signatures to outbound messages to prove authenticity and improve deliverability.
Why Use DKIM?
Without DKIM:
- Emails likely go to spam
- Gmail/Yahoo mark as suspicious
- Poor deliverability
With DKIM:
- Emails reach inbox
- 70%+ better deliverability
- Professional setup
- Required for DMARC
Generate DKIM Keys
./scripts/generate-dkim-keys.sh yourdomain.com default
This creates:
~/.mu/keys/dkim.key- Private key (keep secure!)~/.mu/keys/dkim.pub- Public key (reference)- DNS TXT record output
Manual Key Generation
mkdir -p ~/.mu/keys
chmod 700 ~/.mu/keys
openssl genrsa -out ~/.mu/keys/dkim.key 2048
chmod 600 ~/.mu/keys/dkim.key
# Extract public key for DNS
openssl rsa -in ~/.mu/keys/dkim.key -pubout -outform PEM | \
grep -v "PUBLIC KEY" | tr -d '\n'
Configure DKIM
export MAIL_DOMAIN="yourdomain.com"
export MAIL_SELECTOR="default"
Note: DKIM automatically enables if keys exist at ~/.mu/keys/dkim.key. No other config needed.
Status Messages
Enabled:
dkim: DKIM signing enabled for domain yourdomain.com with selector default
Disabled:
mail: DKIM signing disabled: DKIM private key not found at ~/.mu/keys/dkim.key
DNS Configuration
MX Records (Required for Receiving)
yourdomain.com. IN MX 10 mail.yourdomain.com.
mail.yourdomain.com. IN A your.server.ip
SPF Record (Recommended)
yourdomain.com. IN TXT "v=spf1 a:mail.yourdomain.com ~all"
DKIM Record (Recommended)
default._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjAN..."
Replace MIIBIjAN... with your public key from generate-dkim-keys.sh output.
DMARC Record (Optional)
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"
Verify DNS
# Check MX
dig MX yourdomain.com
# Check SPF
dig TXT yourdomain.com
# Check DKIM
dig TXT default._domainkey.yourdomain.com
# Check DMARC
dig TXT _dmarc.yourdomain.com
Testing
Test Receiving
# Using swaks
swaks --to alice@localhost --from test@example.com \
--server localhost:2525 \
--header "Subject: Test" --body "Hello"
# Using Python
python3 << 'EOF'
import smtplib
from email.mime.text import MIMEText
msg = MIMEText("Test message")
msg['Subject'] = 'Test'
msg['From'] = 'test@example.com'
msg['To'] = 'alice@localhost'
s = smtplib.SMTP('localhost', 2525)
s.send_message(msg)
s.quit()
print("Sent!")
EOF
Test Sending
- Login to mu web interface
- Go to Mail → Compose
- Send to external address (e.g., your Gmail)
- Check recipient inbox
Verify DKIM
In Gmail:
- Open the email
- Click “Show original” (⋮ menu)
- Look for “DKIM: ‘PASS’”
Online Tools:
- https://www.mail-tester.com/
- https://dkimvalidator.com/
- Send to: check-auth@verifier.port25.com
Troubleshooting
SMTP Server Not Starting
Issue: No “Starting SMTP server” message
Check:
- Port already in use? Try a different port
- Permission issue? Port 25 requires root/capabilities
Test port availability:
lsof -i :2525
Mail to External Address Fails
Issue: “Failed to send email”
Check:
- DNS resolving MX records correctly?
- Firewall blocking outbound port 25?
- Server IP not blacklisted?
Test MX lookup:
dig +short MX gmail.com
Test connection:
telnet mx.example.com 25
DKIM Not Signing
Issue: No “DKIM signing enabled” message
Check:
- Keys exist:
ls -la ~/.mu/keys/dkim.key - Permissions:
chmod 600 ~/.mu/keys/dkim.key - Valid key format (PEM)
DKIM Fails Verification
Issue: “dkim=fail” in headers
Common causes:
- DNS not propagated - wait 1-48 hours
- Public/private key mismatch - regenerate both
- Wrong selector - must match DNS record name
- DNS format issues - no line breaks in public key
Verify DNS:
dig TXT default._domainkey.yourdomain.com +short
Emails Going to Spam
Common causes:
- Missing or invalid SPF/DKIM/DMARC records
- Low sender reputation (new domain/IP)
- Content triggers spam filters
- Rate limited by recipient server
Solutions:
- Verify all DNS records are correct
- Start with low volume, gradually increase
- Avoid spam trigger words (“free”, “click here”, etc.)
- Use proper HTML formatting
- Include unsubscribe links
Blocklist Management
Blocking Abusive Senders
Navigate to /admin/blocklist (admin access required) to manage blocked senders.
Block by email:
- Individual:
spammer@example.com - Domain wildcard:
*@spammydomain.com
Block by IP:
192.168.1.100
Effects of Blocking
When a sender or IP is blocked:
- Connection rejected immediately with SMTP 554 error
- Message: “Transaction failed: sender blocked”
- No rate limiting check performed (blocked before that)
- Logged for monitoring
Managing the Blocklist
Via Admin Interface:
- Go to
/admin/blocklist - Enter email or IP to block
- Click “Block Email” or “Block IP”
- View currently blocked entries
- Click “Unblock” to remove
Blocklist Storage:
- Stored in
~/.mu/blocklist.json - Automatically loaded on startup
- Persisted immediately when changed
Log Messages:
smtp: Rejected blocked sender: spammer@bad.com (IP: 1.2.3.4)
mail: Blocked email: spammer@bad.com
mail: Unblocked email: reformed@example.com
Solutions:
- Add DKIM signing
- Configure SPF record
- Set up DMARC
- Use proper From address (@yourdomain.com)
- Warm up IP (gradual sending increase)
- Check blacklists: https://mxtoolbox.com/blacklists.aspx
Permission Errors
# Fix DKIM key permissions
chmod 700 ~/.mu/keys
chmod 600 ~/.mu/keys/dkim.key
SMTP Server on Port 25
Issue: Permission denied
Fix: Run as root or use CAP_NET_BIND_SERVICE:
sudo setcap 'cap_net_bind_service=+ep' ./mu
Complete Production Setup
1. DNS Configuration
# Add these records to your DNS
yourdomain.com. IN MX 10 mail.yourdomain.com.
mail.yourdomain.com. IN A your.server.ip
yourdomain.com. IN TXT "v=spf1 a:mail.yourdomain.com ~all"
2. Generate DKIM Keys
./scripts/generate-dkim-keys.sh yourdomain.com default
Add the DNS TXT record from output.
3. Environment Variables
# Mail configuration
export MAIL_PORT="25"
export MAIL_DOMAIN="yourdomain.com"
export MAIL_SELECTOR="default"
4. Firewall
# Allow SMTP port
sudo ufw allow 25/tcp
5. Start Service
./mu --serve --address :8080
6. Verify
# Check logs
# Should see:
# - "DKIM signing enabled for domain yourdomain.com"
# - "Starting SMTP server (receive only) on :25"
# Test receiving
swaks --to user@yourdomain.com --from test@gmail.com \
--server yourdomain.com --header "Subject: Test"
# Test sending (via web interface)
# Send to external address, verify DKIM passes
Systemd Service
[Unit]
Description=Mu Mail Service
After=network.target
[Service]
Type=simple
User=mu
WorkingDirectory=/opt/mu
Environment="MAIL_PORT=25"
Environment="MAIL_DOMAIN=yourdomain.com"
Environment="MAIL_SELECTOR=default"
ExecStart=/opt/mu/mu --serve --address :8080
Restart=always
[Install]
WantedBy=multi-user.target
Architecture Summary
Components:
- SMTP Server: Receives mail from internet (optional, disabled by default)
- SMTP Client: Sends mail to external servers (configurable)
- Internal Storage: JSON file for all messages
Security Features:
- Recipient validation (not an open relay)
- Rate limiting (per-IP and per-sender)
- SPF verification for incoming mail
- Connection timeouts and size limits
- Automatic rate limit cleanup
- Email and IP blocking with admin interface
Message Flow:
- DKIM Signing: Optional, auto-enabled if keys present
Security:
- Authentication required for sending
- SMTP server only accepts mail for valid users
- Not an open relay
- DKIM optional but recommended
Configuration:
- All in mail.Load() - automatic on startup
- Environment variables only
- No code changes needed
See Also
- Environment Variables - All environment variables
- Generate DKIM keys:
./scripts/generate-dkim-keys.sh - Test mail: https://www.mail-tester.com/












