Mini Shell

Direktori : /opt/sharedrads/oldrads/
Upload File :
Current File : //opt/sharedrads/oldrads/outboundspam.sh

#!/bin/bash
# outbound-spam-report.sh
# Written by Ryan C <ryan@imhadmin.net> / x 769
#
# This script examines /var/log/exim_mainlog to find outbound messages
# rejected by cpaneleximscanner (SpamAssassin) and sends an STR when it
# finds an address with a number of rejected messages greater than the
# threshold.
#
# ARGV1 to this script can be an integer in order to adjust
# the threshold

HOSTNAME=$(hostname -s)
CONTACT_EMAIL=str@imhadmin.net
EMAIL_SUBJECT="[AUTO STR] Outbound SPAM on ${HOSTNAME}"

# Parse args
for i in $@; do
    # Use the offset file?
    grep -q 'offset' -- <<<"$i"
    if [[ $? -eq 0 ]]; then
        OFFSET_FILE="/opt/sharedrads/ops/outbound-spam-offset"
        OFFSET=$(grep -E '[0-9]+' $OFFSET_FILE)
        [[ -z $OFFSET ]] && OFFSET=0
    fi

    # Was a threshold specified? We're just looking for some number
    # passed as an argument
    grep -qE '^[0-9]+$' -- <<<"$i"
    if [[ $? -eq 0 ]]; then
        SPAM_THRESHOLD=$i
    fi

    # Send an STR?
    grep -q 'send-str' -- <<<"$i"
    if [[ $? -eq 0 ]]; then
        SEND_STR=1
    fi

    # help?
    grep -qE -- '-h|--help' <<<"$i"
    if [[ $? -eq 0 ]]; then
        cat <<EOF
${0} [-h|--help] [--offset] [--send-str] [SPAM_THRESHOLD]

   -h|--help        Print help and exit.
   --offset         Use offset file. Primarily intended to be used when run from
                    cron.
   --send-str       Send STR to ${CONTACT_EMAIL} for addresses which exceed the
                    threshold.
   SPAM_THRESHOLD   Default: 30; An integer representing the minumum number of
                    blocked messages required in order to be included in the
                    report

 Examples:
 - Suggested cron invocation:
   ${0} --offset --send-str

 - Specify a specific threshold and print to STDOUT
   ${0} 10

EOF
        exit
    fi
done

# Defaults
[[ -z $OFFSET ]] && OFFSET=0
[[ -z $SPAM_THRESHOLD ]] && SPAM_THRESHOLD=30
[[ -z $SEND_STR ]] && SEND_STR=0

# If the offset is greater than the number of lines, start from 0
LOG_LINES=$(wc -l /var/log/exim_mainlog | awk '{print $1}')
[[ $LOG_LINES -lt $OFFSET ]] && OFFSET=0

# Use mawk if it's available
if command mawk 2>/dev/null; then
    AWK=mawk
else
    AWK=awk
fi

RESULTS=$($AWK -v "OFFSET=$OFFSET" \
-v "OFFSET_FILE=$OFFSET_FILE" \
-v "SPAM_THRESHOLD=$SPAM_THRESHOLD" \
'BEGIN {
    ID_TO_EMAIL[0] = ""
    SPAM_COUNT[0] = ""
    USERS[0] = ""
    SPAM_IDS[0] = ""
    SPAM_IPS[0] = ""
    ACL = "/usr/local/cpanel/etc/exim/acls/ACL_OUTGOING_SMTP_CHECKALL_BLOCK/custom_begin_outgoing_smtp_checkall"

    ACL_MAX_SCORE = 0;
    while ((getline < ACL) > 0) {
        SCORE_MATCH=match($0, /[$]spam_score_int[{}]+[0-9]+[}{]+1/)
        if (SCORE_MATCH) {
            ACL_MAX_SCORE = substr($0, SCORE_MATCH + 17, RLENGTH - 20)
            break
        }
    }

    # spam_score_int should be divided by 10 to get the actual spam score that
    # will be used to filter mail
    MAX_SCORE = ACL_MAX_SCORE / 10
}

NR > OFFSET {
    MSG_ID = $3
    if ($0 ~ /cpaneleximscanner detected OUTGOING.*as spam/) {
        MSG_ID = $3
        SPAM_SCORE = substr($NF, match($NF, /-?[0-9.]+/), RLENGTH)
        if (SPAM_SCORE > MAX_SCORE) {
            SPAM_IDS[MSG_ID] = ""
        }
    }
    if (MSG_ID in SPAM_IDS) {
        ADDR_MATCH = match($0, /F=<[a-zA-Z0-9@-.]+>/)
        if (ADDR_MATCH > 0) {
            SPAMMER = substr($0, ADDR_MATCH + 3, RLENGTH - 4)
            SPAM_COUNT[SPAMMER]++
        }
    }
}
END {
    for (ACCOUNT in SPAM_COUNT) {
        if (SPAM_COUNT[ACCOUNT] > SPAM_THRESHOLD) {
            printf("%5s %s\n", SPAM_COUNT[ACCOUNT], ACCOUNT)
        }
    }
    print "\n"
    if (OFFSET_FILE) {
        print NR > OFFSET_FILE
    }
}' /var/log/exim_mainlog)

if [[ $(wc -l <<<"$RESULTS" | awk '{print $1}') -gt 1 ]]; then
    REPORT=$(echo -n "Outbound SPAM Report"
    if [[ ! -z $OFFSET_FILE ]]; then
        echo -ne " for lines ${OFFSET}-$(cat $OFFSET_FILE) of /var/log/exim_mainlog.\n"
    else
        echo -e "Please review mail logs and customer accounts for abuse.\n"
    fi

    printf "%9s %5s %s\n" User "#" Address
    # Time for an ugly BASH loop
    while read number address ; do
        domain=$(cut -d@ -f2<<<"$address")
        user=$(grep -im1 "$domain" /etc/userdomains | cut -d: -f2 )

        # Check to see if it was sent by the cPanel user
        grep -iq "@${HOSTNAME}" <<<"$address"
        if [[ $? -eq 0 ]]; then
            user=$(cut -d@ -f1 <<<"$address")
        fi

        if [[ -z $user ]]; then
            printf "%9s %5s %s\n" -- $number $address
        else
            printf "%9s %5s %s\n" $user $number $address
        fi
    done <<<"$RESULTS" | sort -nk2)

    # Send the report or print it
    if [[ $SEND_STR -eq 1 ]]; then
        echo "$REPORT" | mail -s "${EMAIL_SUBJECT}" $CONTACT_EMAIL
    else
        echo "$REPORT"
    fi
else
    echo "Nothing to report!"
fi

Zerion Mini Shell 1.0