7be2f3bf93
- Exclude lines with 'saved mail to' (successful deliveries) - Exclude lines with '=>' (delivery confirmations) - Only show actual bounce/failure messages - Updated both counting and display sections This fixes the bounce section showing 'saved mail to INBOX' which are actually successful deliveries, not bounces.
659 lines
23 KiB
Bash
Executable File
659 lines
23 KiB
Bash
Executable File
#!/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"
|
|
TEMP_AUTH="/tmp/email_auth_$$.txt"
|
|
TEMP_ALL="/tmp/email_all_$$.txt"
|
|
|
|
# Search multiple log files for comprehensive results
|
|
# Check Exim logs (email delivery)
|
|
if [ -f "/var/log/exim_mainlog" ]; then
|
|
grep -i "$search_pattern" /var/log/exim_mainlog >> "$TEMP_ALL" 2>/dev/null || true
|
|
fi
|
|
|
|
# Check maillog (Dovecot auth + some delivery)
|
|
if [ -f "/var/log/maillog" ]; then
|
|
grep -i "$search_pattern" /var/log/maillog >> "$TEMP_ALL" 2>/dev/null || true
|
|
fi
|
|
|
|
# Check messages log (fallback)
|
|
if [ -f "/var/log/messages" ]; then
|
|
grep -i "$search_pattern" /var/log/messages >> "$TEMP_ALL" 2>/dev/null || true
|
|
fi
|
|
|
|
# If we found nothing, fall back to the detected mail log
|
|
if [ ! -s "$TEMP_ALL" ]; then
|
|
grep -i "$search_pattern" "$MAIL_LOG" > "$TEMP_ALL" 2>/dev/null || true
|
|
fi
|
|
|
|
# Separate authentication events (IMAP/POP3 logins)
|
|
grep -E "imap-login|pop3-login|dovecot.*Login|Logged in|Disconnected" "$TEMP_ALL" > "$TEMP_AUTH" 2>/dev/null || true
|
|
|
|
# Get only email delivery events (exclude auth logs)
|
|
grep -v "imap-login\|pop3-login\|dovecot.*Login\|Logged in\|Disconnected" "$TEMP_ALL" > "$TEMP_MATCHES" 2>/dev/null || true
|
|
|
|
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" "$TEMP_AUTH" "$TEMP_ALL"
|
|
exit 0
|
|
fi
|
|
|
|
total_lines=$(wc -l < "$TEMP_MATCHES")
|
|
print_success "Found $total_lines log entries for $check_label"
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Categorize activity
|
|
################################################################################
|
|
|
|
# Count different types first (sanitize to remove newlines)
|
|
delivered=$(grep -ci "=> .*$search_pattern\|delivered.*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
delivered=$(echo "$delivered" | head -1 | tr -d '\n\r')
|
|
sent=$(grep -ci "<=.*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
sent=$(echo "$sent" | head -1 | tr -d '\n\r')
|
|
# Only count actual email bounces, not auth failures or successful deliveries
|
|
bounced=$(grep -i "$search_pattern" "$TEMP_MATCHES" | grep -v "authenticator failed\|Authentication failed\|saved mail to\|=>" | grep -ci "550\|551\|552\|553\|554\|bounced\|Mail delivery failed\|** " 2>/dev/null || echo 0)
|
|
bounced=$(echo "$bounced" | head -1 | tr -d '\n\r')
|
|
deferred=$(grep -ci "deferred.*$search_pattern\|retry.*$search_pattern\|temporarily rejected" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
deferred=$(echo "$deferred" | head -1 | tr -d '\n\r')
|
|
rejected=$(grep -i "$search_pattern" "$TEMP_MATCHES" | grep -v "authenticator failed\|Authentication failed" | grep -ci "rejected RCPT\|rejected.*relay.*denied\|rejected.*spam" 2>/dev/null || echo 0)
|
|
rejected=$(echo "$rejected" | head -1 | tr -d '\n\r')
|
|
spf_fail=$(grep -ci "SPF.*fail.*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
spf_fail=$(echo "$spf_fail" | head -1 | tr -d '\n\r')
|
|
dkim_fail=$(grep -ci "DKIM.*fail.*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
dkim_fail=$(echo "$dkim_fail" | head -1 | tr -d '\n\r')
|
|
# Only count actually rejected spam, not spam delivered to spam folder
|
|
spam_rejected=$(grep -i "$search_pattern" "$TEMP_MATCHES" | grep -i "spam" | grep -ci "rejected\|blocked\|denied" 2>/dev/null || echo 0)
|
|
spam_rejected=$(echo "$spam_rejected" | head -1 | tr -d '\n\r')
|
|
greylist=$(grep -ci "greylist.*$search_pattern\|greylisted.*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
greylist=$(echo "$greylist" | head -1 | tr -d '\n\r')
|
|
received=$(grep -ci "=> .*$search_pattern" "$TEMP_MATCHES" 2>/dev/null || echo 0)
|
|
received=$(echo "$received" | head -1 | tr -d '\n\r')
|
|
|
|
# Count authentication events
|
|
auth_failed=$(grep -ci "auth failed\|Login aborted\|authentication failed" "$TEMP_AUTH" 2>/dev/null || echo 0)
|
|
auth_failed=$(echo "$auth_failed" | head -1 | tr -d '\n\r')
|
|
auth_success=$(grep -ci "Logged in\|Login:.*user=.*$search_pattern" "$TEMP_AUTH" 2>/dev/null || echo 0)
|
|
auth_success=$(echo "$auth_success" | head -1 | tr -d '\n\r')
|
|
|
|
################################################################################
|
|
# Quick Summary
|
|
################################################################################
|
|
|
|
print_header "QUICK SUMMARY"
|
|
echo ""
|
|
|
|
# Determine quick status
|
|
total_problems=$((bounced + rejected + spam_rejected))
|
|
total_email_activity=$((sent + received + delivered))
|
|
|
|
if [ "$total_email_activity" -gt 0 ] && [ "$total_problems" -eq 0 ]; then
|
|
print_success "Email appears to be working (${total_email_activity} email events, no problems)"
|
|
elif [ "$total_email_activity" -gt 0 ] && [ "$total_problems" -gt 0 ]; then
|
|
print_warning "Partial email issues (${total_email_activity} delivered, ${total_problems} failed)"
|
|
elif [ "$total_problems" -gt 0 ]; then
|
|
print_error "Email delivery problems detected (${total_problems} failures)"
|
|
elif [ "$auth_success" -gt 0 ] && [ "$total_email_activity" -eq 0 ]; then
|
|
print_info "Account active (${auth_success} logins) but no email traffic in last ${hours}h"
|
|
elif [ "$auth_failed" -gt 0 ]; then
|
|
print_warning "Failed login attempts detected (${auth_failed} attempts) - possible attack"
|
|
else
|
|
print_info "No activity detected in last ${hours} hours"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Detailed Activity Breakdown
|
|
################################################################################
|
|
|
|
print_header "EMAIL DELIVERY ACTIVITY (last $hours hours)"
|
|
echo ""
|
|
|
|
# Always show main metrics for clarity
|
|
if [ "$received" -gt 0 ]; then
|
|
print_success "Received: $received emails (incoming TO this $check_label)"
|
|
else
|
|
echo "Received: 0 emails (no incoming mail)"
|
|
fi
|
|
|
|
if [ "$sent" -gt 0 ]; then
|
|
print_success "Sent: $sent emails (outgoing FROM this $check_label)"
|
|
else
|
|
echo "Sent: 0 emails (no outgoing mail)"
|
|
fi
|
|
|
|
if [ "$delivered" -gt 0 ]; then
|
|
print_success "Delivered: $delivered successful deliveries"
|
|
else
|
|
echo "Delivered: 0 (no completed deliveries logged)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Only show problems if they exist
|
|
has_problems=0
|
|
|
|
if [ "$bounced" -gt 0 ]; then
|
|
print_error "Bounced: $bounced emails bounced/failed"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$deferred" -gt 0 ]; then
|
|
print_warning "Deferred: $deferred emails temporarily delayed"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$rejected" -gt 0 ]; then
|
|
print_error "Rejected: $rejected emails blocked/rejected"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$spam_rejected" -gt 0 ]; then
|
|
print_error "Spam Rejected: $spam_rejected emails marked as spam"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$spf_fail" -gt 0 ]; then
|
|
print_warning "SPF Failures: $spf_fail authentication failures"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$dkim_fail" -gt 0 ]; then
|
|
print_warning "DKIM Failures: $dkim_fail signature failures"
|
|
has_problems=1
|
|
fi
|
|
|
|
if [ "$greylist" -gt 0 ]; then
|
|
print_info "Greylisted: $greylist emails temporarily delayed (normal anti-spam)"
|
|
fi
|
|
|
|
if [ $has_problems -eq 0 ]; then
|
|
print_success "No delivery problems detected"
|
|
fi
|
|
|
|
# Show email traffic patterns
|
|
if [ "$sent" -gt 0 ] || [ "$received" -gt 0 ]; then
|
|
echo ""
|
|
print_header "EMAIL TRAFFIC PATTERNS"
|
|
echo ""
|
|
|
|
# Top recipients (who this email is sending to)
|
|
if [ "$sent" -gt 0 ]; then
|
|
print_info "Top 5 recipients (emails sent TO):"
|
|
grep -i "<= .*$search_pattern" "$TEMP_MATCHES" | grep -oE "=> [^@]+@[^ ]+" | sed 's/=> //' | sort | uniq -c | sort -rn | head -5 | while read count recipient; do
|
|
echo " $recipient - $count emails"
|
|
done
|
|
echo ""
|
|
fi
|
|
|
|
# Top senders (who is sending to this email)
|
|
if [ "$received" -gt 0 ]; then
|
|
print_info "Top 5 senders (emails received FROM):"
|
|
grep -i "=> .*$search_pattern" "$TEMP_MATCHES" | grep -oE "<= [^@]+@[^ ]+" | sed 's/<= //' | sort | uniq -c | sort -rn | head -5 | while read count sender; do
|
|
echo " $sender - $count emails"
|
|
done
|
|
echo ""
|
|
fi
|
|
fi
|
|
|
|
# Show authentication summary
|
|
if [ -s "$TEMP_AUTH" ]; then
|
|
echo ""
|
|
print_header "MAILBOX ACCESS ACTIVITY (IMAP/POP3 Logins)"
|
|
echo ""
|
|
print_info "This shows if customer can access their mailbox (not email delivery)"
|
|
echo ""
|
|
|
|
if [ "$auth_success" -gt 0 ]; then
|
|
print_success "Successful Logins: $auth_success (password is correct, mailbox accessible)"
|
|
fi
|
|
|
|
if [ "$auth_failed" -gt 0 ]; then
|
|
print_error "Failed Logins: $auth_failed (WRONG PASSWORD or brute-force attack)"
|
|
|
|
# Extract IPs attempting failed logins
|
|
failed_ips=$(grep -i "auth failed\|Login aborted" "$TEMP_AUTH" | grep -oE "rip=[0-9.]+|from [0-9.]+" | sed 's/rip=//; s/from //' | sort | uniq -c | sort -rn)
|
|
if [ -n "$failed_ips" ]; then
|
|
echo ""
|
|
print_warning "IPs with failed login attempts:"
|
|
echo "$failed_ips" | while read count ip; do
|
|
echo " $ip - $count attempts"
|
|
done
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Account Status Check (for specific email addresses)
|
|
################################################################################
|
|
|
|
if [ "$check_type" != "2" ]; then
|
|
print_header "EMAIL ACCOUNT STATUS"
|
|
echo ""
|
|
|
|
# Extract username and domain from email
|
|
local_part=$(echo "$target" | cut -d'@' -f1)
|
|
domain_part=$(echo "$target" | cut -d'@' -f2)
|
|
|
|
# Check if email account exists in various locations
|
|
account_found=0
|
|
maildir=""
|
|
|
|
# Check cPanel mail directory
|
|
if [ -d "/home/*/mail/$domain_part/$local_part" ]; then
|
|
maildir=$(find /home/*/mail/$domain_part/$local_part -maxdepth 0 -type d 2>/dev/null | head -1)
|
|
if [ -n "$maildir" ]; then
|
|
account_found=1
|
|
fi
|
|
fi
|
|
|
|
# Check Plesk mail directory
|
|
if [ $account_found -eq 0 ] && [ -d "/var/qmail/mailnames/$domain_part/$local_part" ]; then
|
|
account_found=1
|
|
maildir="/var/qmail/mailnames/$domain_part/$local_part"
|
|
fi
|
|
|
|
# Check generic /var/mail
|
|
if [ $account_found -eq 0 ] && [ -f "/var/mail/$local_part" ]; then
|
|
account_found=1
|
|
maildir="/var/mail/$local_part"
|
|
fi
|
|
|
|
# If successful logins exist, account must exist (even if we can't find the directory)
|
|
if [ $account_found -eq 0 ] && [ "$auth_success" -gt 0 ]; then
|
|
account_found=1
|
|
print_success "Email account EXISTS (confirmed by successful logins)"
|
|
print_warning "Note: Mailbox directory not found in standard locations"
|
|
elif [ $account_found -eq 1 ]; then
|
|
print_success "Email account EXISTS on this server"
|
|
|
|
# Show mailbox details if we found the directory
|
|
if [ -n "$maildir" ] && [ -d "$maildir" ]; then
|
|
disk_usage=$(du -sh "$maildir" 2>/dev/null | awk '{print $1}')
|
|
if [ -n "$disk_usage" ]; then
|
|
print_info "Mailbox size: $disk_usage"
|
|
fi
|
|
|
|
# Count messages
|
|
msg_count=$(find "$maildir" -type f -name "*:2,*" 2>/dev/null | wc -l)
|
|
if [ "$msg_count" -gt 0 ]; then
|
|
print_info "Messages stored: $msg_count"
|
|
fi
|
|
|
|
# Check for quota file
|
|
quota_file=$(find "$maildir" -name "maildirsize" 2>/dev/null | head -1)
|
|
if [ -f "$quota_file" ]; then
|
|
quota_info=$(head -1 "$quota_file" 2>/dev/null)
|
|
print_info "Quota: $quota_info"
|
|
fi
|
|
fi
|
|
else
|
|
print_warning "Email account NOT FOUND on this server"
|
|
echo ""
|
|
echo "This could mean:"
|
|
echo " • Account doesn't exist (typo in email address?)"
|
|
echo " • Account is on a different mail server"
|
|
echo " • Mail is handled by external service (Google, Office365, etc.)"
|
|
fi
|
|
|
|
# Check for forwarders
|
|
if [ -f "/etc/valiases/$domain_part" ]; then
|
|
forwarder=$(grep "^$local_part:" "/etc/valiases/$domain_part" 2>/dev/null)
|
|
if [ -n "$forwarder" ]; then
|
|
echo ""
|
|
print_info "Forwarder configured:"
|
|
echo " $forwarder"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
fi
|
|
|
|
################################################################################
|
|
# Show verdict
|
|
################################################################################
|
|
|
|
print_header "DIAGNOSTIC RESULT"
|
|
echo ""
|
|
|
|
# Determine overall status
|
|
if [ "$delivered" -gt 0 ] && [ "$bounced" -eq 0 ] && [ "$rejected" -eq 0 ] && [ "$spam_rejected" -eq 0 ]; then
|
|
print_success "EMAIL IS WORKING PROPERLY"
|
|
echo ""
|
|
echo "Evidence: $delivered successful deliveries in the last $hours hours"
|
|
echo "No bounces, rejections, or spam filtering detected"
|
|
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 ] || [ "$spam_rejected" -gt 0 ]; then
|
|
print_error "EMAIL HAS DELIVERY PROBLEMS"
|
|
echo ""
|
|
echo "Emails are being rejected, bouncing, or filtered as spam"
|
|
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 within minutes"
|
|
echo ""
|
|
|
|
elif [ "$sent" -gt 0 ] || [ "$received" -gt 0 ]; then
|
|
print_info "EMAIL ACTIVITY DETECTED"
|
|
echo ""
|
|
echo "Email traffic logged but no delivery confirmations in last $hours hours"
|
|
echo "This may be normal depending on email volume"
|
|
echo ""
|
|
|
|
elif [ "$auth_success" -gt 0 ] || [ "$auth_failed" -gt 0 ]; then
|
|
print_info "MAILBOX ACCESS ONLY"
|
|
echo ""
|
|
echo "No email delivery activity, only mailbox access (IMAP/POP3) detected"
|
|
echo "This means the account exists and is being checked, but no emails sent/received"
|
|
echo ""
|
|
if [ "$auth_success" -gt 0 ]; then
|
|
echo "Authentication is working (customer can access mailbox)"
|
|
fi
|
|
if [ "$auth_failed" -gt 0 ]; then
|
|
echo "Failed login attempts detected (see details below)"
|
|
fi
|
|
echo ""
|
|
|
|
else
|
|
print_warning "NO EMAIL ACTIVITY FOUND"
|
|
echo ""
|
|
echo "No email sending, receiving, or mailbox access in the last $hours hours"
|
|
echo "Account may be inactive or not used during this time period"
|
|
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 delivery:"
|
|
echo ""
|
|
grep -i "$search_pattern" "$TEMP_MATCHES" | grep -v "authenticator failed\|Authentication failed\|saved mail to\|=>" | grep -i "550\|551\|552\|553\|554\|bounced\|Mail delivery failed\|** " | 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 "$search_pattern" "$TEMP_MATCHES" | grep -v "authenticator failed\|Authentication failed\|saved mail to" | grep -i "550\|551\|bounced\|** " | grep -oE "550 [^(]*|551 [^(]*|User unknown|Mailbox.*full|Relay.*denied|No such user|does not exist" | sort | uniq -c | sort -rn | head -5
|
|
echo ""
|
|
fi
|
|
|
|
if [ "$rejected" -gt 0 ]; then
|
|
print_header "RECENT REJECTIONS (last 5)"
|
|
echo ""
|
|
grep -i "$search_pattern" "$TEMP_MATCHES" | grep -v "authenticator failed\|Authentication failed" | grep -i "rejected RCPT\|rejected.*relay.*denied\|rejected.*spam" | tail -5 | while read line; do
|
|
echo " $line"
|
|
done
|
|
echo ""
|
|
fi
|
|
|
|
if [ "$spam_rejected" -gt 0 ]; then
|
|
print_header "RECENT SPAM REJECTIONS (last 5)"
|
|
echo ""
|
|
print_info "Emails rejected as spam (not delivered):"
|
|
echo ""
|
|
grep -i "$search_pattern" "$TEMP_MATCHES" | grep -i "spam" | grep -i "rejected\|blocked\|denied" | 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 ""
|
|
fi
|
|
|
|
if [ "$greylist" -gt 0 ]; then
|
|
print_header "RECENT GREYLISTING EVENTS (last 5)"
|
|
echo ""
|
|
print_info "Note: Greylisting is temporary - emails usually deliver after retry"
|
|
echo ""
|
|
grep -i "greylist" "$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
|
|
|
|
if [ "$spam_rejected" -gt 0 ]; then
|
|
echo "To fix spam rejections:"
|
|
echo " 1. Check SpamAssassin score and adjust settings"
|
|
echo " 2. Verify email content isn't triggering spam filters"
|
|
echo " 3. Ensure proper SPF/DKIM authentication"
|
|
echo " 4. Check if sending domain has good reputation"
|
|
echo ""
|
|
fi
|
|
|
|
if [ "$greylist" -gt 0 ] && [ "$delivered" -eq 0 ]; then
|
|
echo "Greylisting delays:"
|
|
echo " • This is normal anti-spam behavior"
|
|
echo " • Emails should deliver after sender retries (5-15 minutes)"
|
|
echo " • No action needed unless emails never arrive"
|
|
echo ""
|
|
fi
|
|
|
|
if [ "$check_type" != "2" ] && [ $account_found -eq 0 ]; then
|
|
echo "Email account not found:"
|
|
echo " 1. Verify the email address is spelled correctly"
|
|
echo " 2. Check if domain DNS points to this server"
|
|
echo " 3. Create the email account if it should exist here"
|
|
echo " 4. Check if mail is handled by external service"
|
|
echo ""
|
|
fi
|
|
|
|
if [ "$auth_failed" -gt 0 ]; then
|
|
echo "Failed login attempts detected:"
|
|
echo " 1. Customer may be using wrong password"
|
|
echo " 2. Could be brute-force attack attempt"
|
|
echo " 3. Check IPs - block suspicious ones with firewall"
|
|
echo " 4. Advise customer to change password if compromised"
|
|
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" "$TEMP_AUTH" "$TEMP_ALL"
|