#!/bin/bash

#################################################################################
#                                                                               #
#                  ALL THIS SCRIPT IS UNDER GPL LICENSE                         #
# Version 0.4                                                                   #
# Title:     mailgraph                                                          #
# Author:    Alexander Bech  (alex |at| bakarasse |dot| de)                     #
# Date:      2010-01-22                                                         #
# Purpose:   Graphing mail statistics trends                                    #
# Platforms: Uni*                                                               #
# Tested:    Xymon 4.2.3                                                        #
#                                                                               #
# 06.05.2010                                                                    #
# Version 0.4                                                                   #
#  - redesign                                            			#
#  - using logtail2 for more accuracy in logfile parsing                        #
#    Note: rotated file must not be compressed                                  #
#                                                                               #
# 17.04.2010                                                                    #
# Version 0.3                                                                   #
#  - ${WC} -l replaced by ${WC}. WC is defined as WC="/usr/bin/wc -l"           #
#  - Custom variables moved to head of the script                               #
#  - possibility of settting MACHINE variable                                   #
#    Thanks dOCtoR MADneSs                                                      #
#                                                                               #
# 15/03/2010                                                                    #
# Version 0.2                                                                   #
#  - Calculate and graph own runtime.                                           #
#  - Eliminate all greps, seds and awks for better performance.       		#
#                                                                               #
# Version 0.1                                                                   #
#  - Initial version								#
#                                                                               #
#################################################################################

# DEBUG="TRUE"
# 
# Debian based systems have CLIENTHOSTNAME set
# when not set, you can set MACHINE here
if [ -z "${CLIENTHOSTNAME}" ]
then
    # not debian-based
    if [ -z "${MACHINE}" ]
    then
	echo "Error: MACHINE not defined !"
	exit 1
    fi
else
    # Debian-based
    MACHINE=${CLIENTHOSTNAME}
fi

if [ ! -d "$BBTMP" ] ; then             # GET DEFINITIONS IF NEEDED
          echo "*** LOADING HOBBITCLIENT.CFG ***"                  
        . $BBHOME/etc/hobbitclient.cfg          # INCLUDE STANDARD DEFINITIONS
fi

#Change to fit your system/wills :
LOGFILE="/var/log/maillog"
TEST="mailgraph"

MESSAGECOMMAND="status"					# MESSAGECOMMAND: data or status
COLOR="green"
ERRORCOLOR="yellow"

LOGTAIL2="${BBHOME}/bin/logtail2"				# logtail2 executable. logtail2 can find a file that might be the rotated.
							# For debian/ubuntu: apt-get install logtail
OFFSETFILE="${BBTMP}/${TEST}.${MACHINE}.offset"		# logtail2 stores here offset of previous run

### here working:
function debug () {
    if [ "${DEBUG}" = "TRUE" ]
    then
        echo "Debug: $@"
    fi
}

function sendmessage () {
case ${MESSAGECOMMAND}
in
    status)
	MSG="${MESSAGECOMMAND} ${MACHINE}.${TEST} ${COLOR} ${DATE}"
    ;;
    data)
	MSG="${MESSAGECOMMAND} ${MACHINE}.${TEST}"
    ;;
esac
MSG="${MSG}
loglines = ${TAILLINES}
runtime = ${RUNTIME}

mails:
received = ${RECEIVED}
sent = ${SENT}
bounced = ${BOUNCED}
rejected = ${REJECTED}
reject_warning = ${REJECT_WARNING}
warning = ${WARNING}
received_local = ${RECEIVED_LOCAL}
sent_local = ${SENT_LOCAL}

amavis:
passed_clean = ${PASSED_CLEAN}
blocked_virus = ${BLOCKED_VIRUS}
blocked_banned = ${BLOCKED_BANNED}

spamd:
spam = ${SPAM}
non_spam = ${NON_SPAM}

postgrey:
greylisted = ${GREYLISTED}
early-retry = ${EARLY_RETRY}
delayed = ${DELAYED}
passed = ${PASSED}
reason_triplet_found = ${REASON_TRIPLET_FOUND}
reason_awl = ${REASON_AWL}
reason_client_wl = ${REASON_CLIENT_WL}
reason_recip_wl = ${REASON_RECIP_WL}
"
debug "${BB} ${BBDISP} ${MSG}"
${BB} ${BBDISP} "${MSG}"
}

