#!/bin/bash ################################################################################ # Email Functions Library ################################################################################ # Shared functions for email troubleshooting modules ################################################################################ # Detect MTA (Mail Transfer Agent) detect_mta() { if command -v exim &>/dev/null; then echo "exim" elif command -v postfix &>/dev/null || [ -f /etc/postfix/main.cf ]; then echo "postfix" elif command -v sendmail &>/dev/null; then echo "sendmail" else echo "unknown" fi } # Get mail log path based on system get_mail_log_path() { local control_panel=$(detect_control_panel 2>/dev/null || echo "unknown") # Try common log locations in order of likelihood if [ "$control_panel" = "cpanel" ]; then if [ -f /var/log/exim_mainlog ]; then echo "/var/log/exim_mainlog" elif [ -f /var/log/exim/mainlog ]; then echo "/var/log/exim/mainlog" fi elif [ "$control_panel" = "plesk" ]; then if [ -f /var/log/maillog ]; then echo "/var/log/maillog" fi else # Standalone or other if [ -f /var/log/mail.log ]; then echo "/var/log/mail.log" elif [ -f /var/log/maillog ]; then echo "/var/log/maillog" elif [ -f /var/log/exim_mainlog ]; then echo "/var/log/exim_mainlog" fi fi } # Get mailbox base path get_mailbox_base_path() { local control_panel=$(detect_control_panel 2>/dev/null || echo "unknown") case "$control_panel" in cpanel) echo "/home" ;; plesk) echo "/var/qmail/mailnames" ;; *) # Try common locations if [ -d /home/vmail ]; then echo "/home/vmail" elif [ -d /var/mail ]; then echo "/var/mail" else echo "/home" fi ;; esac } # Validate email address format validate_email() { local email="$1" if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then return 0 else return 1 fi } # Extract domain from email address get_email_domain() { local email="$1" echo "${email##*@}" } # Extract local part from email address get_email_local() { local email="$1" echo "${email%%@*}" } # Convert bytes to human-readable format format_size() { local bytes="$1" if [ "$bytes" -lt 1024 ]; then echo "${bytes}B" elif [ "$bytes" -lt 1048576 ]; then echo "$((bytes / 1024))KB" elif [ "$bytes" -lt 1073741824 ]; then echo "$((bytes / 1048576))MB" else echo "$((bytes / 1073741824))GB" fi } # Check if MTA service is running check_mta_running() { local mta=$(detect_mta) case "$mta" in exim) if systemctl is-active --quiet exim 2>/dev/null || service exim status &>/dev/null; then return 0 fi ;; postfix) if systemctl is-active --quiet postfix 2>/dev/null || service postfix status &>/dev/null; then return 0 fi ;; sendmail) if systemctl is-active --quiet sendmail 2>/dev/null || service sendmail status &>/dev/null; then return 0 fi ;; esac return 1 } # Get MTA version get_mta_version() { local mta=$(detect_mta) case "$mta" in exim) exim -bV 2>/dev/null | head -1 | awk '{print $3}' ;; postfix) postconf mail_version 2>/dev/null | awk '{print $3}' ;; sendmail) sendmail -d0.1 2>&1 | head -1 | awk '{print $2}' ;; *) echo "unknown" ;; esac } # Get mail queue count get_queue_count() { local mta=$(detect_mta) case "$mta" in exim) exim -bpc 2>/dev/null || echo "0" ;; postfix) postqueue -p 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '(' | tr -d ')' ;; *) echo "0" ;; esac } # Check DNS record check_dns_record() { local domain="$1" local record_type="$2" # A, MX, TXT, etc. if command -v dig &>/dev/null; then dig +short "$domain" "$record_type" 2>/dev/null elif command -v host &>/dev/null; then host -t "$record_type" "$domain" 2>/dev/null | grep -v "has no" | awk '{print $NF}' elif command -v nslookup &>/dev/null; then nslookup -type="$record_type" "$domain" 2>/dev/null | grep -A10 "answer:" | grep -v "answer:" fi } # Get server's primary IP get_primary_ip() { # Try multiple methods local ip="" # Method 1: hostname -i ip=$(hostname -I 2>/dev/null | awk '{print $1}') # Method 2: ip route if [ -z "$ip" ]; then ip=$(ip route get 8.8.8.8 2>/dev/null | awk '{print $7; exit}') fi # Method 3: ifconfig if [ -z "$ip" ]; then ip=$(ifconfig 2>/dev/null | grep 'inet ' | grep -v '127.0.0.1' | head -1 | awk '{print $2}' | cut -d: -f2) fi echo "$ip" } # Check if IP is valid format is_valid_ip() { local ip="$1" if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then return 0 else return 1 fi } # Get reverse DNS (PTR) for IP get_reverse_dns() { local ip="$1" if command -v dig &>/dev/null; then dig +short -x "$ip" 2>/dev/null | sed 's/\.$//' elif command -v host &>/dev/null; then host "$ip" 2>/dev/null | grep "pointer" | awk '{print $NF}' | sed 's/\.$//' fi } # Send test email send_test_email() { local to="$1" local subject="${2:-Test Email from Server Toolkit}" local body="${3:-This is a test email sent from the Server Toolkit.}" local from="${4:-root@$(hostname)}" if command -v mail &>/dev/null; then echo "$body" | mail -s "$subject" -r "$from" "$to" return $? elif command -v sendmail &>/dev/null; then { echo "From: $from" echo "To: $to" echo "Subject: $subject" echo "" echo "$body" } | sendmail -t return $? else return 1 fi } # Parse email from Exim log line parse_exim_email() { local log_line="$1" # Extract email addresses from various Exim log formats echo "$log_line" | grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -1 } # Get date range for log analysis (default: last 24 hours) get_log_date_range() { local hours="${1:-24}" date -d "$hours hours ago" "+%Y-%m-%d %H:%M:%S" } # Count messages by sender count_by_sender() { local log_file="$1" local min_date="${2:-}" if [ -n "$min_date" ]; then awk -v min_date="$min_date" '$0 >= min_date' "$log_file" | \ grep "<=" | \ grep -oE '\<[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\>' | \ sort | uniq -c | sort -rn else grep "<=" "$log_file" | \ grep -oE '\<[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\>' | \ sort | uniq -c | sort -rn fi } # Export to detect_control_panel if not already available if ! type detect_control_panel &>/dev/null; then detect_control_panel() { if [ -f /usr/local/cpanel/version ]; then echo "cpanel" elif [ -f /usr/local/psa/version ]; then echo "plesk" else echo "standalone" fi } fi # Export functions for use in subshells export -f detect_mta export -f get_mail_log_path export -f get_mailbox_base_path export -f validate_email export -f get_email_domain export -f get_email_local export -f format_size export -f check_mta_running export -f get_mta_version export -f get_queue_count export -f check_dns_record export -f get_primary_ip export -f is_valid_ip export -f get_reverse_dns export -f send_test_email export -f parse_exim_email export -f get_log_date_range export -f count_by_sender