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