On Sun, Nov 01, 2009 at 07:57:34AM -0500, Nathan Gibbs wrote:
* Ed Ravin wrote:
We use a similar monitor for SpamAssassin that uses the corresponding
fake spam signature to test whether spamd is checking messages - if
anyone's interested, let me know.
-- Ed
Sure, I could use that.
See attached.
#!/usr/bin/perl -w
#
# test spamd by sending a test spam string. Will alarm if socket doesn
# not answer or if spamd fails to recognize the test string as spam.
# copyright(2004) by Ed Ravin era...@panix.com. License is GPL
# this software is made available courtesy of PANIX, http://www.panix.com
# based on code snatched from nntp.monitor by Jim Trocki and
# http.monitor by Jon Meek.
#
#
my $usage=
spamd.monitor [-d] [-p port] [-t timeout] host [host...]\n;
# -d for debug
#
use strict;
use Getopt::Std;
use English;
use vars qw($opt_p $opt_t $opt_d);
getopts (m:p:t:d) || die $usage;
my $PORT = $opt_p || 783;
my $TIMEOUT = $opt_t || 30;
my $DEBUG = $opt_d || ;
my @failures = ();
my @details= ();
# WARNING - this spam test string is broken up to avoid getting trapped by
# spam filters if the program is sent via mail.
my $GTUBE=
XJS*C4JDBQADN1.NSBN3*2IDNEN* .
GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X;
foreach my $host (@ARGV) {
if (! spamdTEST($host, $PORT)) {
push (@failures, $host);
}
}
if (@failures == 0) {
exit 0;
}
print join ( , sort @failures), \n;
print sort @details if (scalar @details) 0;
exit 1;
sub spamdTEST {
use Socket;
use Sys::Hostname;
my($Server, $Port) = @_;
my($ServerOK, $TheContent);
$ServerOK = 0;
$TheContent = '';
###
my $TransactionOK= eval {
local $SIG{ALRM} = sub { die Timeout Alarm };
alarm $TIMEOUT;
my $result = OpenSocket($Server, $Port); # Open a connection to the
server
if (!$result) { # Failure to open the socket
print $Server: Unable to open socket\n if $DEBUG;
return '';
}
my $now= time;
my $testmessage=Subject: Mon test of spamd at $now\r\n\r\n$GTUBE;
my $testlength= length($testmessage) + 2;
# 52 45 50 4f 52 54 20 5350 41 4d 43 2f 31 2e 33REPORT SPAMC/1.3
# 0d 0a 55 73 65 72 3a 2072 6f 6f 74 0d 0a 43 6f..User: root..Co
# 6e 74 65 6e 74 2d 6c 656e 67 74 68 3a 20 31 31ntent-length: 11
# 31 0d 0a 0d 0a1
transact(REPORT SPAMC/1.3\r\nUser: netmon\r\nContent-length:
$testlength\r\n, '', $Server: failed sending REPORT request) || return 0;
# Expected reply to test message:
# 53 50 41 4d 44 2f 31 2e31 20 30 20 45 58 5f 4fSPAMD/1.1 0 EX_O
# 4b 0d 0a K..
transact($testmessage, '^SPAMD/.*\b0\b', $Server: no response (or
incorrect response) to test message) || return 0;
my $inputline=;
my @spamcresults= S;
if (grep /^1000\s+GTUBE\b/, @spamcresults)
{
push @details, $Server: spamd OK, found test spam\n if $DEBUG;
return 1;
}
else
{
push @details, $Server: spamd responded but didn't find test
spam\n;
map {push @details, $Server: $_ } @spamcresults;
return 0;
}
};
close(S);
alarm 0; # Cancel the alarm
if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) {
push(@details, $Server: timeout($TIMEOUT)\n);
return 0;
}
return 0 unless $TransactionOK;
$ServerOK = 1;
return $ServerOK;
}
sub OpenSocket {
#
# Make a Berkeley socket connection between this program and a TCP port
# on another (or this) host. Port can be a number or a named service
#
my($OtherHostname, $Port) = @_;
my($OurHostname, $sockaddr, $proto, $type, $len,
$ThisAddr, $that, $OtherHostAddr, $result);
$OurHostname = hostname;
$proto = getprotobyname('tcp');
$Port = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/;
$ThisAddr = gethostbyname($OurHostname);
$OtherHostAddr = gethostbyname($OtherHostname);
if (!defined $OtherHostAddr)
{
push (@details, $OtherHostname: cannot resolve hostname\n);
return undef
}
$that = sockaddr_in ($Port, $OtherHostAddr);
if (! ($result = socket(S, PF_INET, SOCK_STREAM, $proto)) ||
(! ($result = connect(S, $that))) )
{
push (@details, $OtherHostname: $!\n); return undef;
}
select(S); $| = 1; select(STDOUT); # set S to be un-buffered
return 1; # success
}
sub transact # string to send, pattern to expect, error message
{
my($sendstr, $rxpattern, $errormsg) = @_;
my($rxstr);
warn DEBUG: sending data: $sendstrCR LF\n if $DEBUG;
print S $sendstr . \r\n unless