ansible-role-postfix/files/disclaimer.sh

333 lines
14 KiB
Bash
Raw Permalink Normal View History

2022-10-11 09:19:06 +02:00
#!/bin/bash
2023-11-02 16:26:19 +01:00
set -euo pipefail
2022-10-11 09:19:06 +02:00
# 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} <in.$$"
# shellcheck disable=SC2086
result=$("${SENDMAIL}" -v -v ${ARGUMENTS} <"in.$$")
return_code="${?}"
if [[ "${return_code}" != "0" ]]; then
message "Error ${return_code} sending file to sendmail"
message "result: ${result}"
echo "Error ${return_code} sending file to sendmail with disclaimer.sh. result: ${result}" | mail -s "Error in disclaimer.sh filter" ad@susurrando.com
exit ${return_code}
fi
}
#trap "$SENDMAIL '$@' <in.$$" 0 1 2 3 15
trap finish exit
LOGFILE=/var/log/disclaimer.log
if [ ! -w "${LOGFILE}" ]; then
LOGFILE="${HOME}/log/disclaimer.log"
if [ ! -w "${LOGFILE}" ]; then
LOGFILE="./disclaimer.log"
fi
fi
function message() {
HIDE="${2}"
CDATE=$(date '+%Y-%m-%d %H:%M:%S')
APP=$(basename "${0}")
MSG="[$$] ${1}"
if [[ "${HIDE}" != "true" ]]; then
echo "${MSG}"
fi
/usr/bin/logger -t "${APP}" "${MSG}"
echo "${CDATE} ${MSG}" >> "${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 <sysexits.h>
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