#!/bin/sh # SecuBox Mail Server Controller VERSION="1.0.0" CONFIG="mailserver" LIB_DIR="/usr/lib/mailserver" # Load libraries . "$LIB_DIR/container.sh" . "$LIB_DIR/users.sh" . "$LIB_DIR/mesh.sh" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "${GREEN}[MAIL]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; } uci_get() { uci -q get ${CONFIG}.$1; } # ============================================================================ # Install / Setup # ============================================================================ cmd_install() { local container=$(uci_get main.container) container="${container:-mailserver}" local data_path=$(uci_get main.data_path) data_path="${data_path:-/srv/mailserver}" log "Installing mail server..." # Create container container_create "$container" "$data_path" local rc=$? [ $rc -ne 0 ] && return $rc # Start container log "Starting container..." lxc-start -n "$container" sleep 5 # Run setup log "Installing mail packages..." lxc-attach -n "$container" -- /root/setup.sh log "Installation complete!" echo "" echo "Next steps:" echo " 1. Configure domain: uci set mailserver.main.domain='yourdomain.com'" echo " 2. Set up DNS: dnsctl mail-setup" echo " 3. Add SSL cert: mailctl ssl-setup" echo " 4. Add users: mailctl user-add user@yourdomain.com" echo " 5. Enable: uci set mailserver.main.enabled=1 && uci commit" } cmd_uninstall() { local container=$(uci_get main.container) container="${container:-mailserver}" warn "This will remove the mail server container and all data!" echo "Continue? (yes/no)" read confirm [ "$confirm" != "yes" ] && { echo "Aborted"; return 1; } log "Stopping container..." lxc-stop -n "$container" 2>/dev/null log "Removing container..." rm -rf "/srv/lxc/$container" log "Mail server removed. Data in $(uci_get main.data_path) preserved." } # ============================================================================ # Service Control # ============================================================================ cmd_start() { /etc/init.d/mailserver start } cmd_stop() { /etc/init.d/mailserver stop } cmd_restart() { /etc/init.d/mailserver stop sleep 2 /etc/init.d/mailserver start } cmd_status() { local container=$(uci_get main.container) container="${container:-mailserver}" local domain=$(uci_get main.domain) local hostname=$(uci_get main.hostname) echo "" echo "========================================" echo " SecuBox Mail Server v$VERSION" echo "========================================" echo "" # Container status local state="stopped" lxc-info -n "$container" 2>/dev/null | grep -q "RUNNING" && state="running" echo " Container: $container ($state)" echo " Domain: ${domain:-not set}" echo " Hostname: ${hostname:-mail}.${domain:-example.com}" echo "" # Port status echo " Ports:" local ports="25 587 465 993 995" for port in $ports; do if netstat -tln 2>/dev/null | grep -q ":$port "; then echo -e " $port: ${GREEN}listening${NC}" else echo -e " $port: ${RED}closed${NC}" fi done echo "" # User count local data_path=$(uci_get main.data_path) data_path="${data_path:-/srv/mailserver}" local user_count=$(wc -l < "$data_path/config/users" 2>/dev/null || echo "0") echo " Users: $user_count" # Storage local storage=$(du -sh "$data_path" 2>/dev/null | awk '{print $1}') echo " Storage: ${storage:-0}" echo "" } # ============================================================================ # User Commands # ============================================================================ cmd_user() { local action="$1" shift case "$action" in add) user_add "$@" ;; del) user_del "$@" ;; list) user_list ;; passwd) user_passwd "$@" ;; *) echo "User commands:" echo " user add Add mail user" echo " user del Delete mail user" echo " user list List all users" echo " user passwd Change password" ;; esac } cmd_alias() { local action="$1" shift case "$action" in add) alias_add "$@" ;; list) alias_list ;; *) echo "Alias commands:" echo " alias add Add email alias" echo " alias list List aliases" ;; esac } # ============================================================================ # SSL Certificate # ============================================================================ cmd_ssl_setup() { local container=$(uci_get main.container) container="${container:-mailserver}" local domain=$(uci_get main.domain) local hostname=$(uci_get main.hostname) hostname="${hostname:-mail}" local fqdn="${hostname}.${domain}" log "Setting up SSL for $fqdn..." # Check if acme.sh available if ! command -v acme.sh >/dev/null 2>&1; then error "acme.sh not installed. Install with: opkg install acme acme-dnsapi" return 1 fi # Use DNS-01 via dnsctl log "Requesting certificate via DNS-01..." dnsctl acme-dns01 "$fqdn" local cert_dir="/root/.acme.sh/${fqdn}" local data_path=$(uci_get main.data_path) data_path="${data_path:-/srv/mailserver}" if [ -f "$cert_dir/fullchain.cer" ]; then cp "$cert_dir/fullchain.cer" "$data_path/ssl/fullchain.pem" cp "$cert_dir/${fqdn}.key" "$data_path/ssl/privkey.pem" chmod 600 "$data_path/ssl/"*.pem log "SSL certificates installed to $data_path/ssl/" log "Restarting mail services..." cmd_restart else error "Certificate generation failed" return 1 fi } cmd_ssl_status() { local data_path=$(uci_get main.data_path) data_path="${data_path:-/srv/mailserver}" if [ -f "$data_path/ssl/fullchain.pem" ]; then echo "SSL Certificate:" openssl x509 -in "$data_path/ssl/fullchain.pem" -noout -subject -dates 2>/dev/null | sed 's/^/ /' else echo "No SSL certificate installed" fi } # ============================================================================ # DNS Integration # ============================================================================ cmd_dns_setup() { local hostname=$(uci_get main.hostname) hostname="${hostname:-mail}" log "Setting up DNS records..." dnsctl mail-setup "$hostname" } # ============================================================================ # Mesh Commands # ============================================================================ cmd_mesh() { local action="$1" shift case "$action" in backup) mesh_backup ;; restore) mesh_restore "$@" ;; sync) mesh_sync "$@" ;; add-peer) mesh_add_peer "$@" ;; peers) mesh_list_peers ;; enable) uci set $CONFIG.mesh.enabled=1 uci commit $CONFIG log "Mesh sync enabled" ;; disable) uci set $CONFIG.mesh.enabled=0 uci commit $CONFIG log "Mesh sync disabled" ;; *) echo "Mesh commands:" echo " mesh backup Create backup for mesh" echo " mesh restore Restore from backup" echo " mesh sync [push|pull] Sync with peers" echo " mesh add-peer Add mesh peer" echo " mesh peers List mesh peers" echo " mesh enable Enable mesh sync" echo " mesh disable Disable mesh sync" ;; esac } # ============================================================================ # Logs & Diagnostics # ============================================================================ cmd_logs() { local lines="${1:-50}" local container=$(uci_get main.container) container="${container:-mailserver}" lxc-attach -n "$container" -- tail -n "$lines" /var/log/mail.log 2>/dev/null } cmd_test() { local email="$1" [ -z "$email" ] && { echo "Usage: mailctl test "; return 1; } local container=$(uci_get main.container) container="${container:-mailserver}" local domain=$(uci_get main.domain) local hostname=$(uci_get main.hostname) log "Sending test email to $email..." lxc-attach -n "$container" -- sh -c "echo 'Test from SecuBox Mail Server' | mail -s 'Test Email' '$email'" log "Test email sent. Check inbox." } # ============================================================================ # Webmail Integration # ============================================================================ cmd_webmail() { local action="${1:-status}" case "$action" in status) local webmail=$(uci_get webmail.container) webmail="${webmail:-secubox-webmail}" if docker ps 2>/dev/null | grep -q "$webmail"; then local port=$(uci_get webmail.port) echo "Webmail: Running on port ${port:-8026}" else echo "Webmail: Not running" fi ;; configure) local domain=$(uci_get main.domain) local hostname=$(uci_get main.hostname) hostname="${hostname:-mail}" local fqdn="${hostname}.${domain}" log "Configuring webmail to use $fqdn..." local webmail=$(uci_get webmail.container) webmail="${webmail:-secubox-webmail}" # Update Roundcube config docker exec "$webmail" sh -c "cat > /var/www/html/config/config.docker.inc.php << EOF [options] Setup: install Create and configure mail server uninstall Remove mail server dns-setup Set up MX/SPF/DKIM/DMARC via dnsctl ssl-setup Obtain SSL certificate Service: start Start mail server stop Stop mail server restart Restart mail server status Show server status Users: user add Add mail user user del Delete mail user user list List all users user passwd Change password Aliases: alias add Add email alias alias list List aliases Mesh Backup: mesh backup Create backup mesh restore Restore from backup mesh sync Sync with peers mesh peers List mesh peers Webmail: webmail status Show webmail status webmail configure Configure for this server Diagnostics: logs [lines] View mail logs test Send test email ssl-status Show SSL cert info Examples: mailctl install mailctl user add user@example.com mailctl dns-setup mailctl mesh sync push EOF } # ============================================================================ # Main # ============================================================================ case "${1:-}" in install) shift; cmd_install "$@" ;; uninstall) shift; cmd_uninstall "$@" ;; start) shift; cmd_start "$@" ;; stop) shift; cmd_stop "$@" ;; restart) shift; cmd_restart "$@" ;; status) shift; cmd_status "$@" ;; user) shift; cmd_user "$@" ;; alias) shift; cmd_alias "$@" ;; ssl-setup) shift; cmd_ssl_setup "$@" ;; ssl-status) shift; cmd_ssl_status "$@" ;; dns-setup) shift; cmd_dns_setup "$@" ;; mesh) shift; cmd_mesh "$@" ;; webmail) shift; cmd_webmail "$@" ;; logs) shift; cmd_logs "$@" ;; test) shift; cmd_test "$@" ;; help|--help|-h|'') show_help ;; *) error "Unknown command: $1"; show_help >&2; exit 1 ;; esac exit 0