#!/bin/bash set -euo pipefail # http://www.postfix.org/FILTER_README.html # Clean up when done or when aborting. finished=false SENDMAIL=$(which sendmail) if [ -z ${SENDMAIL} ]; then if [ -x "/usr/sbin/sendmail" ]; then SENDMAIL="/usr/sbin/sendmail" else nessage "Sendmail command not found" fi fi function finish { ${finished} || logger -t disclaimer "Disclaimer script not finished cleanly." message "Sendmail command: ${SENDMAIL} -v -v ${ARGUMENTS} > "${LOGFILE}" } ARGUMENTS=${*} inspect_dir=/var/spool/filter export HOME="${inspect_dir}" out_stat_folder="${inspect_dir}/out.stats" mkdir -p "${out_stat_folder}" in_stat_folder="${inspect_dir}/in.stats" mkdir -p "${in_stat_folder}" DISCLAIMER_ADDRESSES=/etc/postfix/disclaimer_addresses TEXT_DISCLAIMER=/etc/postfix/text_disclaimer.txt HTML_DISCLAIMER_FILE=/etc/postfix/html_disclaimer.htm # Exit codes from EX_TEMPFAIL=75 EX_UNAVAILABLE=69 DATE=$(date +%s) #GetRecordID $FROM mail_addresses mail_address mail function GetRecordID() { TEXT=$(echo "$1" | sed "s/'/\'/g" -) ERR="${?}" if [[ "$ERR" != "0" ]] then message "Error $ERR escaping single quotes from TEXT in GetRecordID" fi if [[ "$TEXT" == "" ]]; then echo NULL else TABLE=$(echo "$2" | sed "s/'/\'/g" -) ERR="${?}" if [[ "$ERR" != "0" ]] then message "Error $ERR escaping single quotes from TABLE in GetRecordID" fi FIELD=$(echo "$3" | sed "s/'/\'/g" -) ERR="${?}" if [[ "$ERR" != "0" ]] then message "Error $ERR escaping single quotes from FIELD in GetRecordID" fi DATABASE=$(echo "$4" | sed "s/'/\'/g" -) ERR="${?}" if [[ "$ERR" != "0" ]] then message "Error $ERR escaping single quotes from DATABASE in GetRecordID" fi if [[ "$DATABASE" == "" ]]; then message "No database indicated." true else ACTION=$(echo "$5" | sed "s/'/\'/g" -) ERR="${?}" if [[ "$ERR" != "0" ]] then message "Error $ERR escaping single quotes from $ACTION in GetRecordID" fi QUERY="SELECT id FROM $TABLE WHERE $FIELD='$TEXT';" result=$(echo "$QUERY" | /usr/bin/env mysql "$DATABASE") resultID=$(echo "$result" | grep -v id) return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Error getting $FIELD id for $TEXT from database with query '$QUERY'. result: $result" true else if [[ "$resultID" == "" ]]; then message "The field '$TABLE.$FIELD' in database '$DATABASE' doesn't contain a record '$TEXT', adding it." QUERY="INSERT INTO $TABLE (id, $FIELD) VALUES (NULL, '$TEXT');" temp_file=$(mktemp /tmp/tmp.XXXXX) echo "$QUERY" | /usr/bin/env mysql -v -v -v "$DATABASE" &> "${temp_file}" return_code="${?}" result=$(cat "${temp_file}") if [[ "$return_code" != "0" ]]; then message "Error $return_code adding $FIELD to database '$DATABASE' with query '$QUERY'. result: $result" true else QUERY="SELECT id FROM $TABLE WHERE $FIELD='$FROM';" result=$(echo "$QUERY" | /usr/bin/env mysql "${DATABASE}") resultID=$(echo "$result" | grep -v id) return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Error $return_code obtaining $FIELD id with query '$QUERY'. result: $result" true exit 1 fi fi fi fi echo "${resultID}" fi fi } function FromID() { FROM="$1" SENDER_ID=$(GetRecordID "$FROM" senders sender mail "Getting Id for From $1") echo "${SENDER_ID}" } function RecipientID() { RECIPIENT="$1" RECIPIENT_ID=$(GetRecordID "$FROM" recipients recipient mail "Getting Id for To $1") echo "${RECIPIENT_ID}" } # Start processing. message "Processing message 'in.$$' as user '$(whoami)'..." cd "${inspect_dir}" || exit return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Error $return_code changing to directory '$inspect_dir'" exit $EX_TEMPFAIL; fi cat >in.$$ return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Cannot save mail to file" exit $EX_TEMPFAIL fi message "Adding labels..." /usr/bin/env python3 /etc/postfix/labeler.py in.$$ > in.$$.labeler.log cp in.$$.labeler.log /var/spool/filter/last_message.eml.labeler.log -rfp #Save last message message "Saving as last_message.eml..." cp in.$$ /var/spool/filter/last_message.eml -rfp #Save copy of the messages. DANGEROUS!! Will consumpt disk space message "Saving copy of message (this might fill the disk)..." mkdir -p "/var/spool/filter/$(date +%Y%m%d)/" cp in.$$ "/var/spool/filter/$(date +%Y%m%d)/$(date +%Y%m%d%H%M%S%N).eml" -rfp # obtain headers message "Obtaining headers..." HEADERS=$(sed ':a;N;$!ba;s/\n\n.*//g' in.$$) messageID=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 -i "^message-id: " | sed 's/^message-id: //g' | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "message ID: '$messageID'" FROMLONG=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^From:" | sed "s/From: //" -) SENDER_ID=$(FromID "$FROM") message "From(long): '${FROMLONG}' (Id: $SENDER_ID)" FROM=$(echo "${FROMLONG}" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "From(short): '${FROM}'" SUBJECT=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Subject:" | sed "s/Subject: //" - | sed "s/'/\'/g" - ) message "Subject: '$SUBJECT'" RECIPIENT=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^To:" | sed "s/To: //g" - | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) RECIPIENT_ID=$(RecipientID "$RECIPIENT") message "TO: '$RECIPIENT'" CCRECIPIENT=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Cc:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "CC: '$CCRECIPIENT'" BCRECIPIENT=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Bcc:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "CCO: '$BCRECIPIENT'" DELIVEREDTO=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Delivered-To:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Delivered to: '$DELIVEREDTO'" RETURNPATH=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Return-Path:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Return path: '$RETURNPATH'" REPLYTO=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Reply-To:" | sed "s/Sender: //g" - | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to: '$REPLYTO'" XORIGINALSENDER=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' |grep -m 1 "^X-Original-Sender:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to (original sender): '$XORIGINALSENDER'" SENDER=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^Sender:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to (sender): '$SENDER'" XFORWARDEDTO=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^X-Forwarded-To:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to (forwarded to): '$XFORWARDEDTO'" XFORWARDEDFOR=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' |grep -m 1 "^X-Forwarded-For:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to (forwarded for): '$XFORWARDEDFOR'" XBEENTHERE=$(echo "$HEADERS" | sed ':a;N;$!ba;s/\n\s/ /g' | grep -m 1 "^X-BeenThere:" | cut -d "<" -f 2 | cut -d ">" -f 1 | sed "s/'/\'/g" - ) message "Reply to (been there): '$XBEENTHERE'" if grep -qi "^${FROM}$" "${DISCLAIMER_ADDRESSES}"; then message "This is a mail from a local user '$FROM' with a disclaimer text, adding it to the message..." DIRECTION=0 CURHOUR=$(date +%Y%m%d%H) if [[ -e $in_stat_folder/$CURHOUR.stats ]]; then CURHOURSTAT=$(cat "$in_stat_folder/$CURHOUR.stats") else CURHOURSTAT=0 fi CURHOURSTAT=$((CURHOURSTAT + 1)) echo "$CURHOURSTAT" > "$in_stat_folder/$CURHOUR.stats" QUERY="INSERT INTO messages (id, sender_id, subject, date, messageid) VALUES (NULL, '$SENDER_ID', '$SUBJECT', '$DATE', '$messageID');" temp_file=$(mktemp /tmp/tmp.XXXX) echo "$QUERY" | /usr/bin/env mysql -v -v -v mailview &> "${temp_file}" return_code="${?}" result=$(cat "${temp_file}") if [[ "$return_code" != "0" ]]; then message "Error $return_code while adding message to database 'mailview' with query '$QUERY'. result: '${result}'" fi QUERY="SELECT id FROM messages WHERE sender_id='$SENDER_ID' AND subject='$SUBJECT' AND date='$DATE';" # MSG_ID=$(echo "$QUERY" | /usr/bin/env mysql mailview | grep -v id) return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Error $return_code while obtaining message id with query '$QUERY' from database 'mailview'" fi TMP_HTML_DISCLAIMER_FILE=$(/bin/mktemp /tmp/disclaimer.XXXXX) if [[ -r /etc/postfix/$FROM.disclaimer.html ]]; then HTML_DISCLAIMER="/etc/postfix/$FROM.disclaimer.html" echo "${HTML_DISCLAIMER}" > /dev/null fi sed "s/id=MSGID/id=$DB_MSG_ID/g" $HTML_DISCLAIMER_FILE > "$TMP_HTML_DISCLAIMER_FILE" TMP_HTML_DISCLAIMER_FILE_BIS=$(/bin/mktemp /tmp/disclaimer.XXXXX) sed "s/SENDERID/$SENDER_ID/g" "$TMP_HTML_DISCLAIMER_FILE" > "$TMP_HTML_DISCLAIMER_FILE_BIS" sed "s/RECIPIENTID/$RECIPIENT_ID/g" "$TMP_HTML_DISCLAIMER_FILE_BIS" > "$TMP_HTML_DISCLAIMER_FILE" message "Disclaimer HTML at '$TMP_HTML_DISCLAIMER_FILE'" if [[ -r /etc/postfix/$FROM.disclaimer.txt ]]; then TEXT_DISCLAIMER=/etc/postfix/$FROM.disclaimer.txt fi message "Running altermime with: /usr/bin/altermime --input=in.$$ --log-syslog --log-stdout --disclaimer=$TEXT_DISCLAIMER --disclaimer-html=$TMP_HTML_DISCLAIMER_FILE --xheader=\"X-MTA: $(cat /etc/mailname)\"" ALTERMIMEresult=$(/usr/bin/altermime --input=in.$$ --log-syslog --log-stdout --disclaimer="$TEXT_DISCLAIMER" --disclaimer-html="$TMP_HTML_DISCLAIMER_FILE" --xheader="X-MTA: $(cat /etc/mailname)") message "altermime result: $ALTERMIMEresult" return_code="${?}" if [[ "$return_code" != "0" ]]; then message "Error $return_code message content rejected." exit $EX_UNAVAILABLE; fi else DIRECTION=1 message "Sender '$FROMLONG' ($FROM) is NOT in disclaimer addresses file" CURHOUR=$(date +%Y%m%d%H) if [[ -e $out_stat_folder/$CURHOUR.stats ]]; then CURHOURSTAT=$(cat "$out_stat_folder/$CURHOUR.stats") else CURHOURSTAT=0 fi CURHOURSTAT=$((CURHOURSTAT + 1)) echo $CURHOURSTAT > "$out_stat_folder/$CURHOUR.stats" fi #Stats FROMID=$(GetRecordID "$FROM" mail_addresses mail_address mail "Get ID of From $FROM") message "From $FROM with ID $FROMID" if [[ "$RECIPIENT" != "" ]]; then TOID=$(GetRecordID "$RECIPIENT" mail_addresses mail_address mail "Get ID of To $TO") else TOID="0" fi message "To $RECIPIENT with ID $TOID" if [[ -z "$CCRECIPIENT" ]]; then CCID=$(GetRecordID "$CCRECIPIENT" mail_addresses mail_address mail "Get ID of CC") else CCID="0" fi if [[ -z "$BCRECIPIENT" ]]; then CCOID=$(GetRecordID "$BCRECIPIENT" mail_addresses mail_address mail "Get ID of BCC") else CCOID="0" fi if [[ -z "$DELIVEREDTO" ]]; then DTID=$(GetRecordID "$DELIVEREDTO" mail_addresses mail_address mail "Get ID of DeliveredTo") else DTID="0" fi if [[ -z "$RETURNPATH" ]]; then RPID=$(GetRecordID "$RETURNPATH" mail_addresses mail_address mail) else RPID="0" fi if [[ -z "$XORIGINALSENDER" ]]; then XOSID=$(GetRecordID "$XORIGINALSENDER" mail_addresses mail_address mail) else XOSID="0" fi if [[ -z "$SENDER" ]]; then SID=$(GetRecordID "$SENDER" mail_addresses mail_address mail) else SID="0" fi if [[ -z "$XFORWARDEDTO" ]]; then XFTID=$(GetRecordID "$XFORWARDEDTO" mail_addresses mail_address mail) else XFTID="0" fi if [[ -z "$XFORWARDEDFOR" ]]; then XFFID=$(GetRecordID "$XFORWARDEDFOR" mail_addresses mail_address mail) else XFFID="0" fi QUERY="INSERT INTO stats (msgid, from_id, to_id,cc_id, cco_id, subject, direction, delivered_to_id, return_path_id, s_original_sender_id, sender_id, x_forwarded_to, x_forwarded_for) VALUES ('$messageID',$FROMID, $TOID, $CCID, $CCOID, '$SUBJECT', $DIRECTION, $DTID, $RPID, $XOSID, $SID, $XFTID, $XFFID);" temp_file=$(mktemp /tmp/tmp.XXXX) echo "${QUERY}" | /usr/bin/env mysql -v -v -v mail &> "${temp_file}" return_code="${?}" result=$(cat "${temp_file}") if [[ "${return_code}" != "0" ]]; then message "Error ${return_code} saving stats with query '${QUERY}'. result: ${result}" fi finished=true