From f47a16412473d11c5e73aae3e891f9c07eb97b6c Mon Sep 17 00:00:00 2001 From: cschantz Date: Wed, 31 Dec 2025 18:38:10 -0500 Subject: [PATCH] Add Email Diagnostics tool - verify if email/domain is working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Features: - Check specific email address or entire domain - Shows if emails are working with PROOF - Displays recent activity with timestamps highlighted - Categorizes: delivered, bounced, rejected, deferred - Shows last 5 examples of each type from selected time period - Clear verdict: Working / Partially Working / Has Problems - Extracts bounce reasons and recommendations - Saves full report for customer evidence Usage: Email menu โ†’ Option 1 (Email Diagnostics) Perfect for: 'Customer says they're not receiving emails' Example output: โœ… EMAIL IS WORKING PROPERLY Evidence: 15 successful deliveries in last 24 hours PROOF - Recent deliveries with timestamps shown below --- launcher.sh | 38 ++-- modules/email/email-diagnostics.sh | 319 +++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+), 18 deletions(-) create mode 100755 modules/email/email-diagnostics.sh diff --git a/launcher.sh b/launcher.sh index 2267e83..b3d181d 100755 --- a/launcher.sh +++ b/launcher.sh @@ -398,21 +398,22 @@ show_email_menu() { echo "" echo -e "${BOLD}Diagnostics:${NC}" echo "" - echo -e " ${CYAN}1)${NC} ๐Ÿ“ฌ Email Deliverability Test - Test sending/receiving" - echo -e " ${CYAN}2)${NC} ๐Ÿ” Mail Queue Inspector - View stuck emails" - echo -e " ${CYAN}3)${NC} ๐Ÿ“Š SMTP Connection Test - Verify mail server" - echo -e " ${CYAN}4)${NC} ๐Ÿ” SPF/DKIM/DMARC Check - Email authentication" + echo -e " ${CYAN}1)${NC} ๐Ÿ” Email Diagnostics - Verify email/domain is working โญ" + echo -e " ${CYAN}2)${NC} ๐Ÿ“ฌ Email Deliverability Test - Test sending/receiving" + echo -e " ${CYAN}3)${NC} ๐Ÿ” Mail Queue Inspector - View stuck emails" + echo -e " ${CYAN}4)${NC} ๐Ÿ“Š SMTP Connection Test - Verify mail server" + echo -e " ${CYAN}5)${NC} ๐Ÿ” SPF/DKIM/DMARC Check - Email authentication" echo "" echo -e "${BOLD}Troubleshooting:${NC}" echo "" - echo -e " ${YELLOW}5)${NC} ๐Ÿšซ Blacklist Check - Check IP reputation" - echo -e " ${YELLOW}6)${NC} ๐Ÿ“ง Mail Log Analyzer - Search mail logs" - echo -e " ${YELLOW}7)${NC} ๐Ÿ”„ Flush Mail Queue - Clear stuck emails" + echo -e " ${YELLOW}6)${NC} ๐Ÿšซ Blacklist Check - Check IP reputation" + echo -e " ${YELLOW}7)${NC} ๐Ÿ“ง Mail Log Analyzer - Search mail logs" + echo -e " ${YELLOW}8)${NC} ๐Ÿ”„ Flush Mail Queue - Clear stuck emails" echo "" echo -e "${BOLD}Maintenance:${NC}" echo "" - echo -e " ${GREEN}8)${NC} ๐Ÿงน Clean Mailboxes - Remove old emails" - echo -e " ${GREEN}9)${NC} ๐Ÿ“ˆ Mailbox Size Report - Show usage per account" + echo -e " ${GREEN}9)${NC} ๐Ÿงน Clean Mailboxes - Remove old emails" + echo -e " ${GREEN}10)${NC} ๐Ÿ“ˆ Mailbox Size Report - Show usage per account" echo "" echo -e " ${RED}0)${NC} Back to Main Menu" echo "" @@ -426,15 +427,16 @@ handle_email_menu() { read -r choice case $choice in - 1) run_module "email" "deliverability-test.sh" ;; - 2) run_module "email" "mail-queue-inspector.sh" ;; - 3) run_module "email" "smtp-connection-test.sh" ;; - 4) run_module "email" "spf-dkim-dmarc-check.sh" ;; - 5) run_module "email" "blacklist-check.sh" ;; - 6) run_module "email" "mail-log-analyzer.sh" ;; - 7) run_module "email" "flush-mail-queue.sh" ;; - 8) run_module "email" "clean-mailboxes.sh" ;; - 9) run_module "email" "mailbox-size-report.sh" ;; + 1) run_module "email" "email-diagnostics.sh" ;; + 2) run_module "email" "deliverability-test.sh" ;; + 3) run_module "email" "mail-queue-inspector.sh" ;; + 4) run_module "email" "smtp-connection-test.sh" ;; + 5) run_module "email" "spf-dkim-dmarc-check.sh" ;; + 6) run_module "email" "blacklist-check.sh" ;; + 7) run_module "email" "mail-log-analyzer.sh" ;; + 8) run_module "email" "flush-mail-queue.sh" ;; + 9) run_module "email" "clean-mailboxes.sh" ;; + 10) run_module "email" "mailbox-size-report.sh" ;; 0) return ;; *) echo -e "${RED}Invalid option${NC}"; sleep 1 ;; esac diff --git a/modules/email/email-diagnostics.sh b/modules/email/email-diagnostics.sh new file mode 100755 index 0000000..9d33091 --- /dev/null +++ b/modules/email/email-diagnostics.sh @@ -0,0 +1,319 @@ +#!/bin/bash + +################################################################################ +# Email Account/Domain Diagnostics +################################################################################ +# Purpose: Verify email is working for specific address or domain +# Shows proof of delivery or identifies why emails aren't working +################################################################################ + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$SCRIPT_DIR/lib/common-functions.sh" +source "$SCRIPT_DIR/lib/system-detect.sh" +source "$SCRIPT_DIR/lib/email-functions.sh" + +show_banner "Email Diagnostics - Verify Email Delivery" + +# Get mail log path +MAIL_LOG=$(get_mail_log_path) +if [ ! -f "$MAIL_LOG" ]; then + print_error "Mail log not found: $MAIL_LOG" + exit 1 +fi + +print_success "Using mail log: $MAIL_LOG" +echo "" + +# Ask what to check +echo -e "${BOLD}What would you like to check?${NC}" +echo "" +echo " 1) Specific email address (e.g., user@example.com)" +echo " 2) Entire domain (e.g., example.com)" +echo "" +read -p "Enter choice [1]: " check_type +check_type=${check_type:-1} + +# Get email/domain to check +echo "" +if [ "$check_type" = "2" ]; then + read -p "Enter domain to check (e.g., example.com): " target + search_pattern="@${target}" + check_label="domain $target" +else + read -p "Enter email address to check: " target + search_pattern="$target" + check_label="email $target" +fi + +if [ -z "$target" ]; then + print_error "No email/domain provided" + exit 1 +fi + +# Time period to check +echo "" +echo "Check logs from:" +echo " 1) Last 1 hour" +echo " 2) Last 6 hours" +echo " 3) Last 24 hours (recommended)" +echo " 4) Last 48 hours" +echo " 5) Last week" +echo "" +read -p "Enter choice [3]: " time_choice +time_choice=${time_choice:-3} + +case "$time_choice" in + 1) hours=1 ;; + 2) hours=6 ;; + 3) hours=24 ;; + 4) hours=48 ;; + 5) hours=168 ;; + *) hours=24 ;; +esac + +echo "" +print_info "Analyzing $check_label for last $hours hours..." +echo "" + +# Calculate time cutoff +if date --version 2>&1 | grep -q "GNU"; then + # GNU date + cutoff_time=$(date -d "$hours hours ago" +"%Y-%m-%d %H:%M:%S") +else + # BSD date (macOS) + cutoff_time=$(date -v-${hours}H +"%Y-%m-%d %H:%M:%S") +fi + +################################################################################ +# Analysis +################################################################################ + +TEMP_MATCHES="/tmp/email_diag_$$.txt" +grep -i "$search_pattern" "$MAIL_LOG" > "$TEMP_MATCHES" 2>/dev/null + +if [ ! -s "$TEMP_MATCHES" ]; then + print_error "โŒ NO EMAIL ACTIVITY FOUND for $check_label" + echo "" + echo "This means:" + echo " โ€ข No emails sent TO this $check_label" + echo " โ€ข No emails sent FROM this $check_label" + echo " โ€ข No delivery attempts logged" + echo "" + print_warning "Possible reasons:" + echo " 1. Email address/domain doesn't exist on this server" + echo " 2. No email activity in the last $hours hours" + echo " 3. Emails are going to a different mail server" + echo "" + + # Check if domain exists + if [ "$check_type" = "2" ]; then + if grep -q "$target" /etc/localdomains 2>/dev/null || grep -q "$target" /etc/userdomains 2>/dev/null; then + print_info "โœ“ Domain $target IS configured on this server" + else + print_warning "โš  Domain $target NOT found in local domains" + fi + fi + + rm -f "$TEMP_MATCHES" + exit 0 +fi + +total_lines=$(wc -l < "$TEMP_MATCHES") +print_success "โœ“ Found $total_lines log entries for $check_label" +echo "" + +################################################################################ +# Categorize activity +################################################################################ + +print_header "๐Ÿ“Š Activity Summary" +echo "" + +# Count different types +delivered=$(grep -ci "=> .*$search_pattern\|delivered.*$search_pattern" "$TEMP_MATCHES" || echo 0) +sent=$(grep -ci "<=.*$search_pattern" "$TEMP_MATCHES" || echo 0) +bounced=$(grep -ci "bounce.*$search_pattern\|failed.*$search_pattern\|550.*$search_pattern" "$TEMP_MATCHES" || echo 0) +deferred=$(grep -ci "deferred.*$search_pattern\|retry.*$search_pattern\|temporarily rejected" "$TEMP_MATCHES" || echo 0) +rejected=$(grep -ci "rejected.*$search_pattern\|denied.*$search_pattern\|blocked.*$search_pattern" "$TEMP_MATCHES" || echo 0) +spf_fail=$(grep -ci "SPF.*fail.*$search_pattern" "$TEMP_MATCHES" || echo 0) +dkim_fail=$(grep -ci "DKIM.*fail.*$search_pattern" "$TEMP_MATCHES" || echo 0) + +if [ "$delivered" -gt 0 ]; then + print_success "โœ… Delivered: $delivered emails successfully delivered" +fi + +if [ "$sent" -gt 0 ]; then + print_info "๐Ÿ“ค Sent: $sent emails sent FROM this $check_label" +fi + +if [ "$bounced" -gt 0 ]; then + print_error "โŒ Bounced: $bounced emails bounced/failed" +fi + +if [ "$deferred" -gt 0 ]; then + print_warning "โธ Deferred: $deferred emails temporarily delayed" +fi + +if [ "$rejected" -gt 0 ]; then + print_error "๐Ÿšซ Rejected: $rejected emails blocked/rejected" +fi + +if [ "$spf_fail" -gt 0 ]; then + print_warning "โš  SPF Failures: $spf_fail authentication failures" +fi + +if [ "$dkim_fail" -gt 0 ]; then + print_warning "โš  DKIM Failures: $dkim_fail signature failures" +fi + +echo "" + +################################################################################ +# Show verdict +################################################################################ + +print_header "๐Ÿ” Diagnostic Result" +echo "" + +if [ "$delivered" -gt 0 ] && [ "$bounced" -eq 0 ] && [ "$rejected" -eq 0 ]; then + print_success "โœ… EMAIL IS WORKING PROPERLY" + echo "" + echo "Evidence: $delivered successful deliveries in the last $hours hours" + echo "No bounces or rejections detected" + echo "Proof shown below with timestamps" + echo "" +elif [ "$delivered" -gt 0 ] && [ "$bounced" -gt 0 ]; then + print_warning "โš  EMAIL PARTIALLY WORKING" + echo "" + echo "Some emails delivered ($delivered) but some failed ($bounced)" + echo "Check bounce reasons below for details" + echo "" +elif [ "$bounced" -gt 0 ] || [ "$rejected" -gt 0 ]; then + print_error "โŒ EMAIL HAS PROBLEMS" + echo "" + echo "Emails are being rejected or bouncing" + echo "See details below for why" + echo "" +elif [ "$deferred" -gt 0 ]; then + print_warning "โธ EMAIL DELAYED" + echo "" + echo "Emails are being deferred (temporary failures)" + echo "This usually resolves itself" + echo "" +else + print_info "๐Ÿ“ฌ EMAILS SENT, AWAITING CONFIRMATION" + echo "" + echo "Emails were sent but no delivery confirmation yet" + echo "Check again in a few minutes" + echo "" +fi + +################################################################################ +# Show recent activity samples +################################################################################ + +if [ "$delivered" -gt 0 ]; then + print_header "โœ… Recent Successful Deliveries (last 5 from past $hours hours)" + echo "" + print_info "PROOF - These emails were delivered recently:" + echo "" + grep -i "=> .*$search_pattern\|delivered.*$search_pattern" "$TEMP_MATCHES" | tail -5 | while read line; do + # Extract timestamp if present + timestamp=$(echo "$line" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}|[A-Z][a-z]{2} [0-9]+ [0-9]{2}:[0-9]{2}:[0-9]{2}' | head -1) + if [ -n "$timestamp" ]; then + echo -e " ${GREEN}[$timestamp]${NC} $line" + else + echo " $line" + fi + done + echo "" +fi + +if [ "$bounced" -gt 0 ]; then + print_header "โŒ Recent Bounces/Failures (last 5 from past $hours hours)" + echo "" + print_warning "PROOF - These emails failed recently:" + echo "" + grep -i "bounce.*$search_pattern\|failed.*$search_pattern\|550.*$search_pattern" "$TEMP_MATCHES" | tail -5 | while read line; do + timestamp=$(echo "$line" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}|[A-Z][a-z]{2} [0-9]+ [0-9]{2}:[0-9]{2}:[0-9]{2}' | head -1) + if [ -n "$timestamp" ]; then + echo -e " ${RED}[$timestamp]${NC} $line" + else + echo " $line" + fi + done + echo "" + + # Extract bounce reasons + print_header "Common Bounce Reasons" + echo "" + grep -i "bounce\|550\|fail" "$TEMP_MATCHES" | grep -oE "550 .*|User unknown|Mailbox.*full|Relay.*denied|blocked" | sort | uniq -c | sort -rn | head -5 + echo "" +fi + +if [ "$rejected" -gt 0 ]; then + print_header "๐Ÿšซ Recent Rejections (last 5)" + echo "" + grep -i "rejected.*$search_pattern\|denied.*$search_pattern\|blocked.*$search_pattern" "$TEMP_MATCHES" | tail -5 | while read line; do + echo " $line" + done + echo "" +fi + +if [ "$spf_fail" -gt 0 ] || [ "$dkim_fail" -gt 0 ]; then + print_header "โš  Authentication Issues" + echo "" + if [ "$spf_fail" -gt 0 ]; then + echo "SPF failures detected:" + grep -i "SPF.*fail" "$TEMP_MATCHES" | head -3 + echo "" + fi + if [ "$dkim_fail" -gt 0 ]; then + echo "DKIM failures detected:" + grep -i "DKIM.*fail" "$TEMP_MATCHES" | head -3 + echo "" + fi +fi + +################################################################################ +# Recommendations +################################################################################ + +print_header "๐Ÿ’ก Recommendations" +echo "" + +if [ "$bounced" -gt 0 ]; then + echo "To fix bounces:" + echo " 1. Verify the recipient email address is correct" + echo " 2. Check if recipient mailbox is full" + echo " 3. Ensure domain DNS is configured properly" + echo "" +fi + +if [ "$rejected" -gt 0 ]; then + echo "To fix rejections:" + echo " 1. Check if server IP is blacklisted (use Blacklist Check tool)" + echo " 2. Verify SPF/DKIM/DMARC records are correct" + echo " 3. Check if recipient is blocking your domain" + echo "" +fi + +if [ "$spf_fail" -gt 0 ]; then + echo "To fix SPF failures:" + echo " 1. Add this server's IP to domain's SPF record" + echo " 2. Use SPF/DKIM/DMARC Check tool for details" + echo "" +fi + +################################################################################ +# Save full report +################################################################################ + +REPORT_FILE="/tmp/email_diag_${target//[@.]/_}_$(date +%Y%m%d_%H%M%S).txt" +cp "$TEMP_MATCHES" "$REPORT_FILE" + +print_info "Full log saved to: $REPORT_FILE" +echo "" + +# Cleanup +rm -f "$TEMP_MATCHES"