#!/usr/bin/perl # # mailloop.monitor - sends email to mailboxes that are expected to send # the mail back to the sender. Probably not hard to do with procmail, etc. # I've only used a reflector agent for Lotus Notes. Instead of "hosts" in # a hostgroup, use email addresses you want to send bounce tests to. The # code still refers to these as hosts. # # You can use as many addresses as you'd like, but you'll need to use a # unique from address for each hostgroup that calls this monitor, because # it eats all the mail this running copy of the monitor didn't send. # Otherwise, previously delayed mail might lay around forever. # # The monitor then polls a POP3 account for the mail it sent. Don't use # that mailbox for anything else, the monitor will delete all your mail! # I'm not kidding, I didn't say "might", it *will*. # # This monitor assumes the local sendmail knows how to get the mail to # the the first relay in the loop you're testing. It also assumes that # the last host knows to deliver mail sent to the configured from # address so that it shows up in the POP server we poll. # # Takes 5 options: # -d Debug Mode. Not really compatible with normal mon scheduling, # because it doesn't log to syslog or anything, just print to STDOUT. # You'll have to call the monitor by hand to use this option. # Mostly helpful to debug your POP/SMTP setup. # # -f Set the from address, this option will also set the POP user to # all the bits before the '@'. So, don't do any wild aliasing... # # -p Set the POP password. Defaults to null password # # -s Set the POP server. Defaults to localhost. # # -t Standard monitor timeout option. # # # $Id: mailloop.monitor,v 1.3 2000/02/11 23:25:23 bill Exp $ # # Copyright 2000 Shared Medical Systems, Inc. # Author: Bill Smargiassi # Email: william.smargiassi@smed.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use Mail::Sendmail; use POSIX; use Mail::POP3Client; sub dbgprint { my ($str) = @_; print $str, "\n" if $DEBUG; } # "check sum of tests left", not to be confused with a checksum :) sub checksum { my $sum; $sum = 0; foreach $id (keys %check) { $sum += $check{$id}; } dbgprint "sum is " . $sum; return $sum; } sub diefailures { my $hosts, @parts; $hosts = ''; foreach $id (keys %check) { if ($check{$id}) { @parts = split(/ /, $id); $hosts .= $parts[0]; } } dbgprint "hosts is " . $hosts; print $hosts, "\n"; exit 1; } getopts("df:p:s:t:"); $Timeout = $opt_t || 900; $hostname = `hostname`; $fromaddr = "mailloop\@$hostname"; # popname is inferred from fromaddr if set with -f opt $popname = 'mailloop'; if ($opt_f) { $fromaddr = $opt_f; @parts = split(/\@/, $opt_f); $popname = $parts[0]; } $poppass = $opt_p || 'mailloop'; $popserv = $opt_s || 'localhost'; $DEBUG = $opt_d || 0; dbgprint "Timeout = $Timeout"; $failures = ""; foreach $reflect (@ARGV) { # Send some mail to the reflector address $id = "$reflect " . strftime("%Y%m%d%H%M%S", localtime(time)); dbgprint "Sending mail: $id"; %mail = ( To => $reflect, From => $fromaddr, Message => "REFL: $id" ); # remember the id for later POP retrieval $check{$id} = 1; if (sendmail %mail) { } else { $failures .= "Error sending mail: $Mail::Sendmail::error " } } dbgprint "Done sending mail"; if ($failures) {die $failures} local $SIG{TERM} = \&diefailures; $starttime = time; # look for replies $pop = new Mail::POP3Client( USER => $popname, PASSWORD => $poppass, HOST => $popserv, DEBUG => $DEBUG); while(checksum()) { if ((time - $starttime) > $Timeout) { diefailures(); } sleep(30); dbgprint "Logging in..."; $pop->Connect; dbgprint "There are " . $pop->Count . " messages"; for ($i = 1; $i <= $pop->Count; $i++) { $id = ""; @lines = split(/\n/, $pop->Body($i)); foreach $line (@lines) { dbgprint $line; if ($line =~ m/REFL: (\S+ \d+)/g) { $id = $1; dbgprint "Found: $id"; } } $check{$id} = 0; $pop->Delete($i); } dbgprint "Logging out"; $pop->Close; } exit 0;