Text Share Online

yxc

#!/bin/bash

# Define recipient email address
REPORT_RECIPIENT=”[email protected]” # <— IMPORTANT: Change this to your email address!

# Define the log file (adjust if your mail logs are in a different location)
MAIL_LOG=”/var/log/mail.log”

# — Calculate yesterday’s date manually for maximum compatibility —
# Get current date components
CURRENT_YEAR=$(/bin/date +%Y)
CURRENT_MONTH=$(/bin/date +%m)
CURRENT_DAY=$(/bin/date +%d)

# Convert to seconds since epoch, subtract 24 hours, then convert back
# This is a more robust way to get yesterday’s date if -d “yesterday” is not supported
YESTERDAY_EPOCH=$(/bin/date -j -f “%Y %m %d %H %M %S” “$CURRENT_YEAR $CURRENT_MONTH $CURRENT_DAY 00 00 00” +%s)
YESTERDAY_EPOCH=$((YESTERDAY_EPOCH – 86400)) # Subtract 24 hours (86400 seconds)
YESTERDAY_FULL=$(/bin/date -r “$YESTERDAY_EPOCH” +%Y-%m-%d)

# If the above fails (e.g., -j or -r not supported), fall back to a simpler method
if [ -z “$YESTERDAY_FULL” ]; then
# This fallback is less precise but might work on very old systems
# It assumes the log file is rotated daily and yesterday’s log is mail.log.1 or similar
# For now, let’s try to get today minus one day using a different date command if available
# Or, as a last resort, we might have to hardcode or ask the user for the date.
# Given your log format, a YYYY-MM-DD is crucial.
# Let’s try a common alternative for date manipulation if -d is missing
# This might still fail, but it’s worth a shot.
# If this still fails, we will need to reconsider the approach for date calculation.
echo “Warning: Standard date calculation failed. Attempting alternative.” >&2
YESTERDAY_FULL=$(/bin/date +%Y-%m-%d –date=’1 day ago’) # Try GNU date syntax again, just in case
if [ -z “$YESTERDAY_FULL” ]; then
echo “Error: Could not determine yesterday’s date even with alternative methods. Please manually set YESTERDAY_FULL or update your ‘date’ utility.” >&2
exit 1
fi
fi

# Define the report file (ensure YESTERDAY_FULL is correctly set before this)
REPORT_FILE=”/tmp/daily_mail_report_${YESTERDAY_FULL}.txt” # Added date to filename for clarity and uniqueness

# — Start of Report Generation —
echo “Daily Postfix Mail Report for $YESTERDAY_FULL” > “$REPORT_FILE”
echo “—————————————————” >> “$REPORT_FILE”
echo “” >> “$REPORT_FILE”

# Option 1: Simple summary of sent/received
echo “— Mail Summary (Sent/Received) —” >> “$REPORT_FILE”
# Now grepping for the YYYY-MM-DD format
grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/” | grep -E “status=(sent|deferred|bounced)” | awk ‘{print $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14}’ >> “$REPORT_FILE”
echo “” >> “$REPORT_FILE”

# Option 2: More detailed view (example – adjust as needed)
echo “— Detailed Mail Flow (Sender, Recipient, Subject – if available) —” >> “$REPORT_FILE”

# Temporarily store relevant log lines for yesterday
TEMP_LOG_LINES=$(grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/”)

# Use a here-document (EOF) to pass the awk script, preventing shell interpretation issues
echo “$TEMP_LOG_LINES” | awk -F’ ‘ ‘
BEGIN {
# Initialize associative arrays to store message details
# We use qid (including the trailing colon) as the key to link related log entries
}

# Process smtpd lines for client IP and SASL username
/postfix/smtpd[/ {
qid = $4; # Queue ID is the 4th field in your logs (e.g., A74F4E6657:)

ip_match = match($0, /client=[^ ]+\[([^\]]+)\]/);
if (ip_match) {
qid_client_ip[qid] = substr($0, RSTART + 8, RLENGTH – 9);
}

user_match = match($0, /sasl_username=([^ ]+)/);
if (user_match) {
qid_sasl_user[qid] = substr($0, RSTART + 14, RLENGTH – 14);
}
}

