#!/bin/bash version="0.41.0" # --- Configuration variables --- # the filter executable: FILTER_BIN=/usr/bin/postconfirmc # Mailman's distributed mailman executable: MAILMAN_BIN=/usr/lib/mailman/mail/mailman # Mail handler executable SENDMAIL_BIN=/usr/sbin/sendmail # Where we store mailman commands identified as spam SPAM_STASH=/a/postconfirm/cache # --- Re-invoke with logging --- if [ "$RUNNING" != "$0" ]; then export RUNNING=$0 $0 "$@" 2>&1 | logger -t postconfirmw exit ${PIPESTATUS[0]} fi # Command line arguments ## The 'action' argument is set by the caller. Mailman will set 'action' to one ## of "post", "owner", or "admin". The postfix group-alias and draft-alias lists ## will set 'action' to "filter". action="$1" dest="$2" domain="$3" [ "$domain" ] || domain=${RECIPIENT##*@} # Debug switch DEBUG="" # Uncomment for debug: #DEBUG=1 # ---------------- function die() { echo -e "\n$program: error: $*" > /dev/stderr exit 1 } # ---------------- function note() { [ "$DEBUG" ] && echo -e "$*" logger -i -p user.info -t postconfirmw "$*" } # --- Start of script proper --- if [ "$DEBUG" ]; then echo "-----------------------------" date cat <<-EOF Prog: $0 Args: $@ User: $(whoami) USER : $USER SENDER : $SENDER RECIPIENT: $RECIPIENT EOF fi unset HOME [ -d $SPAM_STASH ] || mkdir -p $SPAM_STASH SEND_LOCALPART=${SENDER%@*} RECV_LOCALPART=${RECIPIENT%@*} if [ "${SEND_LOCALPART##*-}" = "bounces" -a "${RECV_LOCALPART##*-}" = "owner" ]; then note "Mailman response piped directly to mailman" $MAILMAN_BIN "$action" "$dest" elif [ "$action" = post -o "$action" = owner -o "$action" = admin -o "$action" = filter ]; then # Using a temp file to hold the message isn't pretty, but we need to catch the exit # code from tmda_filter to decide whether to pipe stuff into mailman or not, and # neither $? or $PIPESTATUS[0] lets us do that inside the pipe itself. tmp=$(mktemp -t postconfirm-tmp-XXXXXX) out=$(mktemp -t postconfirm-out-XXXXXX) err=$(mktemp -t postconfirm-err-XXXXXX) if [ "$action" = filter ]; then cat - > $tmp else # Add List-Id: so that we're able to calculate the Archived-At: header later. # This will be overwritten by Mailman during its processing. cat - | formail -I "List-ID: <$dest.ietf.org>" > $tmp fi note "Input piped to postconfirm: '$FILTER_BIN confirm'" $FILTER_BIN confirm < $tmp 2>$err | /a/postconfirm/insert_expanded_headers "$dest" > $out errnum=${PIPESTATUS[0]} if [ "$DEBUG" ]; then echo "--- $(date +%Y-%m-%d_%H:%M): $* [$SENDER => $RECIPIENT] ---" >> /tmp/postconfirm-debug.log head $out >> /tmp/postconfirm-debug.log fi if [ $errnum == 0 ]; then if [ "$action" = filter ]; then note "Input forwarded to MTA ($SENDMAIL_BIN -f $SENDER $dest@$domain)" $SENDMAIL_BIN -f "$SENDER" "$dest@$domain" < $out else note "Input forwarded to mailman ($MAILMAN_BIN $action $dest)" $MAILMAN_BIN "$action" "$dest" < $out fi elif [ $errnum == 1 ]; then note "Error return $errnum from $FILTER_BIN -- not forwarding" [ "$DEBUG" ] && cat $err else if [ "$action" = filter ]; then echo "$FILTER_BIN failure (error $errnum) -- input forwarded to MTA" $SENDMAIL_BIN -f "$SENDER" "$dest@$domain" < $tmp else echo "$FILTER_BIN failure (error $errnum) -- input forwarded to mailman" $MAILMAN_BIN "$action" "$dest" < $tmp fi fi [ "$DEBUG" ] || rm -f $tmp $out $err else cmd=$(mktemp -t postconfirm-cmd-XXXXX) cat - > $cmd spamflag=$(echo $(formail -c -x "X-Spam-Flag" < $cmd)) if [ "$spamflag" = "YES" ]; then spam=$(mktemp "$SPAM_STASH/spamXXXXXXXX") mv $cmd $spam echo "Mailman command flagged as spam, saved as $spam" else actn=$(mktemp "$SPAM_STASH/actnXXXXXXXX") mv $cmd $actn echo "Command '$action': <$SENDER> -> $dest piped to mailman after spam check, saved as $actn" $MAILMAN_BIN "$action" "$dest" < $actn #rm -f $cmd fi fi true