387 lines
11 KiB
Bash
Executable File
387 lines
11 KiB
Bash
Executable File
#!/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
|