# Process cleanup lines for message-id
/postfix/cleanup[.*]: message-id=</ {
qid = $4; # Queue ID is the 4th field in your logs
msgid_match = match($0, /message-id=<([^>]+)>/);
if (msgid_match) {
qid_msgid[qid] = substr($0, RSTART + 12, RLENGTH – 13);
}
}

# Process qmgr lines for sender
/postfix/qmgr[.*]: ([0-9A-F]+): from=</ {
qid = $4; # Queue ID is the 4th field in your logs
sender_match = match($0, /from=<([^>]+)>/);
if (sender_match) {
qid_from[qid] = substr($0, RSTART + 6, RLENGTH – 7);
} else {
qid_from[qid] = “<>”; # Handle empty sender (e.g., bounce messages)
}
}

# Process smtp/local/virtual lines for recipient and status
/postfix\/(smtp|local|virtual)\[.*\]: ([0-9A-F]+): to=</ {
qid = $4; # Queue ID is the 4th field in your logs
recipient_match = match($0, /to=<([^>]+)>/);
if (recipient_match) {
qid_to[qid] = substr($0, RSTART + 4, RLENGTH – 5);
}

status_match = match($0, /status=(sent|deferred|bounced)/);
if (status_match) {
qid_status[qid] = substr($0, RSTART + 7, RLENGTH – 7);
} else {
qid_status[qid] = “unknown”; # Default if status not found
}
}

# Process bounce lines (these are often separate from the main mail flow)
/postfix/bounce[.*]: ([0-9A-F]+): sender non-delivery notification:/ {
qid = $4; # Queue ID is the 4th field in your logs
qid_status[qid] = “bounced”; # Explicitly mark as bounced
# The `from` and `to` for the original message are usually in earlier qmgr/smtp lines
}

# END block to print the collected information
END {
for (qid in qid_from) { # Iterate through all unique queue IDs found
print “—————————————————“;
print “QID: ” substr(qid, 1, length(qid)-1); # Remove the trailing colon for display
if (qid_msgid[qid]) print ” Message ID: ” qid_msgid[qid];
if (qid_from[qid]) print ” From: ” qid_from[qid];
if (qid_to[qid]) print ” To: ” qid_to[qid];
if (qid_status[qid]) print ” Status: ” qid_status[qid];
if (qid_client_ip[qid]) print ” Client IP: ” qid_client_ip[qid];
if (qid_sasl_user[qid]) print ” SASL User: ” qid_sasl_user[qid];
print “”;
}
}
‘ >> “$REPORT_FILE”

echo “” >> “$REPORT_FILE”
echo “— Summary Counts —” >> “$REPORT_FILE”
# Now grepping for the YYYY-MM-DD format
echo “Total messages processed (approx): $(grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/qmgr” | grep “from=” | wc -l)” >> “$REPORT_FILE”
echo “Messages sent successfully: $(grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/” | grep “status=sent” | wc -l)” >> “$REPORT_FILE”
echo “Messages deferred: $(grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/” | grep “status=deferred” | wc -l)” >> “$REPORT_FILE”
echo “Messages bounced: $(grep “$YESTERDAY_FULL” “$MAIL_LOG” | grep “postfix/” | grep “status=bounced” | wc -l)” >> “$REPORT_FILE”
echo “—————————————————” >> “$REPORT_FILE”

# Send the report via email
mail -s “Daily Postfix Mail Report – $YESTERDAY_FULL” “$REPORT_RECIPIENT” < “$REPORT_FILE”

# Clean up the temporary report file
rm “$REPORT_FILE”

echo “Daily mail report generated and sent to $REPORT_RECIPIENT.”

Share This: