On 8.1.2013 4:33, Troy Ayers wrote:
> Could I trouble you for a sanitized version of your
> /usr/site/dspam_train/bin/dspam_fp script? My system is ...
I am so sorry. I missed your original email a couple weeks ago. I will attach
the script we use.
The bad news is that the script relies on a slightly patched DSPAM: it causes
DSPAM to print error messages to STDERR in addition to it's normal logging.
The patch is only a few lines, and we've used it for many years. However, I
don't know if it's OK for the general community. I'll attach that patch too.
Before invoking DSPAM for retraining, you could verify that the signature
exists; if it does not, don't invoke DSPAM - invoke direct delivery instead.
We implimented this for testing long ago, but we decided on the STDERR route.
Tod Sandman
Sr. Systems Administrator
Middleware Development & Integration
Rice University
Voice: 713.348.5816
#!/bin/sh
###############################################################################
#
# Project: DSPAM
# Program: dspam_fp - retrain/deliver a false positive from the quarantine.
# Version: 0.0
# Author: Tod Sandman
# Start Date: 01/05/06
#
# Usage: dspam_fp [-h] [-u USER] [-d USER2] < message
#
# When dspam is invoked with the --deliver option, dspam exiting with a
# successful status does not assure the message was actually delivered. For
# instance, if the dspam signature in the message is not found in the dspam
# database because it has expired, dspam drops the message but exits with
# "success" (it does log a warning if logging is configured).
#
# This behavior makes sense since dspam is generally receiving mail from the
# big bad world; it does not want to provide back door access for SPAM.
#
# However, when an authenticated user attempts to deliver a mis-classified
# email from his quaratntine, we really want to make sure the message is
# delivered. We'd even prefer a duplicate delivery over a lost message.
#
# This script first tries to deliver the email via dspam as normal, but if
# successful delivery is not certain, it then tries to deliver the message
# directly without going through dspam.
#
# A user must be either passed in with the -u option, or set in the
# "EXTENSION" environemnt variable. The -u over-rides $EXTENSION.
#
# This script is meant to be called via the DSPAM WebUI (see the DELIVER_FP
# configuration setting). An exit value of 0 indicates the message was
# delivered; the WebUI will delete the message from the user's quarantine.
# A non-zero exit indicates the message was not delivered; the WebUI should
# not delete the message from the user's quarantine, and the user will be
# alerted. This script should only ouput something if there were issues.
#
###############################################################################
PATH=/bin:/usr/bin:/usr/sbin:/sbin
program=`basename $0`
nodename="`uname -n | sed 's/\..*$//'`"
dspam=/usr/bin/dspam
dspam_tmp_dir=/var/lib/dspam/tmp
## Set this IF this command is to be run as a DSPAM-trusted user:
DSPAM_TRUSTED_USER=true
## DSPAM training options:
train_opts="--class=innocent --source=error --deliver=innocent"
if [ -n "$DSPAM_TRUSTED_USER" ]; then
train_opts="--user USER $train_opts"
fi
## Direct delivery options for Cyrus backends:
deliver=/usr/lib/cyrus-imapd/deliver
if [ -f $deliver ]; then
if [ -n "$DSPAM_TRUSTED_USER" ]; then
deliver_opts=USER
fi
else
deliver=/usr/bin/procmail
deliver_opts="-Y -f -"
if [ -n "$DSPAM_TRUSTED_USER" ]; then
deliver_opts="$deliver_opts -d USER"
fi
fi
###############################################################################
# Procedures
###############################################################################
Usage ()
{
echo "
NAME
$program - retrain/deliver a false positive from the quarantine
USAGE
$program [-h] [-u <username>] [-d <delivery_user>]
DESCRITION
$program is used to re-train and deliver false positives from
the DSPAM quarantine. Since user authentication to the DSPAM
WebUI is required, extra care can be taken to assure the email
is successfully delivered to the end user.
OPTIONS
-h: Help.
-u: Specify a user. If not provided, the value of \$EXTENSION
is used.
-d: Specify a user for use when direct delivery is required. This
is only needed if the user for direct delivery is different
than the user for delivery via DSPAM.
EXAMPLES
% $program -u joebob
"
exit 0
}
## Routine to log a message via logger.
Log ()
{
if [ $# -gt 1 ]; then p=$1; shift;
else p=mail.notice; fi
logger -p $p "${program}[$$]: $@"
}
## Print a message to STDERR.
Warn () { echo "${program}: $@" >&2; }
## Print a message to STDERR and pass it to logger.
WarnLog () { Warn "$@"; Log mail.err "$@"; }
## Call WarnLog and exit:
Error () { WarnLog "$@"; exit 1; }
## Run the specified DSPAM command.
Dspam ()
{
my_command=$1 ## The command to run
my_tmpfile=$2 ## The file to read; may be empty (read STDIN)
## Run the command, saving its STDOUT/STDERR and its exit status:
my_out="`sed '1{/^From /d;}' $my_tmpfile | $my_command 2>&1`"; my_result=$?
## We'll assume trouble if DSPAM outputs something, or exits non-zero.
if [ \( $my_result -ne 0 \) -o \( -n "$my_out" \) ]; then
WarnLog "Command \"$my_command\" FAILED:"
[ $my_result -eq 0 ] || WarnLog "Command exit failure code: $my_result"
[ -z "$my_out" ] || WarnLog "Command output: $my_out"
return 1
fi
## If DSPAM exits 0 and does not say anything, we'll assume all is OK.
return 0
}
###############################################################################
# End of procedures
###############################################################################
while [ $# -gt 0 ]; do
case $1 in
-u) shift; user=$1;;
-u*) user=`echo $1 | sed 's/^-u\(.*\)$/\1/'`;;
-h) Usage; exit 0;;
-d) shift; deliver_to=$1;;
-d*) deliver_to=`echo $1 | sed 's/^-d\(.*\)$/\1/'`;;
*) Error "Unknown option \"$1\"";;
esac; [ $# -gt 0 ] && shift
done
[ -z "$user" ] && user=$EXTENSION
[ -z "$user" ] && Error "Bad configuration: failed to determine user!"
[ -z "$deliver_to" ] && deliver_to=$user
## Now that we've figured out the user, substitute it in here:
train_opts=`echo $train_opts | sed "s/USER/$user/g"`
deliver_opts=`echo $deliver_opts | sed "s/USER/$deliver_to/g"`
## We want to copy the message (STDIN) so that in case DSPAM fails, we
## can try another way. And we can leave the message behind if worse
## comes to worst.
tmpfile="$dspam_tmp_dir/$user.${program}.$$"
out=`touch $tmpfile 2>&1`; result=$?
if [ $result -ne 0 ]; then
WarnLog "Failure creating tmpfile: $out"
WarnLog "Attempting quarantine delivery/retrain for user $user without a
tmpfile."
tmpfile=""
else
cat - > $tmpfile; result=$?
if [ $result -ne 0 ]; then
WarnLog "Failure writing tmpfile \"$tmpfile\"!"
WarnLog "Not ok: delivery of false positive failed for user $user!"
exit 3 ## There's nothing we can do now!
fi
fi
## Try to retrain/deliver via DSPAM:
if [ ! -x $dspam ]; then
WarnLog "Bad configuration: dspam command \"$dspam\" not found!"
else
Log "Invoking dspam for FP re-classification for user $user."
Log "$dspam $train_opts"
Dspam "$dspam $train_opts" $tmpfile; result=$?
if [ $result -eq 0 ]; then
Log "Ok: re-classification and delivery of message from quarantine
succeeded for $user."
[ -n "$tmpfile" ] && rm $tmpfile
exit 0
elif [ -z "$tmpfile" ]; then
WarnLog "Not ok: delivery of false positive failed for user $user!"
exit 4 ## Nothing we can do now - we already read STDIN!
fi
fi
## Attempt direct delivery without DSPAM:
if [ ! -x $deliver ]; then
WarnLog "Bad configuration: deliver command \"$deliver\" not found!"
[ -n "$tmpfile" ] && WarnLog "Message saved as $tmpfile; it has NOT been
delivered!!!"
exit 5
fi
Log "Attempting direct delivery via $deliver!"
Log "$deliver $deliver_opts"
## We trust deliver's return value a little more than dspam's, but we can't
## be certain if deliver exits successfully but outputs something.
out="`sed '1{/^From /d;}' $my_tmpfile | $deliver $deliver_opts 2>&1`"; result=$?
if [ $result -eq 0 ]; then
if [ -z "$out" ]; then
Log "Ok: direct delivery of message from quarantine for $deliver_to
succeeded."
[ -n "$tmpfile" ] && rm $tmpfile
else
WarnLog "Not sure if direct delivery of message from quarantine for
$deliver_to succeeded."
WarnLog "Delivery command exited successfully, but output the following:
$out"
[ -n "$tmpfile" ] && WarnLog "Message saved as $tmpfile just in case."
fi
exit 0
else
WarnLog "Direct delivery of false positive failed for user ${deliver_to}:
$out"
[ -n "$tmpfile" ] && WarnLog "Message saved as $tmpfile; it has NOT been
delivered!!!"
exit 5
fi
diff -Npru dspam-3.10.2-2.orig/src/error.c dspam-3.10.2-2/src/error.c
--- dspam-3.10.2-2.orig/src/error.c 2012-04-11 13:48:33.000000000 -0500
+++ dspam-3.10.2-2/src/error.c 2012-12-12 18:32:47.000000000 -0600
@@ -65,12 +65,12 @@ pthread_mutex_t __syslog_lock;
#endif
#ifndef _WIN32
+#define LOG_STDERR
void
LOG(int priority, const char *err, ... )
{
-#if defined(USE_SYSLOG) || defined(LOGFILE)
+#if defined(USE_SYSLOG) || defined(LOGFILE) || defined(LOG_STDERR)
va_list ap;
- va_start (ap, err);
#endif
#ifdef LOGFILE
char date[128];
@@ -85,13 +85,20 @@ LOG(int priority, const char *err, ... )
#ifdef USE_SYSLOG
openlog ("dspam", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_MAIL);
+ va_start (ap, err);
vsyslog (priority, err, ap);
closelog ();
+ va_end (ap); /* sandmant */
#endif
-#ifdef LOGFILE
+#if defined(LOGFILE) || defined(LOG_STDERR)
char err_text[256];
+ va_start (ap, err);
vsnprintf(err_text, sizeof(err_text), err, ap);
+ va_end (ap);
+#endif
+
+#ifdef LOGFILE
file = fopen(LOGFILE, "a");
if (file) {
fprintf(file, "%ld: [%s] %s\n", (long) getpid(), format_date_r(date),
err_text);
@@ -102,8 +109,8 @@ LOG(int priority, const char *err, ... )
}
#endif
-#if defined(USE_SYSLOG) || defined(LOGFILE)
- va_end (ap);
+#ifdef LOG_STDERR
+ fprintf(stderr, "%s\n", err_text);
#endif
#ifdef DAEMON
------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnnow-d2d
_______________________________________________
Dspam-devel mailing list
Dspam-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dspam-devel