function senderrormessage () {
    debug "${MSG}"
    ${BB} ${BBDISP} "status ${MACHINE}.${TEST} ${COLOR} ${DATE}
    ${MSG}"
}

RUNTIME=0

declare -i TAILLINES=0
declare -i RECEIVED=0
declare -i SENT=0
declare -i BOUNCED=0

declare -i REJECTED=0
declare -i REJECT_WARNING=0
declare -i WARNING=0

declare -i RECEIVED_LOCAL=0
declare -i SENT_LOCAL=0

declare -i PASSED_CLEAN=0
declare -i BLOCKED_VIRUS=0
declare -i BLOCKED_BANNED=0

declare -i SPAM=0
declare -i NON_SPAM=0

declare -i GREYLISTED=0
declare -i EARLY_RETRY=0
declare -i DELAYED=0
declare -i PASSED=0

declare -i REASON_TRIPLET_FOUND=0
declare -i REASON_AWL=0
declare -i REASON_CLIENT_WL=0
declare -i REASON_RECIP_WL=0

LC_ALL=C
LANG=C
LANGUAGE=C
MSG=""

STARTTIME=$(date +%s.%N)
DATE=$(date)
debug "$DATE $0 "

if [ ! -x ${LOGTAIL2} ]; then
    COLOR="${ERRORCOLOR}"
    MSG="Error: ${LOGTAIL2} not found"
    senderrormessage
    exit 0
fi

if [ -e ${LOGFILE} ]; then
    if [ ! -e ${OFFSETFILE} ]
    then 
	debug "First run. Start monitoring at end of ${LOGFILE}"
	# First run. All data must be = 0. Initialize offsetfile, send message and exit.
	LINES=$(${LOGTAIL2} -f ${LOGFILE} -o ${OFFSETFILE})
	 if [ ${?} != 0 ]
	 then
	    COLOR="${ERRORCOLOR}"
	    MSG=$(echo -e "Error while reading ${LOGFILE}\n${LINES}")
	    senderrormessage
	    exit 0
	 fi
	# send message with first run data (=0):
	sendmessage
	exit 0
    fi

    # Fetching new loglines
    LINES=$(${LOGTAIL2} -f ${LOGFILE} -o ${OFFSETFILE} 2>&1)
    if [ ${?} != 0 ]
    then
	# send errormessage:
	COLOR="${ERRORCOLOR}"
	MSG=$(echo -e "Error while reading ${LOGFILE}\n${LINES}")
	senderrormessage
	exit 0
    fi

else
    # send errormessage:
    COLOR="${ERRORCOLOR}"
    MSG="Error: ${LOGFILE} not found."
    senderrormessage
    exit 0
fi

