Fix critical logic errors in email diagnostics scripts

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>
This commit is contained in:
cschantz
2026-02-07 00:39:07 -05:00
parent a7a76e6bac
commit 89ad050222
9 changed files with 1883 additions and 26 deletions
+9 -6
View File
@@ -243,8 +243,8 @@ analyze_bounces() {
print_info "Analyzing bounce messages..."
# Extract bounces and deferrals
grep -E "(==|defer)" -- "$log_file" 2>/dev/null > "$temp_file"
# Extract bounces (==) and temporary deferrals (defer with reason codes)
grep -E "==|^[0-9].*defer[ed]*.*reason" -- "$log_file" 2>/dev/null > "$temp_file"
if [ -s "$temp_file" ]; then
# Categorize bounces
@@ -746,7 +746,8 @@ calculate_domain_success_rates() {
if [ -f /tmp/top_recipient_domains.$$ ]; then
while read count domain; do
local delivered=$count
local bounced=$(grep -c "^.*${domain}" /tmp/domains_bounced.$$ 2>/dev/null || echo "0")
# Use word boundary to match exact domain, not substrings
local bounced=$(grep -c "\b${domain}$" /tmp/domains_bounced.$$ 2>/dev/null || echo "0")
local total=$((delivered + bounced))
if [ $total -gt 0 ]; then
@@ -856,7 +857,7 @@ display_issues() {
echo " Last seen: $last_occurrence"
# Check if recent (within last hour of log)
local log_end=$(tail -1 "$TEMP_LOG" | awk '{print $1, $2}')
local log_end=$(tail -1 "$MAIL_LOG" 2>/dev/null | awk '{print $1, $2}')
if [ "$last_occurrence" == "$log_end" ] || [ -z "$last_occurrence" ]; then
echo -e " ${RED}Status: STILL OCCURRING ⚠️${NC}"
else
@@ -1181,8 +1182,9 @@ display_domain_analysis() {
local shown=0
while IFS='|' read rate domain stats; do
# Only show if success rate < 80%
local rate_int=${rate%.*}
if [ "$rate_int" -lt 80 ]; then
# Remove percent sign and decimal portion, keep only integer part
local rate_int=$(echo "$rate" | sed 's/[^0-9].*//')
if [ -n "$rate_int" ] && [ "$rate_int" -lt 80 ]; then
if [ $shown -eq 0 ]; then
echo -e "${RED}${BOLD}⚠️ Domains with Low Delivery Success Rates (<80%):${NC}"
echo ""
@@ -1443,6 +1445,7 @@ main() {
if [ -n "$CUTOFF_TIMESTAMP" ]; then
# Filter by actual timestamps
awk -v cutoff="$CUTOFF_TIMESTAMP" '
BEGIN { print_line = 0 }
/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/ {
timestamp = $1 " " $2
if (timestamp >= cutoff) {