89ad050222
CRITICAL FIXES (5 issues):
1. email-diagnostics.sh: Fix inverted sender/recipient extraction logic
- Lines 292-303: Corrected pattern matching to properly extract recipients and senders
- Removed inverted grep patterns that were looking for wrong log entry types
2. mail-log-analyzer.sh: Fix string comparison with percent sign
- Line 1184-1186: Properly extract numeric value before '%' character
- Use sed to isolate leading digits for numeric comparison
3. email-diagnostics.sh: Fix malformed grep syntax
- Line 525-527: Corrected grep command structure with -e options
- Changed to -iE with pipe patterns and proper file argument placement
4. mail-log-analyzer.sh: Fix overly broad domain bounce pattern
- Line 749: Changed from "^.*${domain}" to "\b${domain}$"
- Prevents false positives from substring domain matches
5. mail-log-analyzer.sh: Fix undefined TEMP_LOG variable
- Line 860: Changed TEMP_LOG to MAIL_LOG (the actual global variable)
- Added error handling with 2>/dev/null
HIGH SEVERITY FIXES (2 issues):
6. mail-log-analyzer.sh: Fix AWK uninitialized variable
- Lines 1447-1456: Added BEGIN block to initialize print_line = 0
- Prevents first log entries from being incorrectly filtered
7. mail-log-analyzer.sh: Fix overly permissive bounce detection pattern
- Line 247: Changed from "(==|defer)" to more specific pattern
- Prevents false positives from non-bounce defer messages
MODERATE FIXES (3 issues):
8. mail-queue-inspector.sh: Fix queue message count mismatch
- Line 41: Changed head -40 to head -20 to match label
9. deliverability-test.sh: Fix fragile SMTP connection test
- Lines 102-106: Added nc availability check and fallback to bash TCP
- Proper variable quoting and error handling
10. blacklist-check.sh: Replace deprecated host command with dig
- Line 52: Changed from host to dig +short for consistency and timeout control
All scripts pass syntax validation.
Impact: Logic errors fixed, no security issues introduced, all existing functionality preserved.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
295 lines
9.5 KiB
Bash
Executable File
295 lines
9.5 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
################################################################################
|
|
# Email Deliverability Test - Comprehensive Email Sending Validation
|
|
################################################################################
|
|
# Purpose: Test email deliverability with authentication checks and blacklist detection
|
|
# Validates SPF/DKIM/DMARC, tests SMTP connection, checks blacklists
|
|
################################################################################
|
|
|
|
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 Deliverability Test"
|
|
|
|
# Get input from user
|
|
echo ""
|
|
read -p "Enter domain to test (e.g., example.com): " TARGET_DOMAIN
|
|
if [ -z "$TARGET_DOMAIN" ]; then
|
|
print_error "Domain required"
|
|
exit 1
|
|
fi
|
|
|
|
read -p "Enter test recipient email (will receive test email): " TEST_EMAIL
|
|
if [ -z "$TEST_EMAIL" ]; then
|
|
print_error "Recipient email required"
|
|
exit 1
|
|
fi
|
|
|
|
read -p "Enter sender email address (e.g., test@$TARGET_DOMAIN): " SENDER_EMAIL
|
|
if [ -z "$SENDER_EMAIL" ]; then
|
|
SENDER_EMAIL="test@$TARGET_DOMAIN"
|
|
fi
|
|
|
|
print_info "Starting comprehensive deliverability test..."
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test 1: Authentication Records Check
|
|
################################################################################
|
|
|
|
print_header "Step 1: Email Authentication Records"
|
|
echo ""
|
|
|
|
# SPF Check
|
|
print_info "Checking SPF record..."
|
|
spf_record=$(dig +short TXT "$TARGET_DOMAIN" 2>/dev/null | grep "^\"v=spf1" | sed 's/"//g')
|
|
if [ -n "$spf_record" ]; then
|
|
print_success " ✓ SPF record found"
|
|
else
|
|
print_warning " ⚠ SPF record not found (may affect deliverability)"
|
|
fi
|
|
echo ""
|
|
|
|
# DKIM Check
|
|
print_info "Checking DKIM record..."
|
|
for sel in default k1 k2 google selector1 selector2; do
|
|
dkim_record=$(dig +short TXT "${sel}._domainkey.${TARGET_DOMAIN}" 2>/dev/null | grep "^\"v=DKIM1")
|
|
if [ -n "$dkim_record" ]; then
|
|
print_success " ✓ DKIM record found (selector: $sel)"
|
|
break
|
|
fi
|
|
done
|
|
if [ -z "$dkim_record" ]; then
|
|
print_warning " ⚠ DKIM record not found (recommend enabling for better deliverability)"
|
|
fi
|
|
echo ""
|
|
|
|
# DMARC Check
|
|
print_info "Checking DMARC record..."
|
|
dmarc_record=$(dig +short TXT "_dmarc.${TARGET_DOMAIN}" 2>/dev/null | grep "^\"v=DMARC1" | sed 's/"//g')
|
|
if [ -n "$dmarc_record" ]; then
|
|
print_success " ✓ DMARC record found"
|
|
else
|
|
print_warning " ⚠ DMARC record not found (recommended for authentication monitoring)"
|
|
fi
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test 2: SMTP Connection Test
|
|
################################################################################
|
|
|
|
print_header "Step 2: SMTP Connection Test"
|
|
echo ""
|
|
|
|
print_info "Testing SMTP connectivity..."
|
|
|
|
# Get MX records
|
|
MX_RECORDS=$(dig +short MX "$TARGET_DOMAIN" 2>/dev/null | head -5)
|
|
|
|
if [ -z "$MX_RECORDS" ]; then
|
|
print_error " ✗ No MX records found for $TARGET_DOMAIN"
|
|
echo " Cannot test SMTP connectivity"
|
|
else
|
|
print_success " ✓ MX records found:"
|
|
while read priority server; do
|
|
server=$(echo "$server" | sed 's/\.$//')
|
|
echo " • Priority $priority: $server"
|
|
|
|
# Try to connect to SMTP using multiple methods
|
|
local smtp_ok=0
|
|
|
|
# Try nc first if available
|
|
if command -v nc &>/dev/null; then
|
|
if timeout 3 bash -c "echo 'QUIT' | nc -z -w 1 \"$server\" 25" &>/dev/null; then
|
|
smtp_ok=1
|
|
fi
|
|
fi
|
|
|
|
# Try timeout with bash TCP if nc not available
|
|
if [ $smtp_ok -eq 0 ] && timeout 3 bash -c "exec 3<>/dev/tcp/$server/25 && echo QUIT >&3 && cat <&3" &>/dev/null; then
|
|
smtp_ok=1
|
|
fi
|
|
|
|
if [ $smtp_ok -eq 1 ]; then
|
|
print_success " ✓ SMTP port 25 responds"
|
|
else
|
|
print_warning " ⚠ SMTP port 25 not responding (may use port 587/465)"
|
|
fi
|
|
done < <(echo "$MX_RECORDS")
|
|
fi
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test 3: Blacklist Check (from email-diagnostics)
|
|
################################################################################
|
|
|
|
print_header "Step 3: Server IP Blacklist Check"
|
|
echo ""
|
|
|
|
# Get server's public IP
|
|
print_info "Detecting server IP address..."
|
|
SERVER_IP=$(curl -s --max-time 5 ifconfig.me 2>/dev/null || curl -s --max-time 5 icanhazip.com 2>/dev/null || echo "")
|
|
|
|
if [ -z "$SERVER_IP" ]; then
|
|
print_warning " ⚠ Could not detect server IP (skipping blacklist check)"
|
|
else
|
|
print_success " Server IP: $SERVER_IP"
|
|
echo ""
|
|
|
|
# Check major blacklists
|
|
BLACKLISTS_DB=(
|
|
"zen.spamhaus.org|Spamhaus"
|
|
"bl.spamcop.net|SpamCop"
|
|
"bl.barracudacentral.org|Barracuda"
|
|
"dnsbl.sorbs.net|SORBS"
|
|
"cbl.abuseat.org|CBL"
|
|
)
|
|
|
|
print_info "Checking major blacklists..."
|
|
REVERSED_IP=$(echo $SERVER_IP | awk -F. '{print $4"."$3"."$2"."$1}')
|
|
|
|
listed=0
|
|
for entry in "${BLACKLISTS_DB[@]}"; do
|
|
IFS='|' read -r rbl_host rbl_name <<< "$entry"
|
|
|
|
if dig +short +timeout=2 "${REVERSED_IP}.${rbl_host}" A 2>/dev/null | grep -q .; then
|
|
print_error " ✗ $rbl_name: LISTED (may cause delivery issues)"
|
|
((listed++))
|
|
else
|
|
print_success " ✓ $rbl_name: Not listed"
|
|
fi
|
|
done
|
|
|
|
if [ $listed -gt 0 ]; then
|
|
echo ""
|
|
print_warning " ⚠ Your IP is listed on $listed blacklist(s)"
|
|
echo " Recommendation: Use blacklist-check tool for delisting options"
|
|
fi
|
|
fi
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test 4: Reverse DNS Check
|
|
################################################################################
|
|
|
|
print_header "Step 4: Reverse DNS (PTR Record) Check"
|
|
echo ""
|
|
|
|
print_info "Checking reverse DNS..."
|
|
if [ -n "$SERVER_IP" ]; then
|
|
PTR_RECORD=$(dig +short -x "$SERVER_IP" 2>/dev/null)
|
|
if [ -n "$PTR_RECORD" ]; then
|
|
print_success " ✓ PTR record found: $PTR_RECORD"
|
|
echo " Reverse DNS is properly configured"
|
|
else
|
|
print_error " ✗ PTR record not found"
|
|
echo " Recommendation: Contact your hosting provider to set reverse DNS"
|
|
fi
|
|
else
|
|
print_warning " ⚠ Could not determine server IP (skip PTR check)"
|
|
fi
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test 5: Send Test Email
|
|
################################################################################
|
|
|
|
print_header "Step 5: Send Test Email"
|
|
echo ""
|
|
|
|
print_info "Composing and sending test email..."
|
|
|
|
# Create test email
|
|
TEST_EMAIL_FILE="/tmp/deliverability_test_$$.txt"
|
|
cat > "$TEST_EMAIL_FILE" << EMAILEOF
|
|
Subject: Email Deliverability Test from $TARGET_DOMAIN
|
|
From: $SENDER_EMAIL
|
|
To: $TEST_EMAIL
|
|
Date: $(date -R)
|
|
|
|
This is an automated email deliverability test from:
|
|
Domain: $TARGET_DOMAIN
|
|
Server IP: ${SERVER_IP:-Unknown}
|
|
Timestamp: $(date)
|
|
|
|
If you received this email, your email system is working correctly.
|
|
|
|
Check the email headers to verify:
|
|
- SPF authentication result
|
|
- DKIM signature
|
|
- DMARC alignment
|
|
|
|
---
|
|
Sent from Email Deliverability Test Tool
|
|
EMAILEOF
|
|
|
|
# Try to send email
|
|
if command -v sendmail &> /dev/null; then
|
|
if sendmail "$TEST_EMAIL" < "$TEST_EMAIL_FILE" 2>/dev/null; then
|
|
print_success " ✓ Test email sent successfully via sendmail"
|
|
echo " Recipient should receive email at: $TEST_EMAIL"
|
|
else
|
|
print_warning " ⚠ sendmail submission may have failed"
|
|
fi
|
|
elif command -v mail &> /dev/null; then
|
|
if echo "" | mail -s "Email Deliverability Test" -r "$SENDER_EMAIL" "$TEST_EMAIL" 2>/dev/null; then
|
|
print_success " ✓ Test email sent successfully via mail command"
|
|
echo " Recipient should receive email at: $TEST_EMAIL"
|
|
else
|
|
print_warning " ⚠ mail command submission may have failed"
|
|
fi
|
|
else
|
|
print_warning " ⚠ No mail sending utility found (sendmail/mail)"
|
|
echo " Email sending cannot be tested on this system"
|
|
fi
|
|
|
|
rm -f "$TEST_EMAIL_FILE"
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Test Summary & Recommendations
|
|
################################################################################
|
|
|
|
print_header "Deliverability Test Summary"
|
|
echo ""
|
|
|
|
echo "📧 Test Configuration:"
|
|
echo " Domain: $TARGET_DOMAIN"
|
|
echo " Sender: $SENDER_EMAIL"
|
|
echo " Recipient: $TEST_EMAIL"
|
|
if [ -n "$SERVER_IP" ]; then
|
|
echo " Server IP: $SERVER_IP"
|
|
fi
|
|
echo ""
|
|
|
|
echo "✅ Recommended Next Steps:"
|
|
echo ""
|
|
echo "1. Check recipient inbox for test email"
|
|
echo " Look for the email from $SENDER_EMAIL"
|
|
echo ""
|
|
echo "2. Review email headers:"
|
|
echo " - Verify 'Authentication-Results' header"
|
|
echo " - Check SPF, DKIM, DMARC results"
|
|
echo " - Look for any 'pass' or 'fail' indications"
|
|
echo ""
|
|
echo "3. If email didn't arrive:"
|
|
echo " - Check spam/junk folder"
|
|
echo " - Review mail server logs: tail -f /var/log/mail.log"
|
|
echo " - Use email-diagnostics tool: email-diagnostics"
|
|
echo " - Check blacklist status: blacklist-check"
|
|
echo ""
|
|
echo "4. For authentication issues:"
|
|
echo " - Validate records: spf-dkim-dmarc-check"
|
|
echo " - Analyze mail logs: mail-log-analyzer"
|
|
echo ""
|
|
|
|
echo "🔗 Related Tools:"
|
|
echo " • email-diagnostics - Analyze specific email delivery issues"
|
|
echo " • blacklist-check - Check IP reputation on RBLs"
|
|
echo " • spf-dkim-dmarc-check - Validate authentication records"
|
|
echo " • mail-log-analyzer - Analyze mail server logs"
|
|
echo ""
|