# Parse new loglines
ORIGIFS=${IFS}
IFS=$'\n'
for LINE in ${LINES}
do
    IFS=${ORIGIFS}
    ((TAILLINES++))
    set -- ${LINE}

    if [ "${5:0:8}" = "postgrey" ]
    then
    	if [ "${LINE}" != "${LINE/action=greylist, reason=new}" ]; then ((GREYLISTED++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=greylist, reason=early-retry}" ]; then ((EARLY_RETRY++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=pass, reason=triplet found, delay=}" ]; then ((PASSED++)); ((REASON_TRIPLET_FOUND++)); ((DELAYED++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=pass, reason=triplet found, client_name=}" ]; then ((PASSED++)); ((REASON_TRIPLET_FOUND++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=pass, reason=client AWL}" ]; then ((PASSED++)); ((REASON_AWL++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=pass, reason=client whitelist}" ]; then ((PASSED++)); ((REASON_CLIENT_WL++)); continue; fi
    	if [ "${LINE}" != "${LINE/action=pass, reason=recipient whitelist}" ]; then ((PASSED++)); ((REASON_RECIP_WL++)); continue; fi
    fi
    
    if [ "${5:0:5}" = "sSMTP" ]
    then
	if [ "${6} ${7} ${8}" = "Sent mail for" ]; then ((SENT++)); continue; fi
    	if [ "${6} ${7:0:3} ${8:1:1}" = "RCPT TO: 4" ]; then ((BOUNCED++)); continue; fi
    	if [ "${6} ${7:0:3} ${8:1:1}" = "RCPT TO: 5" ]; then ((BOUNCED++)); continue; fi
    fi
    
    if [ "${5:0:7}" = "postfix" ]
    then
	PROG="${5:8}"; PROG="${PROG%%[*}"
	case ${PROG}
	in

	smtp)
	    if [ "${LINE}" != "${LINE/ status=sent }" ]; then
		if [ "${LINE}" != "${LINE/ relay=127.0.0.1}" -o "${LINE}" != "${LINE/ relay=localhost}" ]; then
		    ((SENT_LOCAL++)); continue;
		else
		    ((SENT++)); continue;
		fi
	    fi
	    if [ "${LINE}" != "${LINE/ status=bounced }" ]; then ((BOUNCED++)); continue; fi
	;;

	smtpd)
	    if [ "${17} ${18} ${20}" = "Greylisted for seconds;" ]; then continue; fi
	    if [ "${6} ${7}" = "NOQUEUE: reject:" ]; then ((REJECTED++)); continue; fi
	    if [ "${6} ${7}" = "NOQUEUE: reject_warning:" ]; then ((REJECT_WARNING++)); continue; fi
	    if [ "${6} ${7}" = "NOQUEUE: warn:" ]; then ((WARNING++)); continue; fi
	    if [ "${7:0:27}" = "client=localhost[127.0.0.1]" ]; then ((RECEIVED_LOCAL++)); continue; fi
	    if [ "${7:0:39}" = "client=localhost.localdomain[127.0.0.1]" ]; then ((RECEIVED_LOCAL++)); continue; fi
	    if [ "${7:0:7}" = "client=" ]; then ((RECEIVED++)); continue; fi
	;;

	pickup)
	    if [ "${7:0:4} ${8:0:5}" = "uid= from=" ]; then ((RECEIVED_LOCAL++)); continue; fi
	;;

	local|pipe)
	    if [ "${LINE}" != "${LINE/ status=sent }" ]; then ((SENT_LOCAL++)); continue; fi
	    if [ "${LINE}" != "${LINE/ status=bounced }" ]; then ((BOUNCED++)); continue; fi
	;;

	cleanup)
	    # fix me?
	    continue
	;;
	anvil|qmgr)
	    # fix me?
	    continue
	;;
	*)
	    continue
	;;
	esac
    fi

    if [ "${5:0:6}" = "amavis" ]
    then
	# Feb 28 21:56:49 servername amavis[19268]: (19268-04) Passed CLEAN, LOCAL [192.168.6.13] [192.168.6.13] <user@domain.de> -> <user@domain.com>, Message-ID: <20100228205640.AF34B19F7C@pc.lan>, mail_id: MiyfCvjWKGzy, Hits: -, queued_as: 14DE01E7B30, 7166 ms
	if [ "${7}" = "Passed" ]; then ((PASSED_CLEAN++)); continue; fi
	if [ "${7} ${8}" = "Blocked INFECTED" ]; then ((BLOCKED_VIRUS++)); continue; fi
	if [ "${7} ${8}" = "Blocked BANNED" ]; then ((BLOCKED_BANNED++)); continue; fi
    fi

    if [ "${5:0:5}" = "spamd" ]
    then
	#Feb 28 22:21:00 servername spamd[1852]: spamd: clean message (-2.0/5.0) for spamfilter:1010 in 2.2 seconds, 4294 bytes.
	if [ "${7} ${8}" = "clean message" ]; then ((NON_SPAM++)); continue; fi
	if [ "${7} ${8}" = "identified spam" ]; then ((SPAM++)); continue; fi
    fi
done

ENDTIME=$(date +%s.%N)
RUNTIME=$(echo "${STARTTIME} ${ENDTIME}" | ${AWK} '{print $2 - $1}')

sendmessage
