init
This commit is contained in:
183
QUICK_START.md
Normal file
183
QUICK_START.md
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
# Quick Start Guide
|
||||||
|
|
||||||
|
## Prerequisites Checklist
|
||||||
|
|
||||||
|
Before running the setup script, ensure you have:
|
||||||
|
|
||||||
|
- [ ] Fresh Ubuntu 20.04+ or Debian 11+ server
|
||||||
|
- [ ] Root access to the server
|
||||||
|
- [ ] Domain name (e.g., `example.com`)
|
||||||
|
- [ ] Subdomain for mail server (e.g., `mail.example.com`)
|
||||||
|
- [ ] DNS A record: `mail.example.com` → Your server IP
|
||||||
|
- [ ] DNS MX record: `example.com` → `mail.example.com`
|
||||||
|
- [ ] Server ports 25, 587, 465, 143, 993, 110, 995, 80, 443 accessible
|
||||||
|
|
||||||
|
## Quick Installation
|
||||||
|
|
||||||
|
1. **Download the setup script:**
|
||||||
|
```bash
|
||||||
|
wget https://raw.githubusercontent.com/your-repo/setup-email-server.sh
|
||||||
|
chmod +x setup-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Run as root:**
|
||||||
|
```bash
|
||||||
|
sudo ./setup-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Follow the prompts to enter:**
|
||||||
|
- Domain name (e.g., `example.com`)
|
||||||
|
- Hostname (e.g., `mail.example.com`)
|
||||||
|
- Admin email
|
||||||
|
- Database password
|
||||||
|
- PostfixAdmin setup password
|
||||||
|
|
||||||
|
4. **Wait for completion** (15-30 minutes)
|
||||||
|
|
||||||
|
## Post-Installation Steps
|
||||||
|
|
||||||
|
### 1. Add DNS Records
|
||||||
|
|
||||||
|
Copy the DNS records displayed at the end of the script:
|
||||||
|
|
||||||
|
```dns
|
||||||
|
; SPF Record
|
||||||
|
example.com. IN TXT "v=spf1 mx ~all"
|
||||||
|
|
||||||
|
; DMARC Record
|
||||||
|
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
|
||||||
|
|
||||||
|
; DKIM Record (copy from script output)
|
||||||
|
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configure PostfixAdmin
|
||||||
|
|
||||||
|
1. Visit: `https://mail.example.com/postfixadmin/setup.php`
|
||||||
|
2. Enter the setup password you created
|
||||||
|
3. Create admin user
|
||||||
|
4. Login at: `https://mail.example.com/postfixadmin/`
|
||||||
|
|
||||||
|
### 3. Create Your First Domain and Mailbox
|
||||||
|
|
||||||
|
1. In PostfixAdmin, add your domain (`example.com`)
|
||||||
|
2. Create a mailbox (e.g., `user@example.com`)
|
||||||
|
3. Test by sending an email
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run the test script:
|
||||||
|
```bash
|
||||||
|
./test-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
Set up automated maintenance:
|
||||||
|
```bash
|
||||||
|
# Add to crontab
|
||||||
|
sudo crontab -e
|
||||||
|
|
||||||
|
# Add these lines:
|
||||||
|
0 2 * * * /path/to/maintenance-email-server.sh
|
||||||
|
0 5 1 * * /path/to/backup-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Client Configuration
|
||||||
|
|
||||||
|
### IMAP Settings:
|
||||||
|
- **Server:** mail.example.com
|
||||||
|
- **Port:** 993
|
||||||
|
- **Security:** SSL/TLS
|
||||||
|
- **Authentication:** Normal password
|
||||||
|
|
||||||
|
### SMTP Settings:
|
||||||
|
- **Server:** mail.example.com
|
||||||
|
- **Port:** 587
|
||||||
|
- **Security:** STARTTLS
|
||||||
|
- **Authentication:** Normal password
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues:
|
||||||
|
|
||||||
|
1. **Can't connect to PostfixAdmin:**
|
||||||
|
- Check Apache status: `systemctl status apache2`
|
||||||
|
- Verify SSL certificate: `openssl s_client -connect mail.example.com:443`
|
||||||
|
|
||||||
|
2. **Email not sending:**
|
||||||
|
- Check Postfix status: `systemctl status postfix`
|
||||||
|
- View logs: `tail -f /var/log/mail.log`
|
||||||
|
- Test SMTP: `telnet localhost 25`
|
||||||
|
|
||||||
|
3. **Email not receiving:**
|
||||||
|
- Check MX record: `dig MX example.com`
|
||||||
|
- Check firewall: `ufw status`
|
||||||
|
- Test port 25: `telnet mail.example.com 25`
|
||||||
|
|
||||||
|
4. **DKIM issues:**
|
||||||
|
- Test DKIM: `opendkim-testkey -d example.com -s mail -vvv`
|
||||||
|
- Check DNS: `dig TXT mail._domainkey.example.com`
|
||||||
|
|
||||||
|
### Log Files:
|
||||||
|
- Main mail log: `/var/log/mail.log`
|
||||||
|
- Setup log: `/var/log/email-server-setup.log`
|
||||||
|
- Apache error log: `/var/log/apache2/error.log`
|
||||||
|
|
||||||
|
### Useful Commands:
|
||||||
|
```bash
|
||||||
|
# Check all services
|
||||||
|
systemctl status postfix dovecot amavis spamassassin clamav-daemon opendkim apache2
|
||||||
|
|
||||||
|
# Test configuration
|
||||||
|
postfix check
|
||||||
|
dovecot -n
|
||||||
|
|
||||||
|
# Check mail queue
|
||||||
|
mailq
|
||||||
|
|
||||||
|
# Flush mail queue
|
||||||
|
postqueue -f
|
||||||
|
|
||||||
|
# Check disk space
|
||||||
|
df -h
|
||||||
|
|
||||||
|
# View active connections
|
||||||
|
ss -tulpn | grep :25
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Recommendations
|
||||||
|
|
||||||
|
1. **Keep system updated:**
|
||||||
|
```bash
|
||||||
|
apt update && apt upgrade -y
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Monitor logs regularly:**
|
||||||
|
```bash
|
||||||
|
tail -f /var/log/mail.log | grep -i error
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Backup regularly:**
|
||||||
|
```bash
|
||||||
|
./backup-email-server.sh --include-mail
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test SSL certificates:**
|
||||||
|
```bash
|
||||||
|
openssl x509 -in /etc/letsencrypt/live/mail.example.com/fullchain.pem -noout -dates
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Monitor disk space:**
|
||||||
|
```bash
|
||||||
|
df -h /var/mail/vhosts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
1. Run the test script: `./test-email-server.sh`
|
||||||
|
2. Check the setup log: `/var/log/email-server-setup.log`
|
||||||
|
3. Use online testing tools:
|
||||||
|
- [MX Toolbox](https://mxtoolbox.com/)
|
||||||
|
- [Mail Tester](https://www.mail-tester.com/)
|
||||||
|
- [DKIM Validator](https://dkimvalidator.com/)
|
||||||
309
README.md
Normal file
309
README.md
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
# Email Server Setup Script
|
||||||
|
|
||||||
|
This script automatically sets up a complete email server with the following components:
|
||||||
|
|
||||||
|
- **Postfix** - SMTP server for sending/receiving emails
|
||||||
|
- **Dovecot** - IMAP/POP3 server for email retrieval
|
||||||
|
- **PostgreSQL** - Database backend for virtual domains and users
|
||||||
|
- **PostfixAdmin** - Web interface for managing domains and mailboxes
|
||||||
|
- **Amavis** - Content filter for spam and virus scanning
|
||||||
|
- **SpamAssassin** - Spam filtering
|
||||||
|
- **ClamAV** - Antivirus scanning
|
||||||
|
- **OpenDKIM** - DKIM signing for email authentication
|
||||||
|
- **Let's Encrypt** - SSL/TLS certificates for secure connections
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Fresh Ubuntu/Debian server** (tested on Ubuntu 20.04/22.04)
|
||||||
|
2. **Root access** to the server
|
||||||
|
3. **Domain name** pointing to your server
|
||||||
|
4. **Hostname** (e.g., mail.yourdomain.com) with A record pointing to server IP
|
||||||
|
5. **Ports 25, 587, 465, 110, 995, 143, 993, 80, 443** open in firewall
|
||||||
|
|
||||||
|
## DNS Prerequisites
|
||||||
|
|
||||||
|
Before running the script, ensure you have these DNS records:
|
||||||
|
|
||||||
|
```
|
||||||
|
A mail.yourdomain.com [Your Server IP]
|
||||||
|
MX yourdomain.com mail.yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. **Download the script:**
|
||||||
|
```bash
|
||||||
|
wget https://raw.githubusercontent.com/your-repo/setup-email-server.sh
|
||||||
|
chmod +x setup-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Run the script as root:**
|
||||||
|
```bash
|
||||||
|
sudo ./setup-email-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Provide the required information when prompted:**
|
||||||
|
- Domain name (e.g., yourdomain.com)
|
||||||
|
- Hostname (e.g., mail.yourdomain.com)
|
||||||
|
- Admin email address
|
||||||
|
- PostgreSQL password for postfix user
|
||||||
|
- PostfixAdmin setup password
|
||||||
|
|
||||||
|
## Post-Installation Steps
|
||||||
|
|
||||||
|
### 1. Add DNS Records
|
||||||
|
|
||||||
|
After the script completes, add these DNS records:
|
||||||
|
|
||||||
|
#### SPF Record
|
||||||
|
```
|
||||||
|
TXT yourdomain.com "v=spf1 mx ~all"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### DMARC Record
|
||||||
|
```
|
||||||
|
TXT _dmarc.yourdomain.com "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### DKIM Record
|
||||||
|
The script will display the DKIM DNS record. Add it to your DNS:
|
||||||
|
```
|
||||||
|
TXT mail._domainkey.yourdomain.com "v=DKIM1; k=rsa; p=..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Complete PostfixAdmin Setup
|
||||||
|
|
||||||
|
1. Visit `https://mail.yourdomain.com/postfixadmin/setup.php`
|
||||||
|
2. Enter the setup password you provided during installation
|
||||||
|
3. Create an admin user
|
||||||
|
4. Login to PostfixAdmin at `https://mail.yourdomain.com/postfixadmin/`
|
||||||
|
|
||||||
|
### 3. Create Domains and Mailboxes
|
||||||
|
|
||||||
|
1. Add your domain in PostfixAdmin
|
||||||
|
2. Create mailboxes for your users
|
||||||
|
3. Test email functionality
|
||||||
|
|
||||||
|
## Multiple Domain Support
|
||||||
|
|
||||||
|
This email server fully supports unlimited virtual domains. Each domain can have its own mailboxes, aliases, quotas, and DKIM signing.
|
||||||
|
|
||||||
|
### Adding Additional Domains
|
||||||
|
|
||||||
|
#### Method 1: Using the Helper Script (Recommended)
|
||||||
|
```bash
|
||||||
|
# Add DKIM support for a new domain
|
||||||
|
sudo ./add-domain.sh newdomain.com
|
||||||
|
|
||||||
|
# This will:
|
||||||
|
# - Generate DKIM keys
|
||||||
|
# - Update OpenDKIM configuration
|
||||||
|
# - Display DNS records to add
|
||||||
|
# - Show PostfixAdmin setup instructions
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Method 2: Manual Process
|
||||||
|
1. **Add domain via PostfixAdmin:**
|
||||||
|
- Login to PostfixAdmin
|
||||||
|
- Go to "Domain List" → "New Domain"
|
||||||
|
- Enter domain details and save
|
||||||
|
|
||||||
|
2. **Configure DKIM for the domain:**
|
||||||
|
```bash
|
||||||
|
sudo ./add-domain.sh newdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Add DNS records for the new domain:**
|
||||||
|
```
|
||||||
|
MX newdomain.com mail.yourmainhost.com
|
||||||
|
TXT newdomain.com "v=spf1 mx ~all"
|
||||||
|
TXT _dmarc.newdomain.com "v=DMARC1; p=none; rua=mailto:dmarc@newdomain.com"
|
||||||
|
TXT mail._domainkey.newdomain.com "v=DKIM1; k=rsa; p=..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Managing Multiple Domains
|
||||||
|
|
||||||
|
Use the domain management script for comprehensive domain operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all configured domains
|
||||||
|
sudo ./manage-domains.sh list
|
||||||
|
|
||||||
|
# Show detailed information for a domain
|
||||||
|
sudo ./manage-domains.sh show example.com
|
||||||
|
|
||||||
|
# Test domain configuration (DNS, DKIM, etc.)
|
||||||
|
sudo ./manage-domains.sh test example.com
|
||||||
|
|
||||||
|
# Add a new domain
|
||||||
|
sudo ./manage-domains.sh add newdomain.com
|
||||||
|
|
||||||
|
# Remove a domain (WARNING: deletes all data)
|
||||||
|
sudo ./manage-domains.sh remove olddomain.com
|
||||||
|
|
||||||
|
# Show overall server status
|
||||||
|
sudo ./manage-domains.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Application SMTP for Multiple Domains
|
||||||
|
|
||||||
|
Applications can send from any configured domain using the same SMTP server:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Example: Send from different domains
|
||||||
|
domains = ['company.com', 'mysite.org', 'shop.net']
|
||||||
|
|
||||||
|
for domain in domains:
|
||||||
|
smtp_config = {
|
||||||
|
'host': 'mail.yourmainhost.com',
|
||||||
|
'port': 587,
|
||||||
|
'username': f'noreply@{domain}',
|
||||||
|
'password': 'domain_specific_password'
|
||||||
|
}
|
||||||
|
# Send email using this configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
- **SSL/TLS encryption** for all connections
|
||||||
|
- **DKIM signing** for email authentication
|
||||||
|
- **SPF and DMARC** policies for anti-spoofing
|
||||||
|
- **Spam filtering** with SpamAssassin
|
||||||
|
- **Virus scanning** with ClamAV
|
||||||
|
- **Secure authentication** with encrypted passwords
|
||||||
|
- **Firewall rules** restricting access to necessary ports
|
||||||
|
|
||||||
|
## Email Ports
|
||||||
|
|
||||||
|
- **25** - SMTP (incoming mail)
|
||||||
|
- **587** - Submission (authenticated sending)
|
||||||
|
- **465** - SMTPS (secure SMTP)
|
||||||
|
- **143** - IMAP
|
||||||
|
- **993** - IMAPS (secure IMAP)
|
||||||
|
- **110** - POP3
|
||||||
|
- **995** - POP3S (secure POP3)
|
||||||
|
|
||||||
|
## Client Configuration
|
||||||
|
|
||||||
|
### IMAP Settings
|
||||||
|
- **Server**: mail.yourdomain.com
|
||||||
|
- **Port**: 993 (SSL) or 143 (STARTTLS)
|
||||||
|
- **Security**: SSL/TLS
|
||||||
|
- **Authentication**: Normal password
|
||||||
|
|
||||||
|
### SMTP Settings
|
||||||
|
- **Server**: mail.yourdomain.com
|
||||||
|
- **Port**: 587 (STARTTLS) or 465 (SSL)
|
||||||
|
- **Security**: SSL/TLS
|
||||||
|
- **Authentication**: Normal password
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check Service Status
|
||||||
|
```bash
|
||||||
|
systemctl status postfix dovecot amavis spamassassin clamav-daemon opendkim apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
```bash
|
||||||
|
# Postfix logs
|
||||||
|
tail -f /var/log/mail.log
|
||||||
|
|
||||||
|
# Dovecot logs
|
||||||
|
tail -f /var/log/dovecot.log
|
||||||
|
|
||||||
|
# Amavis logs
|
||||||
|
tail -f /var/log/amavis.log
|
||||||
|
|
||||||
|
# Apache logs
|
||||||
|
tail -f /var/log/apache2/error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Email Sending
|
||||||
|
```bash
|
||||||
|
echo "Test email" | mail -s "Test Subject" user@yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test DKIM
|
||||||
|
```bash
|
||||||
|
opendkim-testkey -d yourdomain.com -s mail -vvv
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test DNS Records
|
||||||
|
```bash
|
||||||
|
dig MX yourdomain.com
|
||||||
|
dig TXT yourdomain.com
|
||||||
|
dig TXT mail._domainkey.yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Update SSL Certificates
|
||||||
|
Certificates are automatically renewed via cron. To test renewal:
|
||||||
|
```bash
|
||||||
|
certbot renew --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Spam Rules
|
||||||
|
```bash
|
||||||
|
sa-update
|
||||||
|
systemctl restart spamassassin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Virus Definitions
|
||||||
|
```bash
|
||||||
|
freshclam
|
||||||
|
systemctl restart clamav-daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Configuration
|
||||||
|
```bash
|
||||||
|
tar -czf email-backup-$(date +%Y%m%d).tar.gz \
|
||||||
|
/etc/postfix \
|
||||||
|
/etc/dovecot \
|
||||||
|
/etc/amavis \
|
||||||
|
/etc/opendkim \
|
||||||
|
/var/www/postfixadmin/config.local.php \
|
||||||
|
/etc/letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Locations
|
||||||
|
|
||||||
|
- **Postfix config**: `/etc/postfix/`
|
||||||
|
- **Dovecot config**: `/etc/dovecot/`
|
||||||
|
- **Amavis config**: `/etc/amavis/`
|
||||||
|
- **OpenDKIM config**: `/etc/opendkim/`
|
||||||
|
- **PostfixAdmin**: `/var/www/postfixadmin/`
|
||||||
|
- **Mail storage**: `/var/mail/vhosts/`
|
||||||
|
- **SSL certificates**: `/etc/letsencrypt/live/`
|
||||||
|
- **Setup log**: `/var/log/email-server-setup.log`
|
||||||
|
|
||||||
|
## Advanced Configuration
|
||||||
|
|
||||||
|
### Custom Spam Rules
|
||||||
|
Edit `/etc/spamassassin/local.cf` and restart SpamAssassin.
|
||||||
|
|
||||||
|
### Additional Domains
|
||||||
|
Add domains through PostfixAdmin web interface.
|
||||||
|
|
||||||
|
### Quota Management
|
||||||
|
Quotas are managed through PostfixAdmin and enforced by Dovecot.
|
||||||
|
|
||||||
|
### Backup Strategy
|
||||||
|
Implement regular backups of:
|
||||||
|
- PostgreSQL database
|
||||||
|
- Configuration files
|
||||||
|
- SSL certificates
|
||||||
|
- Mail data
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues and support:
|
||||||
|
1. Check the setup log: `/var/log/email-server-setup.log`
|
||||||
|
2. Review service logs
|
||||||
|
3. Verify DNS configuration
|
||||||
|
4. Test with online email testing tools
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This script is provided as-is under the MIT License.
|
||||||
329
add-domain.sh
Executable file
329
add-domain.sh
Executable file
@@ -0,0 +1,329 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Add Domain Helper Script
|
||||||
|
# Adds DKIM support and configuration for additional domains
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# Check arguments
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
echo "Usage: $0 <domain>"
|
||||||
|
echo "Example: $0 newdomain.com"
|
||||||
|
echo
|
||||||
|
echo "This script will:"
|
||||||
|
echo " - Generate DKIM keys for the new domain"
|
||||||
|
echo " - Update OpenDKIM configuration"
|
||||||
|
echo " - Display DNS records to add"
|
||||||
|
echo " - Show PostfixAdmin setup instructions"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOMAIN=$1
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_FILE="/var/log/email-server-setup.log"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}INFO: $1${NC}"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
||||||
|
log "WARNING: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
||||||
|
log "ERROR: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate domain format
|
||||||
|
validate_domain() {
|
||||||
|
if [[ ! "$DOMAIN" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.[a-zA-Z]{2,}$ ]]; then
|
||||||
|
error "Invalid domain format: $DOMAIN"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if domain already exists in DKIM
|
||||||
|
check_existing_domain() {
|
||||||
|
if [[ -d "/etc/opendkim/keys/$DOMAIN" ]]; then
|
||||||
|
warning "DKIM keys already exist for $DOMAIN"
|
||||||
|
read -p "Do you want to regenerate them? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
info "Keeping existing DKIM keys for $DOMAIN"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get main hostname from existing configuration
|
||||||
|
get_main_hostname() {
|
||||||
|
if [[ -f "/etc/postfix/main.cf" ]]; then
|
||||||
|
MAIN_HOSTNAME=$(grep "^myhostname" /etc/postfix/main.cf | cut -d= -f2 | tr -d ' ')
|
||||||
|
if [[ -z "$MAIN_HOSTNAME" ]]; then
|
||||||
|
error "Could not determine main hostname from Postfix configuration"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error "Postfix configuration not found. Run the main setup script first."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate DKIM keys for the new domain
|
||||||
|
generate_dkim_keys() {
|
||||||
|
info "Generating DKIM keys for domain: $DOMAIN"
|
||||||
|
|
||||||
|
# Create directory
|
||||||
|
mkdir -p /etc/opendkim/keys/$DOMAIN
|
||||||
|
|
||||||
|
# Generate DKIM key
|
||||||
|
opendkim-genkey -t -s mail -d $DOMAIN -D /etc/opendkim/keys/$DOMAIN
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chown -R opendkim:opendkim /etc/opendkim/keys/$DOMAIN
|
||||||
|
chmod 600 /etc/opendkim/keys/$DOMAIN/mail.private
|
||||||
|
|
||||||
|
success "DKIM keys generated for $DOMAIN"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update OpenDKIM configuration
|
||||||
|
update_opendkim_config() {
|
||||||
|
info "Updating OpenDKIM configuration..."
|
||||||
|
|
||||||
|
# Check if entry already exists in key.table
|
||||||
|
if ! grep -q "mail._domainkey.$DOMAIN" /etc/opendkim/key.table 2>/dev/null; then
|
||||||
|
echo "mail._domainkey.$DOMAIN $DOMAIN:mail:/etc/opendkim/keys/$DOMAIN/mail.private" >> /etc/opendkim/key.table
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if entry already exists in signing.table
|
||||||
|
if ! grep -q "*@$DOMAIN" /etc/opendkim/signing.table 2>/dev/null; then
|
||||||
|
echo "*@$DOMAIN mail._domainkey.$DOMAIN" >> /etc/opendkim/signing.table
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if domain already exists in trusted.hosts
|
||||||
|
if ! grep -q "^$DOMAIN$" /etc/opendkim/trusted.hosts 2>/dev/null; then
|
||||||
|
echo "$DOMAIN" >> /etc/opendkim/trusted.hosts
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "OpenDKIM configuration updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restart OpenDKIM service
|
||||||
|
restart_opendkim() {
|
||||||
|
info "Restarting OpenDKIM service..."
|
||||||
|
if systemctl restart opendkim; then
|
||||||
|
success "OpenDKIM service restarted"
|
||||||
|
else
|
||||||
|
error "Failed to restart OpenDKIM service"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test DKIM configuration
|
||||||
|
test_dkim() {
|
||||||
|
info "Testing DKIM configuration..."
|
||||||
|
sleep 2 # Give OpenDKIM time to start
|
||||||
|
|
||||||
|
if opendkim-testkey -d $DOMAIN -s mail -vvv 2>&1 | grep -q "key OK"; then
|
||||||
|
success "DKIM test passed for $DOMAIN"
|
||||||
|
else
|
||||||
|
warning "DKIM test failed. Check the DNS record below and try again later."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display DNS records to add
|
||||||
|
display_dns_records() {
|
||||||
|
get_main_hostname
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}=== DNS Records to Add for $DOMAIN ===${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}1. MX Record:${NC}"
|
||||||
|
echo "MX $DOMAIN $MAIN_HOSTNAME"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}2. SPF Record:${NC}"
|
||||||
|
echo "TXT $DOMAIN \"v=spf1 mx ~all\""
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}3. DMARC Record:${NC}"
|
||||||
|
echo "TXT _dmarc.$DOMAIN \"v=DMARC1; p=none; rua=mailto:dmarc@$DOMAIN\""
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}4. DKIM Record:${NC}"
|
||||||
|
echo "Record name: mail._domainkey.$DOMAIN"
|
||||||
|
echo "Record type: TXT"
|
||||||
|
echo "Record value:"
|
||||||
|
cat /etc/opendkim/keys/$DOMAIN/mail.txt 2>/dev/null || echo "Error: DKIM key file not found"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display PostfixAdmin instructions
|
||||||
|
display_postfixadmin_instructions() {
|
||||||
|
get_main_hostname
|
||||||
|
|
||||||
|
echo -e "${YELLOW}=== PostfixAdmin Setup Instructions ===${NC}"
|
||||||
|
echo
|
||||||
|
echo "1. Visit: https://$MAIN_HOSTNAME/postfixadmin/"
|
||||||
|
echo "2. Login with your admin credentials"
|
||||||
|
echo "3. Go to 'Domain List' → 'New Domain'"
|
||||||
|
echo "4. Enter domain: $DOMAIN"
|
||||||
|
echo "5. Set desired limits and quotas"
|
||||||
|
echo "6. Click 'Add Domain'"
|
||||||
|
echo "7. Create mailboxes under 'Virtual List' → 'Add Mailbox'"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}Suggested mailboxes for $DOMAIN:${NC}"
|
||||||
|
echo " - admin@$DOMAIN"
|
||||||
|
echo " - info@$DOMAIN"
|
||||||
|
echo " - noreply@$DOMAIN"
|
||||||
|
echo " - support@$DOMAIN"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display application configuration
|
||||||
|
display_app_config() {
|
||||||
|
get_main_hostname
|
||||||
|
|
||||||
|
echo -e "${YELLOW}=== Application SMTP Configuration ===${NC}"
|
||||||
|
echo
|
||||||
|
echo "Your applications can now send email from $DOMAIN using these settings:"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}SMTP Settings:${NC}"
|
||||||
|
echo " Host: $MAIN_HOSTNAME"
|
||||||
|
echo " Port: 587 (STARTTLS) or 465 (SSL/TLS)"
|
||||||
|
echo " Security: STARTTLS or SSL/TLS"
|
||||||
|
echo " Username: mailbox@$DOMAIN (full email address)"
|
||||||
|
echo " Password: [mailbox password from PostfixAdmin]"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}Example Python code:${NC}"
|
||||||
|
cat << 'EOF'
|
||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
|
smtp_config = {
|
||||||
|
'host': 'MAIN_HOSTNAME',
|
||||||
|
'port': 587,
|
||||||
|
'username': 'app@DOMAIN',
|
||||||
|
'password': 'your_mailbox_password'
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = MIMEText("Hello from DOMAIN!")
|
||||||
|
msg['Subject'] = "Test Email"
|
||||||
|
msg['From'] = smtp_config['username']
|
||||||
|
msg['To'] = "recipient@example.com"
|
||||||
|
|
||||||
|
with smtplib.SMTP(smtp_config['host'], smtp_config['port']) as server:
|
||||||
|
server.starttls()
|
||||||
|
server.login(smtp_config['username'], smtp_config['password'])
|
||||||
|
server.send_message(msg)
|
||||||
|
EOF
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify email server is running
|
||||||
|
verify_email_server() {
|
||||||
|
info "Verifying email server status..."
|
||||||
|
|
||||||
|
services=("postfix" "dovecot" "opendkim" "postgresql")
|
||||||
|
all_running=true
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
if ! systemctl is-active --quiet $service; then
|
||||||
|
warning "$service is not running"
|
||||||
|
all_running=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if $all_running; then
|
||||||
|
success "All required services are running"
|
||||||
|
else
|
||||||
|
warning "Some services are not running. You may need to restart them."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function
|
||||||
|
main() {
|
||||||
|
echo -e "${BLUE}Add Domain Script for Email Server${NC}"
|
||||||
|
echo "=================================="
|
||||||
|
echo "Adding domain: $DOMAIN"
|
||||||
|
echo
|
||||||
|
|
||||||
|
check_root
|
||||||
|
validate_domain
|
||||||
|
verify_email_server
|
||||||
|
|
||||||
|
if check_existing_domain; then
|
||||||
|
generate_dkim_keys
|
||||||
|
fi
|
||||||
|
|
||||||
|
update_opendkim_config
|
||||||
|
restart_opendkim
|
||||||
|
test_dkim
|
||||||
|
display_dns_records
|
||||||
|
display_postfixadmin_instructions
|
||||||
|
display_app_config
|
||||||
|
|
||||||
|
echo
|
||||||
|
success "Domain $DOMAIN has been configured!"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Next steps:${NC}"
|
||||||
|
echo "1. Add the DNS records shown above"
|
||||||
|
echo "2. Wait for DNS propagation (up to 24 hours)"
|
||||||
|
echo "3. Add the domain in PostfixAdmin"
|
||||||
|
echo "4. Create mailboxes for the domain"
|
||||||
|
echo "5. Test email sending and receiving"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}To test the configuration later, run:${NC}"
|
||||||
|
echo "./test-email-server.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show help if requested
|
||||||
|
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||||
|
echo "Add Domain Script for Email Server"
|
||||||
|
echo "================================="
|
||||||
|
echo
|
||||||
|
echo "Usage: $0 <domain>"
|
||||||
|
echo
|
||||||
|
echo "This script adds DKIM support for additional domains to your email server."
|
||||||
|
echo "It will generate DKIM keys, update OpenDKIM configuration, and provide"
|
||||||
|
echo "DNS records and PostfixAdmin instructions."
|
||||||
|
echo
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 newcompany.com"
|
||||||
|
echo " $0 mysite.org"
|
||||||
|
echo
|
||||||
|
echo "Prerequisites:"
|
||||||
|
echo " - Email server must be already set up with setup-email-server.sh"
|
||||||
|
echo " - Must be run as root"
|
||||||
|
echo " - Domain should point to your server"
|
||||||
|
echo
|
||||||
|
echo "After running this script:"
|
||||||
|
echo " 1. Add the provided DNS records"
|
||||||
|
echo " 2. Configure the domain in PostfixAdmin"
|
||||||
|
echo " 3. Create mailboxes for the new domain"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
main "$@"
|
||||||
179
backup-email-server.sh
Executable file
179
backup-email-server.sh
Executable file
@@ -0,0 +1,179 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Email Server Backup Script
|
||||||
|
# Creates backups of email server configuration and data
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
BACKUP_DIR="/var/backups/email-server"
|
||||||
|
DATE=$(date +%Y%m%d_%H%M%S)
|
||||||
|
BACKUP_NAME="email-backup-$DATE"
|
||||||
|
RETENTION_DAYS=30
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}INFO: $1${NC}"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
||||||
|
log "ERROR: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create backup directory
|
||||||
|
create_backup_dir() {
|
||||||
|
info "Creating backup directory..."
|
||||||
|
mkdir -p "$BACKUP_DIR/$BACKUP_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup PostgreSQL database
|
||||||
|
backup_database() {
|
||||||
|
info "Backing up PostgreSQL database..."
|
||||||
|
sudo -u postgres pg_dump postfix > "$BACKUP_DIR/$BACKUP_NAME/postfix_db.sql"
|
||||||
|
success "Database backup completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup configuration files
|
||||||
|
backup_configs() {
|
||||||
|
info "Backing up configuration files..."
|
||||||
|
|
||||||
|
# Postfix
|
||||||
|
cp -r /etc/postfix "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
|
||||||
|
# Dovecot
|
||||||
|
cp -r /etc/dovecot "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
|
||||||
|
# Amavis
|
||||||
|
cp -r /etc/amavis "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
|
||||||
|
# OpenDKIM
|
||||||
|
cp -r /etc/opendkim "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
|
||||||
|
# SpamAssassin
|
||||||
|
cp -r /etc/spamassassin "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
|
||||||
|
# PostfixAdmin
|
||||||
|
if [[ -d "/var/www/postfixadmin" ]]; then
|
||||||
|
cp -r /var/www/postfixadmin "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apache configuration
|
||||||
|
cp -r /etc/apache2/sites-available "$BACKUP_DIR/$BACKUP_NAME/apache2-sites/"
|
||||||
|
|
||||||
|
success "Configuration backup completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup SSL certificates
|
||||||
|
backup_ssl() {
|
||||||
|
info "Backing up SSL certificates..."
|
||||||
|
if [[ -d "/etc/letsencrypt" ]]; then
|
||||||
|
cp -r /etc/letsencrypt "$BACKUP_DIR/$BACKUP_NAME/"
|
||||||
|
success "SSL certificates backup completed"
|
||||||
|
else
|
||||||
|
info "No SSL certificates found to backup"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup mail data (optional - can be large)
|
||||||
|
backup_mail_data() {
|
||||||
|
if [[ "${1:-}" == "--include-mail" ]]; then
|
||||||
|
info "Backing up mail data (this may take a while)..."
|
||||||
|
if [[ -d "/var/mail/vhosts" ]]; then
|
||||||
|
tar -czf "$BACKUP_DIR/$BACKUP_NAME/mail_data.tar.gz" -C /var/mail vhosts
|
||||||
|
success "Mail data backup completed"
|
||||||
|
else
|
||||||
|
info "No mail data found to backup"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
info "Skipping mail data backup (use --include-mail to include)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create compressed archive
|
||||||
|
create_archive() {
|
||||||
|
info "Creating compressed archive..."
|
||||||
|
cd "$BACKUP_DIR"
|
||||||
|
tar -czf "$BACKUP_NAME.tar.gz" "$BACKUP_NAME"
|
||||||
|
rm -rf "$BACKUP_NAME"
|
||||||
|
success "Archive created: $BACKUP_DIR/$BACKUP_NAME.tar.gz"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup old backups
|
||||||
|
cleanup_old_backups() {
|
||||||
|
info "Cleaning up backups older than $RETENTION_DAYS days..."
|
||||||
|
find "$BACKUP_DIR" -name "email-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
|
||||||
|
success "Old backups cleaned up"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display backup information
|
||||||
|
show_backup_info() {
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}Backup completed successfully!${NC}"
|
||||||
|
echo "Backup location: $BACKUP_DIR/$BACKUP_NAME.tar.gz"
|
||||||
|
echo "Backup size: $(du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)"
|
||||||
|
echo
|
||||||
|
echo "To restore this backup:"
|
||||||
|
echo "1. Extract: tar -xzf $BACKUP_NAME.tar.gz"
|
||||||
|
echo "2. Stop services: systemctl stop postfix dovecot amavis apache2"
|
||||||
|
echo "3. Restore configurations to their original locations"
|
||||||
|
echo "4. Restore database: sudo -u postgres psql postfix < postfix_db.sql"
|
||||||
|
echo "5. Restart services: systemctl start postfix dovecot amavis apache2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function
|
||||||
|
main() {
|
||||||
|
echo -e "${BLUE}Email Server Backup Script${NC}"
|
||||||
|
echo "=========================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
create_backup_dir
|
||||||
|
backup_database
|
||||||
|
backup_configs
|
||||||
|
backup_ssl
|
||||||
|
backup_mail_data "$@"
|
||||||
|
create_archive
|
||||||
|
cleanup_old_backups
|
||||||
|
show_backup_info
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show usage if help requested
|
||||||
|
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||||
|
echo "Usage: $0 [--include-mail]"
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " --include-mail Include mail data in backup (can be large)"
|
||||||
|
echo " --help, -h Show this help message"
|
||||||
|
echo
|
||||||
|
echo "This script backs up:"
|
||||||
|
echo " - PostgreSQL database"
|
||||||
|
echo " - Configuration files (Postfix, Dovecot, Amavis, OpenDKIM, etc.)"
|
||||||
|
echo " - SSL certificates"
|
||||||
|
echo " - PostfixAdmin installation"
|
||||||
|
echo " - Mail data (if --include-mail is specified)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
main "$@"
|
||||||
207
config.template
Normal file
207
config.template
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# Email Server Configuration Template
|
||||||
|
# Copy this file and customize for your environment
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# BASIC CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Your domain name (e.g., example.com)
|
||||||
|
DOMAIN="yourdomain.com"
|
||||||
|
|
||||||
|
# Your mail server hostname (e.g., mail.example.com)
|
||||||
|
HOSTNAME="mail.yourdomain.com"
|
||||||
|
|
||||||
|
# Administrator email address
|
||||||
|
ADMIN_EMAIL="admin@yourdomain.com"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# DATABASE CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# PostgreSQL database settings
|
||||||
|
DB_NAME="postfix"
|
||||||
|
DB_USER="postfix"
|
||||||
|
DB_PASSWORD="your_secure_database_password"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# POSTFIXADMIN CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# PostfixAdmin setup password (used during initial setup)
|
||||||
|
POSTFIXADMIN_PASSWORD="your_secure_setup_password"
|
||||||
|
|
||||||
|
# PostfixAdmin installation directory
|
||||||
|
WEBROOT="/var/www/postfixadmin"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SSL/TLS CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Let's Encrypt email for certificate registration
|
||||||
|
LETSENCRYPT_EMAIL="admin@yourdomain.com"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SECURITY SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Fail2ban configuration (optional)
|
||||||
|
ENABLE_FAIL2BAN="yes"
|
||||||
|
|
||||||
|
# Maximum message size (in bytes) - 50MB default
|
||||||
|
MAX_MESSAGE_SIZE="52428800"
|
||||||
|
|
||||||
|
# Maximum mailbox size (0 = unlimited)
|
||||||
|
MAX_MAILBOX_SIZE="0"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SPAM FILTERING SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# SpamAssassin score thresholds
|
||||||
|
SA_TAG_LEVEL="2.0" # Add spam headers
|
||||||
|
SA_TAG2_LEVEL="6.0" # Add more spam headers
|
||||||
|
SA_KILL_LEVEL="6.9" # Reject/quarantine
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ADVANCED SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Virtual mail user/group IDs
|
||||||
|
VMAIL_UID="5000"
|
||||||
|
VMAIL_GID="5000"
|
||||||
|
|
||||||
|
# Mail storage location
|
||||||
|
MAIL_LOCATION="/var/mail/vhosts"
|
||||||
|
|
||||||
|
# Dovecot authentication method
|
||||||
|
AUTH_MECHANISMS="plain login"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# NETWORK SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Listen on these interfaces (all = all interfaces)
|
||||||
|
INET_INTERFACES="all"
|
||||||
|
|
||||||
|
# IP protocol (ipv4, ipv6, or all)
|
||||||
|
INET_PROTOCOLS="ipv4"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# BACKUP SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Backup directory
|
||||||
|
BACKUP_DIR="/var/backups/email-server"
|
||||||
|
|
||||||
|
# Backup retention (days)
|
||||||
|
BACKUP_RETENTION="30"
|
||||||
|
|
||||||
|
# Include mail data in backups (yes/no)
|
||||||
|
BACKUP_INCLUDE_MAIL="no"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MONITORING SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Log file locations
|
||||||
|
MAIN_LOG="/var/log/mail.log"
|
||||||
|
SETUP_LOG="/var/log/email-server-setup.log"
|
||||||
|
|
||||||
|
# Disk space warning threshold (percentage)
|
||||||
|
DISK_WARNING_THRESHOLD="85"
|
||||||
|
|
||||||
|
# Certificate expiration warning (days)
|
||||||
|
CERT_WARNING_DAYS="30"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# DNS RECORDS REFERENCE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Add these DNS records to your domain:
|
||||||
|
#
|
||||||
|
# A Record:
|
||||||
|
# mail.yourdomain.com IN A YOUR_SERVER_IP
|
||||||
|
#
|
||||||
|
# MX Record:
|
||||||
|
# yourdomain.com IN MX 10 mail.yourdomain.com
|
||||||
|
#
|
||||||
|
# SPF Record:
|
||||||
|
# yourdomain.com IN TXT "v=spf1 mx ~all"
|
||||||
|
#
|
||||||
|
# DMARC Record:
|
||||||
|
# _dmarc.yourdomain.com IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
|
||||||
|
#
|
||||||
|
# DKIM Record (generated by the script):
|
||||||
|
# mail._domainkey.yourdomain.com IN TXT "v=DKIM1; k=rsa; p=..."
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# FIREWALL PORTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# These ports will be opened in the firewall:
|
||||||
|
# 25 - SMTP (incoming mail)
|
||||||
|
# 587 - Submission (authenticated sending)
|
||||||
|
# 465 - SMTPS (secure SMTP)
|
||||||
|
# 143 - IMAP
|
||||||
|
# 993 - IMAPS (secure IMAP)
|
||||||
|
# 110 - POP3
|
||||||
|
# 995 - POP3S (secure POP3)
|
||||||
|
# 80 - HTTP (for certificate validation)
|
||||||
|
# 443 - HTTPS (PostfixAdmin web interface)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# RECOMMENDED ADDITIONAL SECURITY
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Consider implementing:
|
||||||
|
# 1. Fail2ban for intrusion prevention
|
||||||
|
# 2. Regular security updates
|
||||||
|
# 3. Strong passwords for all accounts
|
||||||
|
# 4. Regular backups
|
||||||
|
# 5. Monitoring and alerting
|
||||||
|
# 6. Rate limiting
|
||||||
|
# 7. Greylisting (optional)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MAINTENANCE SCHEDULE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Recommended cron jobs:
|
||||||
|
# Daily virus definition updates:
|
||||||
|
# 0 2 * * * /usr/bin/freshclam
|
||||||
|
|
||||||
|
# Weekly SpamAssassin rule updates:
|
||||||
|
# 0 3 * * 1 /usr/bin/sa-update && /bin/systemctl restart spamassassin
|
||||||
|
|
||||||
|
# Weekly maintenance:
|
||||||
|
# 0 4 * * 1 /path/to/maintenance-email-server.sh
|
||||||
|
|
||||||
|
# Monthly backups:
|
||||||
|
# 0 5 1 * * /path/to/backup-email-server.sh
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# TROUBLESHOOTING COMMANDS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Check service status:
|
||||||
|
# systemctl status postfix dovecot amavis spamassassin clamav-daemon opendkim
|
||||||
|
|
||||||
|
# View logs:
|
||||||
|
# tail -f /var/log/mail.log
|
||||||
|
# tail -f /var/log/dovecot.log
|
||||||
|
|
||||||
|
# Test configuration:
|
||||||
|
# postfix check
|
||||||
|
# dovecot -n
|
||||||
|
# amavisd-new testkeys
|
||||||
|
|
||||||
|
# Check mail queue:
|
||||||
|
# mailq
|
||||||
|
# postqueue -p
|
||||||
|
|
||||||
|
# Test DKIM:
|
||||||
|
# opendkim-testkey -d yourdomain.com -s mail -vvv
|
||||||
|
|
||||||
|
# Test ports:
|
||||||
|
# telnet localhost 25
|
||||||
|
# openssl s_client -connect localhost:993
|
||||||
290
maintenance-email-server.sh
Executable file
290
maintenance-email-server.sh
Executable file
@@ -0,0 +1,290 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Email Server Maintenance Script
|
||||||
|
# Performs routine maintenance tasks
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}INFO: $1${NC}"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
||||||
|
log "WARNING: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
||||||
|
log "ERROR: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update virus definitions
|
||||||
|
update_virus_definitions() {
|
||||||
|
info "Updating virus definitions..."
|
||||||
|
if freshclam; then
|
||||||
|
success "Virus definitions updated"
|
||||||
|
systemctl restart clamav-daemon
|
||||||
|
else
|
||||||
|
error "Failed to update virus definitions"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update spam rules
|
||||||
|
update_spam_rules() {
|
||||||
|
info "Updating SpamAssassin rules..."
|
||||||
|
if sa-update; then
|
||||||
|
success "SpamAssassin rules updated"
|
||||||
|
systemctl restart spamassassin
|
||||||
|
else
|
||||||
|
warning "SpamAssassin update failed or no updates available"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean mail logs
|
||||||
|
clean_mail_logs() {
|
||||||
|
info "Cleaning old mail logs..."
|
||||||
|
|
||||||
|
# Rotate logs if they're getting large (>100MB)
|
||||||
|
if [[ -f "/var/log/mail.log" ]]; then
|
||||||
|
size=$(stat -f%z "/var/log/mail.log" 2>/dev/null || stat -c%s "/var/log/mail.log" 2>/dev/null || echo 0)
|
||||||
|
if [[ $size -gt 104857600 ]]; then # 100MB
|
||||||
|
logrotate -f /etc/logrotate.d/rsyslog
|
||||||
|
success "Mail logs rotated"
|
||||||
|
else
|
||||||
|
info "Mail logs are not large enough to rotate"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean temporary files
|
||||||
|
clean_temp_files() {
|
||||||
|
info "Cleaning temporary files..."
|
||||||
|
|
||||||
|
# Clean Amavis temporary files
|
||||||
|
find /var/lib/amavis/tmp -type f -mtime +7 -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
# Clean SpamAssassin temporary files
|
||||||
|
find /var/lib/spamassassin -name "*.tmp" -mtime +7 -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
# Clean Postfix temporary files
|
||||||
|
find /var/spool/postfix -name "*" -type f -mtime +7 -path "*/tmp/*" -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
success "Temporary files cleaned"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check disk space
|
||||||
|
check_disk_space() {
|
||||||
|
info "Checking disk space..."
|
||||||
|
|
||||||
|
# Check root filesystem
|
||||||
|
root_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||||
|
if [[ $root_usage -gt 85 ]]; then
|
||||||
|
warning "Root filesystem is ${root_usage}% full"
|
||||||
|
else
|
||||||
|
info "Root filesystem usage: ${root_usage}%"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check mail directory
|
||||||
|
if [[ -d "/var/mail/vhosts" ]]; then
|
||||||
|
mail_usage=$(df /var/mail/vhosts | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||||
|
if [[ $mail_usage -gt 85 ]]; then
|
||||||
|
warning "Mail directory is ${mail_usage}% full"
|
||||||
|
else
|
||||||
|
info "Mail directory usage: ${mail_usage}%"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check certificate expiration
|
||||||
|
check_ssl_expiration() {
|
||||||
|
info "Checking SSL certificate expiration..."
|
||||||
|
|
||||||
|
cert_files=$(find /etc/letsencrypt/live -name "fullchain.pem" 2>/dev/null || true)
|
||||||
|
|
||||||
|
for cert_file in $cert_files; do
|
||||||
|
domain=$(basename $(dirname $cert_file))
|
||||||
|
expires=$(openssl x509 -in "$cert_file" -noout -enddate | cut -d= -f2)
|
||||||
|
expires_epoch=$(date -d "$expires" +%s)
|
||||||
|
current_epoch=$(date +%s)
|
||||||
|
days_left=$(( (expires_epoch - current_epoch) / 86400 ))
|
||||||
|
|
||||||
|
if [[ $days_left -lt 30 ]]; then
|
||||||
|
warning "SSL certificate for $domain expires in $days_left days"
|
||||||
|
else
|
||||||
|
info "SSL certificate for $domain expires in $days_left days"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
check_services() {
|
||||||
|
info "Checking service status..."
|
||||||
|
|
||||||
|
services=("postfix" "dovecot" "amavis" "spamassassin" "clamav-daemon" "opendkim" "apache2" "postgresql")
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
if systemctl is-active --quiet $service; then
|
||||||
|
success "$service is running"
|
||||||
|
else
|
||||||
|
error "$service is not running"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test basic email functionality
|
||||||
|
test_email_basic() {
|
||||||
|
info "Testing basic email functionality..."
|
||||||
|
|
||||||
|
# Test SMTP port
|
||||||
|
if nc -z localhost 25; then
|
||||||
|
success "SMTP port 25 is accessible"
|
||||||
|
else
|
||||||
|
error "SMTP port 25 is not accessible"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test submission port
|
||||||
|
if nc -z localhost 587; then
|
||||||
|
success "Submission port 587 is accessible"
|
||||||
|
else
|
||||||
|
error "Submission port 587 is not accessible"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test IMAP port
|
||||||
|
if nc -z localhost 993; then
|
||||||
|
success "IMAPS port 993 is accessible"
|
||||||
|
else
|
||||||
|
error "IMAPS port 993 is not accessible"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Database maintenance
|
||||||
|
database_maintenance() {
|
||||||
|
info "Performing database maintenance..."
|
||||||
|
|
||||||
|
# Analyze and vacuum database
|
||||||
|
sudo -u postgres psql -d postfix -c "ANALYZE;" >/dev/null 2>&1
|
||||||
|
sudo -u postgres psql -d postfix -c "VACUUM;" >/dev/null 2>&1
|
||||||
|
|
||||||
|
success "Database maintenance completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check mail queue
|
||||||
|
check_mail_queue() {
|
||||||
|
info "Checking mail queue..."
|
||||||
|
|
||||||
|
queue_count=$(mailq | tail -1 | awk '{print $5}' || echo "0")
|
||||||
|
if [[ "$queue_count" == "empty" ]]; then
|
||||||
|
queue_count=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $queue_count -gt 10 ]]; then
|
||||||
|
warning "Mail queue has $queue_count messages"
|
||||||
|
echo "Run 'mailq' to see queued messages"
|
||||||
|
echo "Run 'postqueue -f' to flush the queue"
|
||||||
|
else
|
||||||
|
info "Mail queue has $queue_count messages"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate maintenance report
|
||||||
|
generate_report() {
|
||||||
|
info "Generating maintenance report..."
|
||||||
|
|
||||||
|
report_file="/var/log/email-maintenance-$(date +%Y%m%d).log"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "Email Server Maintenance Report - $(date)"
|
||||||
|
echo "============================================"
|
||||||
|
echo
|
||||||
|
echo "System Information:"
|
||||||
|
echo "- Hostname: $(hostname)"
|
||||||
|
echo "- Uptime: $(uptime | awk -F'up ' '{print $2}' | awk -F', load' '{print $1}')"
|
||||||
|
echo "- Load: $(uptime | awk -F'load average: ' '{print $2}')"
|
||||||
|
echo
|
||||||
|
echo "Disk Usage:"
|
||||||
|
df -h | grep -E "/$|/var"
|
||||||
|
echo
|
||||||
|
echo "Service Status:"
|
||||||
|
systemctl status postfix dovecot amavis --no-pager -l
|
||||||
|
echo
|
||||||
|
echo "Recent Mail Log Entries:"
|
||||||
|
tail -20 /var/log/mail.log | grep "$(date '+%b %d')"
|
||||||
|
} > "$report_file"
|
||||||
|
|
||||||
|
success "Maintenance report saved to $report_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function
|
||||||
|
main() {
|
||||||
|
echo -e "${BLUE}Email Server Maintenance Script${NC}"
|
||||||
|
echo "==============================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
update_virus_definitions
|
||||||
|
update_spam_rules
|
||||||
|
clean_mail_logs
|
||||||
|
clean_temp_files
|
||||||
|
check_disk_space
|
||||||
|
check_ssl_expiration
|
||||||
|
check_services
|
||||||
|
test_email_basic
|
||||||
|
database_maintenance
|
||||||
|
check_mail_queue
|
||||||
|
generate_report
|
||||||
|
|
||||||
|
echo
|
||||||
|
success "Maintenance completed successfully!"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Recommended actions:${NC}"
|
||||||
|
echo "1. Review the maintenance report in /var/log/"
|
||||||
|
echo "2. Monitor disk space regularly"
|
||||||
|
echo "3. Check for any service issues"
|
||||||
|
echo "4. Verify SSL certificate renewal is working"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show usage
|
||||||
|
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||||
|
echo "Usage: $0"
|
||||||
|
echo
|
||||||
|
echo "This maintenance script performs:"
|
||||||
|
echo " - Updates virus definitions"
|
||||||
|
echo " - Updates SpamAssassin rules"
|
||||||
|
echo " - Cleans old logs and temporary files"
|
||||||
|
echo " - Checks disk space usage"
|
||||||
|
echo " - Verifies SSL certificate expiration"
|
||||||
|
echo " - Tests service status"
|
||||||
|
echo " - Performs database maintenance"
|
||||||
|
echo " - Checks mail queue status"
|
||||||
|
echo " - Generates maintenance report"
|
||||||
|
echo
|
||||||
|
echo "Run this script regularly (daily/weekly) via cron:"
|
||||||
|
echo "0 2 * * 0 /path/to/maintenance-email-server.sh"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
main "$@"
|
||||||
386
manage-domains.sh
Executable file
386
manage-domains.sh
Executable file
@@ -0,0 +1,386 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Multiple Domain Management Script for Email Server
|
||||||
|
# Manage multiple domains, view status, and perform domain operations
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}INFO: $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# List all configured domains
|
||||||
|
list_domains() {
|
||||||
|
echo -e "${BLUE}Configured Email Domains${NC}"
|
||||||
|
echo "========================"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Get domains from database
|
||||||
|
echo -e "${YELLOW}Domains in Database:${NC}"
|
||||||
|
if sudo -u postgres psql -d postfix -t -c "
|
||||||
|
SELECT
|
||||||
|
domain,
|
||||||
|
CASE WHEN active = '1' THEN 'Active' ELSE 'Inactive' END as status,
|
||||||
|
aliases || ' aliases' as aliases,
|
||||||
|
mailboxes || ' mailboxes' as mailboxes,
|
||||||
|
CASE WHEN maxquota = 0 THEN 'Unlimited' ELSE (maxquota/1048576)::text || ' MB' END as quota
|
||||||
|
FROM domains
|
||||||
|
ORDER BY domain;" 2>/dev/null; then
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo " Database connection failed"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get domains with DKIM keys
|
||||||
|
echo -e "${YELLOW}Domains with DKIM Keys:${NC}"
|
||||||
|
if [[ -d "/etc/opendkim/keys" ]]; then
|
||||||
|
for domain_dir in /etc/opendkim/keys/*/; do
|
||||||
|
if [[ -d "$domain_dir" ]]; then
|
||||||
|
domain=$(basename "$domain_dir")
|
||||||
|
if [[ -f "$domain_dir/mail.private" ]]; then
|
||||||
|
echo " $domain (DKIM configured)"
|
||||||
|
else
|
||||||
|
echo " $domain (DKIM incomplete)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " No DKIM directory found"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show domain details
|
||||||
|
show_domain_details() {
|
||||||
|
local domain=$1
|
||||||
|
|
||||||
|
echo -e "${BLUE}Domain Details: $domain${NC}"
|
||||||
|
echo "==============================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Database information
|
||||||
|
echo -e "${YELLOW}Database Information:${NC}"
|
||||||
|
sudo -u postgres psql -d postfix -c "
|
||||||
|
SELECT
|
||||||
|
domain,
|
||||||
|
description,
|
||||||
|
aliases || ' aliases' as aliases,
|
||||||
|
mailboxes || ' mailboxes' as mailboxes,
|
||||||
|
CASE WHEN maxquota = 0 THEN 'Unlimited' ELSE (maxquota/1048576)::text || ' MB' END as max_quota,
|
||||||
|
CASE WHEN active = '1' THEN 'Active' ELSE 'Inactive' END as status,
|
||||||
|
created,
|
||||||
|
modified
|
||||||
|
FROM domains
|
||||||
|
WHERE domain = '$domain';" 2>/dev/null || echo "Domain not found in database"
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Mailboxes for this domain
|
||||||
|
echo -e "${YELLOW}Mailboxes:${NC}"
|
||||||
|
sudo -u postgres psql -d postfix -c "
|
||||||
|
SELECT
|
||||||
|
username,
|
||||||
|
name,
|
||||||
|
CASE WHEN quota = 0 THEN 'Unlimited' ELSE (quota/1048576)::text || ' MB' END as quota,
|
||||||
|
CASE WHEN active = '1' THEN 'Active' ELSE 'Inactive' END as status,
|
||||||
|
created
|
||||||
|
FROM mailbox
|
||||||
|
WHERE domain = '$domain'
|
||||||
|
ORDER BY username;" 2>/dev/null || echo "No mailboxes found"
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Aliases for this domain
|
||||||
|
echo -e "${YELLOW}Aliases:${NC}"
|
||||||
|
sudo -u postgres psql -d postfix -c "
|
||||||
|
SELECT
|
||||||
|
address,
|
||||||
|
goto,
|
||||||
|
CASE WHEN active = '1' THEN 'Active' ELSE 'Inactive' END as status,
|
||||||
|
created
|
||||||
|
FROM aliases
|
||||||
|
WHERE domain = '$domain'
|
||||||
|
ORDER BY address;" 2>/dev/null || echo "No aliases found"
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# DKIM status
|
||||||
|
echo -e "${YELLOW}DKIM Status:${NC}"
|
||||||
|
if [[ -d "/etc/opendkim/keys/$domain" ]]; then
|
||||||
|
if [[ -f "/etc/opendkim/keys/$domain/mail.private" && -f "/etc/opendkim/keys/$domain/mail.txt" ]]; then
|
||||||
|
echo " ✓ DKIM keys exist"
|
||||||
|
|
||||||
|
# Test DKIM
|
||||||
|
if opendkim-testkey -d "$domain" -s mail 2>/dev/null | grep -q "key OK"; then
|
||||||
|
echo " ✓ DKIM test passed"
|
||||||
|
else
|
||||||
|
echo " ✗ DKIM test failed (check DNS record)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo " DKIM DNS Record:"
|
||||||
|
echo " Record name: mail._domainkey.$domain"
|
||||||
|
echo " Record type: TXT"
|
||||||
|
echo " Record value:"
|
||||||
|
cat "/etc/opendkim/keys/$domain/mail.txt" 2>/dev/null | sed 's/^/ /'
|
||||||
|
else
|
||||||
|
echo " ✗ DKIM keys incomplete"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✗ No DKIM configuration found"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test domain configuration
|
||||||
|
test_domain() {
|
||||||
|
local domain=$1
|
||||||
|
|
||||||
|
echo -e "${BLUE}Testing Domain: $domain${NC}"
|
||||||
|
echo "========================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# DNS tests
|
||||||
|
echo -e "${YELLOW}DNS Configuration:${NC}"
|
||||||
|
|
||||||
|
# MX record
|
||||||
|
if dig +short MX "$domain" | grep -q .; then
|
||||||
|
mx_record=$(dig +short MX "$domain" | head -1)
|
||||||
|
echo " ✓ MX record: $mx_record"
|
||||||
|
else
|
||||||
|
echo " ✗ MX record not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SPF record
|
||||||
|
if dig +short TXT "$domain" | grep -q "v=spf1"; then
|
||||||
|
echo " ✓ SPF record found"
|
||||||
|
else
|
||||||
|
echo " ✗ SPF record not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# DMARC record
|
||||||
|
if dig +short TXT "_dmarc.$domain" | grep -q "v=DMARC1"; then
|
||||||
|
echo " ✓ DMARC record found"
|
||||||
|
else
|
||||||
|
echo " ✗ DMARC record not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# DKIM record
|
||||||
|
if dig +short TXT "mail._domainkey.$domain" | grep -q "v=DKIM1"; then
|
||||||
|
echo " ✓ DKIM record found"
|
||||||
|
|
||||||
|
# Test DKIM key
|
||||||
|
if opendkim-testkey -d "$domain" -s mail 2>/dev/null | grep -q "key OK"; then
|
||||||
|
echo " ✓ DKIM key validation passed"
|
||||||
|
else
|
||||||
|
echo " ✗ DKIM key validation failed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✗ DKIM record not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Database test
|
||||||
|
echo -e "${YELLOW}Database Status:${NC}"
|
||||||
|
if sudo -u postgres psql -d postfix -t -c "SELECT 1 FROM domains WHERE domain = '$domain' AND active = '1';" 2>/dev/null | grep -q 1; then
|
||||||
|
echo " ✓ Domain is active in database"
|
||||||
|
else
|
||||||
|
echo " ✗ Domain not found or inactive in database"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove domain
|
||||||
|
remove_domain() {
|
||||||
|
local domain=$1
|
||||||
|
|
||||||
|
echo -e "${YELLOW}WARNING: This will remove all data for domain $domain${NC}"
|
||||||
|
echo "This includes:"
|
||||||
|
echo " - All mailboxes and their emails"
|
||||||
|
echo " - All aliases"
|
||||||
|
echo " - DKIM keys"
|
||||||
|
echo " - Database entries"
|
||||||
|
echo
|
||||||
|
read -p "Are you sure you want to continue? Type 'DELETE' to confirm: " confirm
|
||||||
|
|
||||||
|
if [[ "$confirm" != "DELETE" ]]; then
|
||||||
|
echo "Operation cancelled"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Removing domain: $domain"
|
||||||
|
|
||||||
|
# Remove from database
|
||||||
|
sudo -u postgres psql -d postfix -c "DELETE FROM aliases WHERE domain = '$domain';" 2>/dev/null
|
||||||
|
sudo -u postgres psql -d postfix -c "DELETE FROM mailbox WHERE domain = '$domain';" 2>/dev/null
|
||||||
|
sudo -u postgres psql -d postfix -c "DELETE FROM domain_admins WHERE domain = '$domain';" 2>/dev/null
|
||||||
|
sudo -u postgres psql -d postfix -c "DELETE FROM domains WHERE domain = '$domain';" 2>/dev/null
|
||||||
|
|
||||||
|
# Remove DKIM configuration
|
||||||
|
if [[ -d "/etc/opendkim/keys/$domain" ]]; then
|
||||||
|
rm -rf "/etc/opendkim/keys/$domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove from OpenDKIM config files
|
||||||
|
sed -i "/mail\._domainkey\.$domain/d" /etc/opendkim/key.table 2>/dev/null || true
|
||||||
|
sed -i "/*@$domain/d" /etc/opendkim/signing.table 2>/dev/null || true
|
||||||
|
sed -i "/^$domain$/d" /etc/opendkim/trusted.hosts 2>/dev/null || true
|
||||||
|
|
||||||
|
# Remove mail data
|
||||||
|
if [[ -d "/var/mail/vhosts/$domain" ]]; then
|
||||||
|
warning "Removing mail data for $domain"
|
||||||
|
rm -rf "/var/mail/vhosts/$domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restart OpenDKIM
|
||||||
|
systemctl restart opendkim
|
||||||
|
|
||||||
|
success "Domain $domain removed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show usage
|
||||||
|
show_usage() {
|
||||||
|
echo "Multiple Domain Management Script"
|
||||||
|
echo "================================"
|
||||||
|
echo
|
||||||
|
echo "Usage: $0 <command> [options]"
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo " list - List all configured domains"
|
||||||
|
echo " show <domain> - Show detailed information for a domain"
|
||||||
|
echo " test <domain> - Test domain configuration (DNS, DKIM, etc.)"
|
||||||
|
echo " add <domain> - Add a new domain (calls add-domain.sh)"
|
||||||
|
echo " remove <domain> - Remove a domain and all its data"
|
||||||
|
echo " status - Show overall email server status"
|
||||||
|
echo
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 list"
|
||||||
|
echo " $0 show example.com"
|
||||||
|
echo " $0 test example.com"
|
||||||
|
echo " $0 add newdomain.com"
|
||||||
|
echo " $0 remove olddomain.com"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show server status
|
||||||
|
show_status() {
|
||||||
|
echo -e "${BLUE}Email Server Status${NC}"
|
||||||
|
echo "==================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Service status
|
||||||
|
echo -e "${YELLOW}Service Status:${NC}"
|
||||||
|
services=("postfix" "dovecot" "amavis" "spamassassin" "clamav-daemon" "opendkim" "apache2" "postgresql")
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
if systemctl is-active --quiet "$service"; then
|
||||||
|
echo " ✓ $service is running"
|
||||||
|
else
|
||||||
|
echo " ✗ $service is not running"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Domain summary
|
||||||
|
echo -e "${YELLOW}Domain Summary:${NC}"
|
||||||
|
total_domains=$(sudo -u postgres psql -d postfix -t -c "SELECT COUNT(*) FROM domains;" 2>/dev/null | xargs || echo "0")
|
||||||
|
active_domains=$(sudo -u postgres psql -d postfix -t -c "SELECT COUNT(*) FROM domains WHERE active = '1';" 2>/dev/null | xargs || echo "0")
|
||||||
|
total_mailboxes=$(sudo -u postgres psql -d postfix -t -c "SELECT COUNT(*) FROM mailbox;" 2>/dev/null | xargs || echo "0")
|
||||||
|
active_mailboxes=$(sudo -u postgres psql -d postfix -t -c "SELECT COUNT(*) FROM mailbox WHERE active = '1';" 2>/dev/null | xargs || echo "0")
|
||||||
|
|
||||||
|
echo " Total domains: $total_domains"
|
||||||
|
echo " Active domains: $active_domains"
|
||||||
|
echo " Total mailboxes: $total_mailboxes"
|
||||||
|
echo " Active mailboxes: $active_mailboxes"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Mail queue
|
||||||
|
echo -e "${YELLOW}Mail Queue:${NC}"
|
||||||
|
queue_count=$(mailq 2>/dev/null | tail -1 | awk '{print $5}' || echo "0")
|
||||||
|
if [[ "$queue_count" == "empty" ]]; then
|
||||||
|
echo " Mail queue is empty"
|
||||||
|
else
|
||||||
|
echo " Mail queue has $queue_count messages"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main logic
|
||||||
|
case "${1:-}" in
|
||||||
|
"list")
|
||||||
|
check_root
|
||||||
|
list_domains
|
||||||
|
;;
|
||||||
|
"show")
|
||||||
|
if [[ -z "${2:-}" ]]; then
|
||||||
|
error "Domain name required. Usage: $0 show <domain>"
|
||||||
|
fi
|
||||||
|
check_root
|
||||||
|
show_domain_details "$2"
|
||||||
|
;;
|
||||||
|
"test")
|
||||||
|
if [[ -z "${2:-}" ]]; then
|
||||||
|
error "Domain name required. Usage: $0 test <domain>"
|
||||||
|
fi
|
||||||
|
test_domain "$2"
|
||||||
|
;;
|
||||||
|
"add")
|
||||||
|
if [[ -z "${2:-}" ]]; then
|
||||||
|
error "Domain name required. Usage: $0 add <domain>"
|
||||||
|
fi
|
||||||
|
check_root
|
||||||
|
if [[ -f "./add-domain.sh" ]]; then
|
||||||
|
./add-domain.sh "$2"
|
||||||
|
else
|
||||||
|
error "add-domain.sh script not found in current directory"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"remove")
|
||||||
|
if [[ -z "${2:-}" ]]; then
|
||||||
|
error "Domain name required. Usage: $0 remove <domain>"
|
||||||
|
fi
|
||||||
|
check_root
|
||||||
|
remove_domain "$2"
|
||||||
|
;;
|
||||||
|
"status")
|
||||||
|
check_root
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
"--help"|"-h"|"help"|"")
|
||||||
|
show_usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown command: $1. Use --help for usage information."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
921
setup-email-server.sh
Executable file
921
setup-email-server.sh
Executable file
@@ -0,0 +1,921 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Email Server Setup Script
|
||||||
|
# Components: Postfix, Dovecot, Amavis, SpamAssassin, OpenDKIM, PostgreSQL, PostfixAdmin
|
||||||
|
# SSL: Let's Encrypt
|
||||||
|
# Author: Email Server Setup Script
|
||||||
|
# Date: $(date)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Configuration variables
|
||||||
|
DOMAIN=""
|
||||||
|
HOSTNAME=""
|
||||||
|
ADMIN_EMAIL=""
|
||||||
|
DB_NAME="postfix"
|
||||||
|
DB_USER="postfix"
|
||||||
|
DB_PASSWORD=""
|
||||||
|
POSTFIXADMIN_PASSWORD=""
|
||||||
|
WEBROOT="/var/www/postfixadmin"
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_FILE="/var/log/email-server-setup.log"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
||||||
|
log "ERROR: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}INFO: $1${NC}"
|
||||||
|
log "INFO: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
echo -e "${GREEN}SUCCESS: $1${NC}"
|
||||||
|
log "SUCCESS: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
||||||
|
log "WARNING: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get user input
|
||||||
|
get_configuration() {
|
||||||
|
echo -e "${BLUE}Email Server Configuration${NC}"
|
||||||
|
echo "================================="
|
||||||
|
|
||||||
|
while [[ -z "$DOMAIN" ]]; do
|
||||||
|
read -p "Enter your domain name (e.g., example.com): " DOMAIN
|
||||||
|
done
|
||||||
|
|
||||||
|
while [[ -z "$HOSTNAME" ]]; do
|
||||||
|
read -p "Enter your hostname (e.g., mail.example.com): " HOSTNAME
|
||||||
|
done
|
||||||
|
|
||||||
|
while [[ -z "$ADMIN_EMAIL" ]]; do
|
||||||
|
read -p "Enter admin email address: " ADMIN_EMAIL
|
||||||
|
done
|
||||||
|
|
||||||
|
while [[ -z "$DB_PASSWORD" ]]; do
|
||||||
|
read -s -p "Enter PostgreSQL password for postfix user: " DB_PASSWORD
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
while [[ -z "$POSTFIXADMIN_PASSWORD" ]]; do
|
||||||
|
read -s -p "Enter PostfixAdmin setup password: " POSTFIXADMIN_PASSWORD
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
info "Configuration completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update system
|
||||||
|
update_system() {
|
||||||
|
info "Updating system packages..."
|
||||||
|
apt update && apt upgrade -y
|
||||||
|
success "System updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
install_packages() {
|
||||||
|
info "Installing required packages..."
|
||||||
|
|
||||||
|
# Install basic packages
|
||||||
|
apt install -y \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
gnupg \
|
||||||
|
lsb-release \
|
||||||
|
software-properties-common \
|
||||||
|
certbot \
|
||||||
|
nginx \
|
||||||
|
ufw
|
||||||
|
|
||||||
|
# Install PostgreSQL
|
||||||
|
apt install -y postgresql postgresql-contrib
|
||||||
|
|
||||||
|
# Install Postfix and related packages
|
||||||
|
debconf-set-selections <<< "postfix postfix/mailname string $HOSTNAME"
|
||||||
|
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
|
||||||
|
apt install -y \
|
||||||
|
postfix \
|
||||||
|
postfix-pgsql \
|
||||||
|
postfix-policyd-spf-python
|
||||||
|
|
||||||
|
# Install Dovecot
|
||||||
|
apt install -y \
|
||||||
|
dovecot-core \
|
||||||
|
dovecot-imapd \
|
||||||
|
dovecot-pop3d \
|
||||||
|
dovecot-lmtpd \
|
||||||
|
dovecot-pgsql
|
||||||
|
|
||||||
|
# Install Amavis and SpamAssassin
|
||||||
|
apt install -y \
|
||||||
|
amavisd-new \
|
||||||
|
spamassassin \
|
||||||
|
clamav \
|
||||||
|
clamav-daemon \
|
||||||
|
clamav-freshclam \
|
||||||
|
clamav-unofficial-sigs
|
||||||
|
|
||||||
|
# Install OpenDKIM
|
||||||
|
apt install -y opendkim opendkim-tools
|
||||||
|
|
||||||
|
# Install PHP and Apache for PostfixAdmin
|
||||||
|
apt install -y \
|
||||||
|
apache2 \
|
||||||
|
php \
|
||||||
|
php-fpm \
|
||||||
|
php-cli \
|
||||||
|
php-pgsql \
|
||||||
|
php-mbstring \
|
||||||
|
php-xml \
|
||||||
|
php-curl \
|
||||||
|
php-zip \
|
||||||
|
php-gd
|
||||||
|
|
||||||
|
success "All packages installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure PostgreSQL
|
||||||
|
configure_postgresql() {
|
||||||
|
info "Configuring PostgreSQL..."
|
||||||
|
|
||||||
|
# Start PostgreSQL
|
||||||
|
systemctl start postgresql
|
||||||
|
systemctl enable postgresql
|
||||||
|
|
||||||
|
# Create database and user
|
||||||
|
sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
|
||||||
|
sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';"
|
||||||
|
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
|
||||||
|
|
||||||
|
# Create tables for Postfix
|
||||||
|
sudo -u postgres psql -d "$DB_NAME" << 'EOF'
|
||||||
|
CREATE TABLE domains (
|
||||||
|
domain varchar(50) NOT NULL,
|
||||||
|
description varchar(255),
|
||||||
|
aliases int NOT NULL default '0',
|
||||||
|
mailboxes int NOT NULL default '0',
|
||||||
|
maxquota bigint NOT NULL default '0',
|
||||||
|
quota bigint NOT NULL default '0',
|
||||||
|
transport varchar(255) default NULL,
|
||||||
|
backupmx boolean NOT NULL default '0',
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
modified timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (domain)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE aliases (
|
||||||
|
address varchar(255) NOT NULL,
|
||||||
|
goto text NOT NULL,
|
||||||
|
domain varchar(255) NOT NULL,
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
modified timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (address)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE mailbox (
|
||||||
|
username varchar(255) NOT NULL,
|
||||||
|
password varchar(255) NOT NULL,
|
||||||
|
name varchar(255) NOT NULL default '',
|
||||||
|
maildir varchar(255) NOT NULL default '',
|
||||||
|
quota bigint NOT NULL default '0',
|
||||||
|
local_part varchar(255) NOT NULL,
|
||||||
|
domain varchar(255) NOT NULL,
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
modified timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (username)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE domain_admins (
|
||||||
|
username varchar(255) NOT NULL,
|
||||||
|
domain varchar(255) NOT NULL,
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (username, domain)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE admin (
|
||||||
|
username varchar(255) NOT NULL,
|
||||||
|
password varchar(255) NOT NULL,
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
modified timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (username)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE log (
|
||||||
|
timestamp timestamp NOT NULL default now(),
|
||||||
|
username varchar(255) NOT NULL default '',
|
||||||
|
domain varchar(255) NOT NULL default '',
|
||||||
|
action varchar(255) NOT NULL default '',
|
||||||
|
data text NOT NULL default ''
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE vacation (
|
||||||
|
email varchar(255) NOT NULL,
|
||||||
|
subject varchar(255) NOT NULL,
|
||||||
|
body text NOT NULL,
|
||||||
|
cache text NOT NULL default '',
|
||||||
|
domain varchar(255) NOT NULL,
|
||||||
|
created timestamp NOT NULL default now(),
|
||||||
|
active boolean NOT NULL default '1',
|
||||||
|
PRIMARY KEY (email)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE quota (
|
||||||
|
username varchar(255) NOT NULL,
|
||||||
|
path varchar(100) NOT NULL,
|
||||||
|
current bigint NOT NULL default 0,
|
||||||
|
PRIMARY KEY (username, path)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE quota2 (
|
||||||
|
username varchar(100) NOT NULL,
|
||||||
|
bytes bigint NOT NULL default 0,
|
||||||
|
messages int NOT NULL default 0,
|
||||||
|
PRIMARY KEY (username)
|
||||||
|
);
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Grant permissions
|
||||||
|
sudo -u postgres psql -d "$DB_NAME" -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO $DB_USER;"
|
||||||
|
sudo -u postgres psql -d "$DB_NAME" -c "GRANT INSERT, UPDATE, DELETE ON aliases, mailbox, domain_admins, domains TO $DB_USER;"
|
||||||
|
sudo -u postgres psql -d "$DB_NAME" -c "GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $DB_USER;"
|
||||||
|
|
||||||
|
# Insert the primary domain
|
||||||
|
sudo -u postgres psql -d "$DB_NAME" -c "INSERT INTO domains (domain, description, active) VALUES ('$DOMAIN', 'Primary domain configured during setup', '1') ON CONFLICT (domain) DO NOTHING;"
|
||||||
|
|
||||||
|
success "PostgreSQL configured"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure Postfix
|
||||||
|
configure_postfix() {
|
||||||
|
info "Configuring Postfix..."
|
||||||
|
|
||||||
|
# Backup original configuration
|
||||||
|
cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
|
||||||
|
|
||||||
|
# Create main.cf
|
||||||
|
cat > /etc/postfix/main.cf << EOF
|
||||||
|
# Basic configuration
|
||||||
|
myhostname = $HOSTNAME
|
||||||
|
mydomain = $DOMAIN
|
||||||
|
myorigin = \$mydomain
|
||||||
|
inet_interfaces = all
|
||||||
|
inet_protocols = ipv4
|
||||||
|
mydestination = localhost
|
||||||
|
|
||||||
|
# Virtual domains
|
||||||
|
virtual_mailbox_domains = pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
|
||||||
|
virtual_mailbox_maps = pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
|
||||||
|
virtual_alias_maps = pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
|
||||||
|
virtual_mailbox_base = /var/mail/vhosts
|
||||||
|
virtual_minimum_uid = 100
|
||||||
|
virtual_uid_maps = static:5000
|
||||||
|
virtual_gid_maps = static:5000
|
||||||
|
|
||||||
|
# SSL/TLS configuration
|
||||||
|
smtpd_tls_cert_file = /etc/letsencrypt/live/$HOSTNAME/fullchain.pem
|
||||||
|
smtpd_tls_key_file = /etc/letsencrypt/live/$HOSTNAME/privkey.pem
|
||||||
|
smtpd_tls_security_level = may
|
||||||
|
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||||
|
smtp_tls_security_level = may
|
||||||
|
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||||
|
|
||||||
|
# SASL authentication
|
||||||
|
smtpd_sasl_type = dovecot
|
||||||
|
smtpd_sasl_path = private/auth
|
||||||
|
smtpd_sasl_auth_enable = yes
|
||||||
|
|
||||||
|
# Restrictions
|
||||||
|
smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname
|
||||||
|
smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_sender, reject_unknown_sender_domain
|
||||||
|
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unknown_recipient_domain, reject_non_fqdn_recipient
|
||||||
|
smtpd_data_restrictions = reject_unauth_pipelining
|
||||||
|
|
||||||
|
# Content filter (Amavis)
|
||||||
|
content_filter = smtp-amavis:[127.0.0.1]:10024
|
||||||
|
|
||||||
|
# Milters (OpenDKIM)
|
||||||
|
milter_protocol = 2
|
||||||
|
milter_default_action = accept
|
||||||
|
smtpd_milters = inet:localhost:8891
|
||||||
|
non_smtpd_milters = inet:localhost:8891
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
message_size_limit = 52428800
|
||||||
|
mailbox_size_limit = 0
|
||||||
|
biff = no
|
||||||
|
append_dot_mydomain = no
|
||||||
|
readme_directory = no
|
||||||
|
compatibility_level = 2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create PostgreSQL lookup files
|
||||||
|
cat > /etc/postfix/pgsql-virtual-mailbox-domains.cf << EOF
|
||||||
|
user = $DB_USER
|
||||||
|
password = $DB_PASSWORD
|
||||||
|
hosts = localhost
|
||||||
|
dbname = $DB_NAME
|
||||||
|
query = SELECT 1 FROM domains WHERE domain='%s' AND active='1'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/postfix/pgsql-virtual-mailbox-maps.cf << EOF
|
||||||
|
user = $DB_USER
|
||||||
|
password = $DB_PASSWORD
|
||||||
|
hosts = localhost
|
||||||
|
dbname = $DB_NAME
|
||||||
|
query = SELECT 1 FROM mailbox WHERE username='%s' AND active='1'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/postfix/pgsql-virtual-alias-maps.cf << EOF
|
||||||
|
user = $DB_USER
|
||||||
|
password = $DB_PASSWORD
|
||||||
|
hosts = localhost
|
||||||
|
dbname = $DB_NAME
|
||||||
|
query = SELECT goto FROM aliases WHERE address='%s' AND active='1'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chmod 640 /etc/postfix/pgsql-*.cf
|
||||||
|
chown root:postfix /etc/postfix/pgsql-*.cf
|
||||||
|
|
||||||
|
# Configure master.cf for submission and smtps
|
||||||
|
cat >> /etc/postfix/master.cf << EOF
|
||||||
|
|
||||||
|
# Submission port 587
|
||||||
|
submission inet n - y - - smtpd
|
||||||
|
-o syslog_name=postfix/submission
|
||||||
|
-o smtpd_tls_security_level=encrypt
|
||||||
|
-o smtpd_sasl_auth_enable=yes
|
||||||
|
-o smtpd_sasl_type=dovecot
|
||||||
|
-o smtpd_sasl_path=private/auth
|
||||||
|
-o smtpd_reject_unlisted_recipient=no
|
||||||
|
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
||||||
|
-o milter_macro_daemon_name=ORIGINATING
|
||||||
|
|
||||||
|
# SMTPS port 465
|
||||||
|
smtps inet n - y - - smtpd
|
||||||
|
-o syslog_name=postfix/smtps
|
||||||
|
-o smtpd_tls_wrappermode=yes
|
||||||
|
-o smtpd_sasl_auth_enable=yes
|
||||||
|
-o smtpd_sasl_type=dovecot
|
||||||
|
-o smtpd_sasl_path=private/auth
|
||||||
|
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
||||||
|
-o milter_macro_daemon_name=ORIGINATING
|
||||||
|
|
||||||
|
# Amavis
|
||||||
|
smtp-amavis unix - - - - 2 smtp
|
||||||
|
-o smtp_data_done_timeout=1200
|
||||||
|
-o smtp_send_xforward_command=yes
|
||||||
|
-o disable_dns_lookups=yes
|
||||||
|
-o max_use=20
|
||||||
|
|
||||||
|
127.0.0.1:10025 inet n - - - - smtpd
|
||||||
|
-o content_filter=
|
||||||
|
-o local_recipient_maps=
|
||||||
|
-o relay_recipient_maps=
|
||||||
|
-o smtpd_restriction_classes=
|
||||||
|
-o smtpd_delay_reject=no
|
||||||
|
-o smtpd_client_restrictions=permit_mynetworks,reject
|
||||||
|
-o smtpd_helo_restrictions=
|
||||||
|
-o smtpd_sender_restrictions=
|
||||||
|
-o smtpd_recipient_restrictions=permit_mynetworks,reject
|
||||||
|
-o smtpd_data_restrictions=reject_unauth_pipelining
|
||||||
|
-o smtpd_end_of_data_restrictions=
|
||||||
|
-o mynetworks=127.0.0.0/8
|
||||||
|
-o smtpd_error_sleep_time=0
|
||||||
|
-o smtpd_soft_error_limit=1001
|
||||||
|
-o smtpd_hard_error_limit=1000
|
||||||
|
-o smtpd_client_connection_count_limit=0
|
||||||
|
-o smtpd_client_connection_rate_limit=0
|
||||||
|
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create virtual mailbox directory
|
||||||
|
mkdir -p /var/mail/vhosts
|
||||||
|
groupadd -g 5000 vmail 2>/dev/null || true
|
||||||
|
useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -m 2>/dev/null || true
|
||||||
|
chown -R vmail:vmail /var/mail/vhosts
|
||||||
|
|
||||||
|
success "Postfix configured"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure Dovecot
|
||||||
|
configure_dovecot() {
|
||||||
|
info "Configuring Dovecot..."
|
||||||
|
|
||||||
|
# Backup configuration
|
||||||
|
cp -r /etc/dovecot /etc/dovecot.backup
|
||||||
|
|
||||||
|
# Main configuration
|
||||||
|
cat > /etc/dovecot/dovecot.conf << EOF
|
||||||
|
!include_try /usr/share/dovecot/protocols.d/*.protocol
|
||||||
|
protocols = imap pop3 lmtp
|
||||||
|
!include conf.d/*.conf
|
||||||
|
!include_try local.conf
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 10-mail.conf
|
||||||
|
cat > /etc/dovecot/conf.d/10-mail.conf << EOF
|
||||||
|
mail_location = maildir:/var/mail/vhosts/%d/%n
|
||||||
|
namespace inbox {
|
||||||
|
inbox = yes
|
||||||
|
}
|
||||||
|
mail_privileged_group = mail
|
||||||
|
mail_uid = vmail
|
||||||
|
mail_gid = vmail
|
||||||
|
first_valid_uid = 5000
|
||||||
|
last_valid_uid = 5000
|
||||||
|
first_valid_gid = 5000
|
||||||
|
last_valid_gid = 5000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 10-auth.conf
|
||||||
|
cat > /etc/dovecot/conf.d/10-auth.conf << EOF
|
||||||
|
disable_plaintext_auth = yes
|
||||||
|
auth_mechanisms = plain login
|
||||||
|
!include auth-sql.conf.ext
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# auth-sql.conf.ext
|
||||||
|
cat > /etc/dovecot/conf.d/auth-sql.conf.ext << EOF
|
||||||
|
passdb {
|
||||||
|
driver = sql
|
||||||
|
args = /etc/dovecot/dovecot-sql.conf.ext
|
||||||
|
}
|
||||||
|
userdb {
|
||||||
|
driver = static
|
||||||
|
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# dovecot-sql.conf.ext
|
||||||
|
cat > /etc/dovecot/dovecot-sql.conf.ext << EOF
|
||||||
|
driver = pgsql
|
||||||
|
connect = host=localhost dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD
|
||||||
|
default_pass_scheme = SHA512-CRYPT
|
||||||
|
password_query = SELECT username as user, password FROM mailbox WHERE username='%u' AND active='1'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 10-master.conf
|
||||||
|
cat > /etc/dovecot/conf.d/10-master.conf << EOF
|
||||||
|
service imap-login {
|
||||||
|
inet_listener imap {
|
||||||
|
port = 143
|
||||||
|
}
|
||||||
|
inet_listener imaps {
|
||||||
|
port = 993
|
||||||
|
ssl = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service pop3-login {
|
||||||
|
inet_listener pop3 {
|
||||||
|
port = 110
|
||||||
|
}
|
||||||
|
inet_listener pop3s {
|
||||||
|
port = 995
|
||||||
|
ssl = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service lmtp {
|
||||||
|
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||||||
|
mode = 0600
|
||||||
|
user = postfix
|
||||||
|
group = postfix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service auth {
|
||||||
|
unix_listener /var/spool/postfix/private/auth {
|
||||||
|
mode = 0666
|
||||||
|
user = postfix
|
||||||
|
group = postfix
|
||||||
|
}
|
||||||
|
unix_listener auth-userdb {
|
||||||
|
mode = 0600
|
||||||
|
user = vmail
|
||||||
|
group = vmail
|
||||||
|
}
|
||||||
|
user = dovecot
|
||||||
|
}
|
||||||
|
|
||||||
|
service auth-worker {
|
||||||
|
user = vmail
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 10-ssl.conf
|
||||||
|
cat > /etc/dovecot/conf.d/10-ssl.conf << EOF
|
||||||
|
ssl = required
|
||||||
|
ssl_cert = </etc/letsencrypt/live/$HOSTNAME/fullchain.pem
|
||||||
|
ssl_key = </etc/letsencrypt/live/$HOSTNAME/privkey.pem
|
||||||
|
ssl_protocols = !SSLv2 !SSLv3 !TLSv1 !TLSv1.1
|
||||||
|
ssl_cipher_list = ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384
|
||||||
|
ssl_prefer_server_ciphers = yes
|
||||||
|
ssl_dh = </etc/dovecot/dh.pem
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Generate DH parameters
|
||||||
|
openssl dhparam -out /etc/dovecot/dh.pem 2048
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chmod 600 /etc/dovecot/dovecot-sql.conf.ext
|
||||||
|
chown vmail:dovecot /etc/dovecot/dovecot-sql.conf.ext
|
||||||
|
|
||||||
|
success "Dovecot configured"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure OpenDKIM
|
||||||
|
configure_opendkim() {
|
||||||
|
info "Configuring OpenDKIM..."
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
mkdir -p /etc/opendkim/keys/$DOMAIN
|
||||||
|
|
||||||
|
# Generate DKIM key
|
||||||
|
opendkim-genkey -t -s mail -d $DOMAIN -D /etc/opendkim/keys/$DOMAIN
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chown -R opendkim:opendkim /etc/opendkim
|
||||||
|
chmod 600 /etc/opendkim/keys/$DOMAIN/mail.private
|
||||||
|
|
||||||
|
# OpenDKIM configuration
|
||||||
|
cat > /etc/opendkim.conf << EOF
|
||||||
|
Syslog yes
|
||||||
|
UMask 007
|
||||||
|
Socket inet:8891@localhost
|
||||||
|
PidFile /var/run/opendkim/opendkim.pid
|
||||||
|
OversignHeaders From
|
||||||
|
TrustAnchorFile /usr/share/dns/root.key
|
||||||
|
UserID opendkim
|
||||||
|
KeyTable /etc/opendkim/key.table
|
||||||
|
SigningTable /etc/opendkim/signing.table
|
||||||
|
ExternalIgnoreList /etc/opendkim/trusted.hosts
|
||||||
|
InternalHosts /etc/opendkim/trusted.hosts
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Key table
|
||||||
|
echo "mail._domainkey.$DOMAIN $DOMAIN:mail:/etc/opendkim/keys/$DOMAIN/mail.private" > /etc/opendkim/key.table
|
||||||
|
|
||||||
|
# Signing table
|
||||||
|
echo "*@$DOMAIN mail._domainkey.$DOMAIN" > /etc/opendkim/signing.table
|
||||||
|
|
||||||
|
# Trusted hosts
|
||||||
|
cat > /etc/opendkim/trusted.hosts << EOF
|
||||||
|
127.0.0.1
|
||||||
|
localhost
|
||||||
|
$HOSTNAME
|
||||||
|
$DOMAIN
|
||||||
|
EOF
|
||||||
|
|
||||||
|
success "OpenDKIM configured"
|
||||||
|
|
||||||
|
# Display DNS record
|
||||||
|
info "Add this TXT record to your DNS:"
|
||||||
|
echo "mail._domainkey.$DOMAIN"
|
||||||
|
cat /etc/opendkim/keys/$DOMAIN/mail.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure Amavis and SpamAssassin
|
||||||
|
configure_amavis() {
|
||||||
|
info "Configuring Amavis and SpamAssassin..."
|
||||||
|
|
||||||
|
# Update ClamAV signatures
|
||||||
|
freshclam
|
||||||
|
|
||||||
|
# Configure Amavis
|
||||||
|
cat > /etc/amavis/conf.d/15-content_filter_mode << 'EOF'
|
||||||
|
use strict;
|
||||||
|
@bypass_virus_checks_maps = (
|
||||||
|
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
|
||||||
|
@bypass_spam_checks_maps = (
|
||||||
|
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
|
||||||
|
1; # ensure a defined return
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/amavis/conf.d/20-debian_defaults << EOF
|
||||||
|
use strict;
|
||||||
|
\$MYHOME = '/var/lib/amavis';
|
||||||
|
\$mydomain = '$DOMAIN';
|
||||||
|
\$myhostname = '$HOSTNAME';
|
||||||
|
\$max_servers = 3;
|
||||||
|
\$daemon_user = 'amavis';
|
||||||
|
\$daemon_group = 'amavis';
|
||||||
|
\$inet_socket_port = 10024;
|
||||||
|
\$policy_bank{'MYNETS'} = {
|
||||||
|
originating => 1,
|
||||||
|
os_fingerprint_method => undef,
|
||||||
|
};
|
||||||
|
\$interface_policy{'10024'} = 'ORIGINATING';
|
||||||
|
\$policy_bank{'ORIGINATING'} = {
|
||||||
|
originating => 1,
|
||||||
|
allow_disclaimers => 1,
|
||||||
|
virus_admin_maps => ["virusalert\\\@\$mydomain"],
|
||||||
|
spam_admin_maps => ["virusalert\\\@\$mydomain"],
|
||||||
|
warnbadhsender => 1,
|
||||||
|
forward_method => 'smtp:[127.0.0.1]:10025',
|
||||||
|
smtpd_discard_ehlo_keywords => ['8BITMIME'],
|
||||||
|
bypass_banned_checks_maps => [1],
|
||||||
|
terminate_dsn_on_notify_success => 0,
|
||||||
|
};
|
||||||
|
\$sa_tag_level_deflt = 2.0;
|
||||||
|
\$sa_tag2_level_deflt = 6.0;
|
||||||
|
\$sa_kill_level_deflt = 6.9;
|
||||||
|
\$sa_dsn_cutoff_level = 10;
|
||||||
|
\$penpals_bonus_score = 8;
|
||||||
|
\$penpals_threshold_high = \$sa_kill_level_deflt;
|
||||||
|
\$bounce_killer_score = 100;
|
||||||
|
\$virus_admin = "postmaster\\\@\$mydomain";
|
||||||
|
\$mailfrom_notify_admin = "postmaster\\\@\$mydomain";
|
||||||
|
\$mailfrom_notify_recip = "postmaster\\\@\$mydomain";
|
||||||
|
\$mailfrom_notify_spamadmin = "postmaster\\\@\$mydomain";
|
||||||
|
\$mailfrom_to_quarantine = '';
|
||||||
|
\@lookup_sql_dsn = ( ['DBI:Pg:database=$DB_NAME;host=127.0.0.1;port=5432', '$DB_USER', '$DB_PASSWORD'] );
|
||||||
|
\$enable_db = 1;
|
||||||
|
\$enable_global_cache = 1;
|
||||||
|
\$inet_socket_bind = '127.0.0.1';
|
||||||
|
@inet_acl = qw(127.0.0.1);
|
||||||
|
1;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Configure SpamAssassin
|
||||||
|
cat > /etc/spamassassin/local.cf << EOF
|
||||||
|
rewrite_header Subject *****SPAM*****
|
||||||
|
report_safe 0
|
||||||
|
required_score 5.0
|
||||||
|
use_bayes 1
|
||||||
|
use_bayes_rules 1
|
||||||
|
bayes_auto_learn 1
|
||||||
|
skip_rbl_checks 0
|
||||||
|
use_razor2 1
|
||||||
|
use_dcc 1
|
||||||
|
use_pyzor 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add amavis user to clamav group
|
||||||
|
usermod -a -G clamav amavis
|
||||||
|
|
||||||
|
success "Amavis and SpamAssassin configured"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get Let's Encrypt certificates
|
||||||
|
get_ssl_certificates() {
|
||||||
|
info "Obtaining Let's Encrypt certificates..."
|
||||||
|
|
||||||
|
# Stop services that might be using port 80
|
||||||
|
systemctl stop apache2 2>/dev/null || true
|
||||||
|
systemctl stop nginx 2>/dev/null || true
|
||||||
|
|
||||||
|
# Get certificate
|
||||||
|
certbot certonly --standalone -d $HOSTNAME --email $ADMIN_EMAIL --agree-tos --non-interactive
|
||||||
|
|
||||||
|
if [[ ! -f "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" ]]; then
|
||||||
|
error "Failed to obtain SSL certificate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up auto-renewal
|
||||||
|
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
|
||||||
|
|
||||||
|
success "SSL certificates obtained"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install PostfixAdmin
|
||||||
|
install_postfixadmin() {
|
||||||
|
info "Installing PostfixAdmin..."
|
||||||
|
|
||||||
|
# Download PostfixAdmin
|
||||||
|
cd /tmp
|
||||||
|
wget https://github.com/postfixadmin/postfixadmin/archive/postfixadmin-3.3.11.tar.gz
|
||||||
|
tar -xzf postfixadmin-3.3.11.tar.gz
|
||||||
|
mv postfixadmin-postfixadmin-3.3.11 $WEBROOT
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chown -R www-data:www-data $WEBROOT
|
||||||
|
chmod -R 755 $WEBROOT
|
||||||
|
|
||||||
|
# Create PostfixAdmin configuration
|
||||||
|
cat > $WEBROOT/config.local.php << EOF
|
||||||
|
<?php
|
||||||
|
\$CONF['configured'] = true;
|
||||||
|
\$CONF['setup_password'] = '$(php -r "echo password_hash('$POSTFIXADMIN_PASSWORD', PASSWORD_DEFAULT);")';
|
||||||
|
\$CONF['postfix_admin_url'] = 'https://$HOSTNAME/postfixadmin';
|
||||||
|
\$CONF['postfix_admin_path'] = '$WEBROOT';
|
||||||
|
\$CONF['default_language'] = 'en';
|
||||||
|
\$CONF['database_type'] = 'pgsql';
|
||||||
|
\$CONF['database_host'] = 'localhost';
|
||||||
|
\$CONF['database_user'] = '$DB_USER';
|
||||||
|
\$CONF['database_password'] = '$DB_PASSWORD';
|
||||||
|
\$CONF['database_name'] = '$DB_NAME';
|
||||||
|
\$CONF['admin_email'] = '$ADMIN_EMAIL';
|
||||||
|
\$CONF['encrypt'] = 'sha512.crypt';
|
||||||
|
\$CONF['dovecotpw'] = "/usr/bin/doveadm pw";
|
||||||
|
\$CONF['page_size'] = '10';
|
||||||
|
\$CONF['default_aliases'] = array (
|
||||||
|
'abuse' => 'abuse@change-this-to-your.domain.tld',
|
||||||
|
'hostmaster' => 'hostmaster@change-this-to-your.domain.tld',
|
||||||
|
'postmaster' => 'postmaster@change-this-to-your.domain.tld',
|
||||||
|
'webmaster' => 'webmaster@change-this-to-your.domain.tld'
|
||||||
|
);
|
||||||
|
\$CONF['domain_path'] = 'YES';
|
||||||
|
\$CONF['domain_in_mailbox'] = 'YES';
|
||||||
|
\$CONF['maildir_name_hook'] = 'maildir_name_hook';
|
||||||
|
function maildir_name_hook(\$domain, \$user) {
|
||||||
|
return \$domain . '/' . \$user . '/';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Configure Apache virtual host
|
||||||
|
cat > /etc/apache2/sites-available/postfixadmin.conf << EOF
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName $HOSTNAME
|
||||||
|
Redirect permanent / https://$HOSTNAME/
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
<VirtualHost *:443>
|
||||||
|
ServerName $HOSTNAME
|
||||||
|
DocumentRoot $WEBROOT/public
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateFile /etc/letsencrypt/live/$HOSTNAME/fullchain.pem
|
||||||
|
SSLCertificateKeyFile /etc/letsencrypt/live/$HOSTNAME/privkey.pem
|
||||||
|
|
||||||
|
<Directory $WEBROOT/public>
|
||||||
|
Options -Indexes
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog \${APACHE_LOG_DIR}/postfixadmin_error.log
|
||||||
|
CustomLog \${APACHE_LOG_DIR}/postfixadmin_access.log combined
|
||||||
|
</VirtualHost>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Enable Apache modules and site
|
||||||
|
a2enmod ssl
|
||||||
|
a2enmod rewrite
|
||||||
|
a2ensite postfixadmin
|
||||||
|
a2dissite 000-default
|
||||||
|
|
||||||
|
success "PostfixAdmin installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure firewall
|
||||||
|
configure_firewall() {
|
||||||
|
info "Configuring firewall..."
|
||||||
|
|
||||||
|
# Reset UFW
|
||||||
|
ufw --force reset
|
||||||
|
|
||||||
|
# Default policies
|
||||||
|
ufw default deny incoming
|
||||||
|
ufw default allow outgoing
|
||||||
|
|
||||||
|
# Allow SSH
|
||||||
|
ufw allow ssh
|
||||||
|
|
||||||
|
# Allow email ports
|
||||||
|
ufw allow 25/tcp # SMTP
|
||||||
|
ufw allow 587/tcp # Submission
|
||||||
|
ufw allow 465/tcp # SMTPS
|
||||||
|
ufw allow 110/tcp # POP3
|
||||||
|
ufw allow 995/tcp # POP3S
|
||||||
|
ufw allow 143/tcp # IMAP
|
||||||
|
ufw allow 993/tcp # IMAPS
|
||||||
|
|
||||||
|
# Allow web ports
|
||||||
|
ufw allow 80/tcp # HTTP
|
||||||
|
ufw allow 443/tcp # HTTPS
|
||||||
|
|
||||||
|
# Enable UFW
|
||||||
|
ufw --force enable
|
||||||
|
|
||||||
|
success "Firewall configured"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start and enable services
|
||||||
|
start_services() {
|
||||||
|
info "Starting and enabling services..."
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# Start and enable services
|
||||||
|
systemctl enable --now postgresql
|
||||||
|
systemctl enable --now postfix
|
||||||
|
systemctl enable --now dovecot
|
||||||
|
systemctl enable --now amavis
|
||||||
|
systemctl enable --now spamassassin
|
||||||
|
systemctl enable --now clamav-daemon
|
||||||
|
systemctl enable --now clamav-freshclam
|
||||||
|
systemctl enable --now opendkim
|
||||||
|
systemctl enable --now apache2
|
||||||
|
|
||||||
|
success "All services started and enabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display final information
|
||||||
|
display_final_info() {
|
||||||
|
success "Email server setup completed!"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}=== Setup Summary ===${NC}"
|
||||||
|
echo "Primary Domain: $DOMAIN"
|
||||||
|
echo "Hostname: $HOSTNAME"
|
||||||
|
echo "Admin Email: $ADMIN_EMAIL"
|
||||||
|
echo "PostfixAdmin URL: https://$HOSTNAME/postfixadmin/"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}=== DNS Records to Add for $DOMAIN ===${NC}"
|
||||||
|
echo "A $HOSTNAME [Your server IP]"
|
||||||
|
echo "MX $DOMAIN $HOSTNAME"
|
||||||
|
echo "TXT $DOMAIN \"v=spf1 mx ~all\""
|
||||||
|
echo "TXT _dmarc.$DOMAIN \"v=DMARC1; p=none; rua=mailto:dmarc@$DOMAIN\""
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}=== DKIM DNS Record for $DOMAIN ===${NC}"
|
||||||
|
cat /etc/opendkim/keys/$DOMAIN/mail.txt
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}=== Next Steps ===${NC}"
|
||||||
|
echo "1. Add the DNS records shown above"
|
||||||
|
echo "2. Visit https://$HOSTNAME/postfixadmin/setup.php to complete PostfixAdmin setup"
|
||||||
|
echo "3. Create your first domain and mailbox in PostfixAdmin"
|
||||||
|
echo "4. Test email sending and receiving"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}=== Multiple Domain Support ===${NC}"
|
||||||
|
echo "This server supports unlimited virtual domains!"
|
||||||
|
echo
|
||||||
|
echo "To add additional domains:"
|
||||||
|
echo "1. Run: ./add-domain.sh newdomain.com"
|
||||||
|
echo "2. Add the provided DNS records"
|
||||||
|
echo "3. Configure the domain in PostfixAdmin"
|
||||||
|
echo "4. Create mailboxes for the new domain"
|
||||||
|
echo
|
||||||
|
echo "Each domain can have its own:"
|
||||||
|
echo " • Independent mailboxes and aliases"
|
||||||
|
echo " • DKIM signing for authentication"
|
||||||
|
echo " • Custom quotas and limits"
|
||||||
|
echo " • Application SMTP access"
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}=== Application SMTP Configuration ===${NC}"
|
||||||
|
echo "Your applications can send email using these settings:"
|
||||||
|
echo " Host: $HOSTNAME"
|
||||||
|
echo " Port: 587 (STARTTLS) or 465 (SSL/TLS)"
|
||||||
|
echo " Username: mailbox@yourdomain.com (full email address)"
|
||||||
|
echo " Password: [mailbox password from PostfixAdmin]"
|
||||||
|
echo " Security: STARTTLS or SSL/TLS"
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}Setup completed successfully!${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
echo -e "${BLUE}Email Server Setup Script${NC}"
|
||||||
|
echo "========================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
check_root
|
||||||
|
get_configuration
|
||||||
|
update_system
|
||||||
|
install_packages
|
||||||
|
configure_postgresql
|
||||||
|
get_ssl_certificates
|
||||||
|
configure_postfix
|
||||||
|
configure_dovecot
|
||||||
|
configure_opendkim
|
||||||
|
configure_amavis
|
||||||
|
install_postfixadmin
|
||||||
|
configure_firewall
|
||||||
|
start_services
|
||||||
|
display_final_info
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
||||||
262
test-email-server.sh
Executable file
262
test-email-server.sh
Executable file
@@ -0,0 +1,262 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Email Server Test Script
|
||||||
|
# This script helps test various components of your email server
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DOMAIN=""
|
||||||
|
HOSTNAME=""
|
||||||
|
TEST_EMAIL=""
|
||||||
|
|
||||||
|
# Get configuration
|
||||||
|
get_config() {
|
||||||
|
if [[ -z "$DOMAIN" ]]; then
|
||||||
|
read -p "Enter your domain (e.g., example.com): " DOMAIN
|
||||||
|
fi
|
||||||
|
if [[ -z "$HOSTNAME" ]]; then
|
||||||
|
read -p "Enter your hostname (e.g., mail.example.com): " HOSTNAME
|
||||||
|
fi
|
||||||
|
if [[ -z "$TEST_EMAIL" ]]; then
|
||||||
|
read -p "Enter test email address: " TEST_EMAIL
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test functions
|
||||||
|
test_dns() {
|
||||||
|
echo -e "${BLUE}Testing DNS Configuration...${NC}"
|
||||||
|
|
||||||
|
echo "Checking MX record for $DOMAIN:"
|
||||||
|
if dig +short MX $DOMAIN | grep -q $HOSTNAME; then
|
||||||
|
echo -e "${GREEN}✓ MX record found${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ MX record not found or incorrect${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking A record for $HOSTNAME:"
|
||||||
|
if dig +short A $HOSTNAME | grep -q .; then
|
||||||
|
echo -e "${GREEN}✓ A record found${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ A record not found${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking SPF record for $DOMAIN:"
|
||||||
|
if dig +short TXT $DOMAIN | grep -q "v=spf1"; then
|
||||||
|
echo -e "${GREEN}✓ SPF record found${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ SPF record not found${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking DKIM record for $DOMAIN:"
|
||||||
|
if dig +short TXT mail._domainkey.$DOMAIN | grep -q "v=DKIM1"; then
|
||||||
|
echo -e "${GREEN}✓ DKIM record found${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ DKIM record not found${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checking DMARC record for $DOMAIN:"
|
||||||
|
if dig +short TXT _dmarc.$DOMAIN | grep -q "v=DMARC1"; then
|
||||||
|
echo -e "${GREEN}✓ DMARC record found${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ DMARC record not found${NC}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_services() {
|
||||||
|
echo -e "${BLUE}Testing Service Status...${NC}"
|
||||||
|
|
||||||
|
services=("postfix" "dovecot" "amavis" "spamassassin" "clamav-daemon" "opendkim" "apache2" "postgresql")
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
if systemctl is-active --quiet $service; then
|
||||||
|
echo -e "${GREEN}✓ $service is running${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ $service is not running${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_ports() {
|
||||||
|
echo -e "${BLUE}Testing Port Connectivity...${NC}"
|
||||||
|
|
||||||
|
ports=("25:SMTP" "587:Submission" "465:SMTPS" "143:IMAP" "993:IMAPS" "110:POP3" "995:POP3S")
|
||||||
|
|
||||||
|
for port_info in "${ports[@]}"; do
|
||||||
|
port=$(echo $port_info | cut -d: -f1)
|
||||||
|
name=$(echo $port_info | cut -d: -f2)
|
||||||
|
|
||||||
|
if nc -z localhost $port 2>/dev/null; then
|
||||||
|
echo -e "${GREEN}✓ Port $port ($name) is open${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Port $port ($name) is closed${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_ssl() {
|
||||||
|
echo -e "${BLUE}Testing SSL Certificates...${NC}"
|
||||||
|
|
||||||
|
if [[ -f "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" ]]; then
|
||||||
|
echo -e "${GREEN}✓ SSL certificate found${NC}"
|
||||||
|
|
||||||
|
# Check certificate validity
|
||||||
|
if openssl x509 -in /etc/letsencrypt/live/$HOSTNAME/fullchain.pem -noout -checkend 86400; then
|
||||||
|
echo -e "${GREEN}✓ SSL certificate is valid${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ SSL certificate is expired or expiring soon${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check certificate CN
|
||||||
|
cn=$(openssl x509 -in /etc/letsencrypt/live/$HOSTNAME/fullchain.pem -noout -subject | grep -o "CN=[^,]*" | cut -d= -f2)
|
||||||
|
if [[ "$cn" == "$HOSTNAME" ]]; then
|
||||||
|
echo -e "${GREEN}✓ SSL certificate CN matches hostname${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ SSL certificate CN ($cn) doesn't match hostname ($HOSTNAME)${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ SSL certificate not found${NC}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_dkim() {
|
||||||
|
echo -e "${BLUE}Testing DKIM Configuration...${NC}"
|
||||||
|
|
||||||
|
# Find all domains with DKIM keys
|
||||||
|
dkim_domains=()
|
||||||
|
if [[ -d "/etc/opendkim/keys" ]]; then
|
||||||
|
while IFS= read -r -d '' domain_dir; do
|
||||||
|
domain=$(basename "$domain_dir")
|
||||||
|
dkim_domains+=("$domain")
|
||||||
|
done < <(find /etc/opendkim/keys -mindepth 1 -maxdepth 1 -type d -print0)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#dkim_domains[@]} -eq 0 ]]; then
|
||||||
|
echo -e "${RED}✗ No DKIM domains found${NC}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
for domain in "${dkim_domains[@]}"; do
|
||||||
|
if opendkim-testkey -d "$domain" -s mail -vvv 2>&1 | grep -q "key OK"; then
|
||||||
|
echo -e "${GREEN}✓ DKIM key test passed for $domain${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ DKIM key test failed for $domain${NC}"
|
||||||
|
echo " Run: opendkim-testkey -d $domain -s mail -vvv"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_authentication() {
|
||||||
|
echo -e "${BLUE}Testing SMTP Authentication...${NC}"
|
||||||
|
|
||||||
|
if echo "quit" | telnet localhost 587 2>/dev/null | grep -q "250-AUTH"; then
|
||||||
|
echo -e "${GREEN}✓ SMTP AUTH is available${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ SMTP AUTH is not available${NC}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_database() {
|
||||||
|
echo -e "${BLUE}Testing Database Connection...${NC}"
|
||||||
|
|
||||||
|
if sudo -u postgres psql -d postfix -c "SELECT 1;" >/dev/null 2>&1; then
|
||||||
|
echo -e "${GREEN}✓ Database connection successful${NC}"
|
||||||
|
|
||||||
|
# Check tables
|
||||||
|
tables=$(sudo -u postgres psql -d postfix -t -c "SELECT tablename FROM pg_tables WHERE schemaname='public';" | xargs)
|
||||||
|
if [[ "$tables" == *"domains"* && "$tables" == *"mailbox"* && "$tables" == *"aliases"* ]]; then
|
||||||
|
echo -e "${GREEN}✓ Required database tables exist${NC}"
|
||||||
|
|
||||||
|
# Check configured domains
|
||||||
|
domain_count=$(sudo -u postgres psql -d postfix -t -c "SELECT COUNT(*) FROM domains WHERE active='1';" | xargs)
|
||||||
|
echo -e "${GREEN}✓ Database has $domain_count active domain(s)${NC}"
|
||||||
|
|
||||||
|
if [[ $domain_count -gt 0 ]]; then
|
||||||
|
echo "Active domains:"
|
||||||
|
sudo -u postgres psql -d postfix -t -c "SELECT ' - ' || domain FROM domains WHERE active='1';" | grep -v "^$"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Required database tables missing${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Database connection failed${NC}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
test_email_flow() {
|
||||||
|
echo -e "${BLUE}Testing Email Flow...${NC}"
|
||||||
|
|
||||||
|
if [[ -n "$TEST_EMAIL" ]]; then
|
||||||
|
echo "Sending test email to $TEST_EMAIL..."
|
||||||
|
if echo "This is a test email from your email server." | mail -s "Email Server Test" $TEST_EMAIL; then
|
||||||
|
echo -e "${GREEN}✓ Test email sent${NC}"
|
||||||
|
echo "Check your inbox for the test email"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed to send test email${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}! No test email provided, skipping email flow test${NC}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
check_logs() {
|
||||||
|
echo -e "${BLUE}Recent Log Entries...${NC}"
|
||||||
|
|
||||||
|
echo "=== Postfix Logs (last 10 lines) ==="
|
||||||
|
tail -10 /var/log/mail.log | grep postfix || echo "No recent postfix logs"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Dovecot Logs (last 5 lines) ==="
|
||||||
|
tail -5 /var/log/mail.log | grep dovecot || echo "No recent dovecot logs"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Setup Log (last 5 lines) ==="
|
||||||
|
if [[ -f "/var/log/email-server-setup.log" ]]; then
|
||||||
|
tail -5 /var/log/email-server-setup.log
|
||||||
|
else
|
||||||
|
echo "Setup log not found"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
echo -e "${BLUE}Email Server Test Suite${NC}"
|
||||||
|
echo "======================"
|
||||||
|
echo
|
||||||
|
|
||||||
|
get_config
|
||||||
|
|
||||||
|
test_dns
|
||||||
|
test_services
|
||||||
|
test_ports
|
||||||
|
test_ssl
|
||||||
|
test_dkim
|
||||||
|
test_authentication
|
||||||
|
test_database
|
||||||
|
test_email_flow
|
||||||
|
check_logs
|
||||||
|
|
||||||
|
echo -e "${GREEN}Testing completed!${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Online testing tools:${NC}"
|
||||||
|
echo "- MX Toolbox: https://mxtoolbox.com/"
|
||||||
|
echo "- Mail Tester: https://www.mail-tester.com/"
|
||||||
|
echo "- DKIM Validator: https://dkimvalidator.com/"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user