Files
EmailHostingPlatform/manage-domains.sh
Tommy Parnell e9c35bdc8d init
2025-08-03 11:36:44 -04:00

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