MAPI and OLE-based Mail solutions are difficult to setup, and very error-prone during their life. It is a lot better to use SMTP-based mail, which works well in an Exchange environment.
use strict;
use Mail::Box::Manager;
use Mail::Transport::SMTP;
use POSIX qw(strftime); # Dont REALLY need this
use Date::Parse qw( str2time );
use Date::Manip;
my $MailboxManager = Mail::Box::Manager->new;
my $CurrentTime = time();
my @mrtginfo=(9999,9999,0,0);
my %OPT = qw(VERBOSE 0 DELETEALL 0 DELETEMINE 1 CHECKOPT 0 HELP 0
MAIL1 0 MAIL2 0 NAME1 0 NAME2 0
MAXMESSAGES 15
MAILBOX MY_DOMAIN/MY_USER_ID/MY_MAILBOX_NAME
MAILBOXPASSWORD MY_DOMAIN_PASSWORD
MAILBOXSERVER ExchServerName
SMTPSERVER smtp.myDomain.com
FROM MailMonitor@MyDomain.com
);
# DestX=WW.Test@RemoteDomain.com destY=Someone.else@OtherDomain.co
+m
for (@ARGV){
my $matchedOp=0;
foreach my $o (keys %OPT){
m/$o/i and $OPT{$o}= $matchedOp =1; # ON unless specified other
+wise
m/$o=(\S+)/i and $OPT{$o} = $1;
$OPT{$o}=~s/ / /g; # Substitute SPACES (For Passwords etc)
}
$matchedOp or $OPT{HELP}=1, warn "ERROR: Unknown option:'$_'\n";
}
$OPT{MAIL1} or warn "MAIL1=user\@addr.com not specified - not sending
+ any e-mail\n";
$OPT{NAME1} or ($OPT{NAME1}) = ($OPT{MAIL1}=~m/\@(\w+)\.?/);
$OPT{NAME2} or ($OPT{NAME2}) = ($OPT{MAIL2}=~m/\@(\w+)\.?/);
$OPT{VERBOSE} and print " Option: $_ \t= $OPT{$_}\n" for sort keys %O
+PT;
$OPT{HELP} and print "Program option: $_\n" for sort keys %OPT;
($OPT{CHECKOPT} or $OPT{HELP}) and exit 0; # Finished checking options
if ($OPT{MAIL1}){
$OPT{VERBOSE} and print "Sending Mail1 with stamp $CurrentTime\n";
SendMail( ['hostname'=> $OPT{SMTPSERVER}, ] # Ref to@smtpopts
,[## Ref to @sendopts
From => $OPT{FROM}
, To => $OPT{MAIL1}
, Subject=> "bounce 0 $OPT{NAME1} from Mail::Box \@$Curre
+ntTime\@"
##, Cc => [ Mail::Address->parse($groupalias) ]
]
);
}
if ($OPT{MAIL2}){
$OPT{VERBOSE} and print "Sending Mail2 with stamp $CurrentTime\n";
SendMail( ['hostname'=>$OPT{SMTPSERVER}, ] # Ref to@smtpopts
,[## Ref to @sendopts
From => $OPT{FROM}
, To => $OPT{MAIL2}
, Subject=> "bounce 1 $OPT{NAME2} from Mail::Box \@$Curre
+ntTime\@"
##, Cc => [ Mail::Address->parse($groupalias) ]
]
);
}
$OPT{VERBOSE} and print "Reading Mail..\n";
ReadMail($OPT{MAILBOX},
,$OPT{MAILBOXPASSWORD}
,$OPT{MAILBOXSERVER});
print $mrtginfo[$_] . "\n" for 0..3; # First 4 only
#############################################################
sub ReadMail{
my ($UserName, $Password, $Server) = @_;
#In order to specify a mailbox, the complete domain/username/mailbox s
+tring is required. Should the server see only a 2 item entry, (I.E.
+username/mailbox) then it will be interpreted as domain/username, not
+ as username/mailbox.
#Appending a mailbox entry to the username is also useful for accessin
+g a mailbox
# that is not the users ‘default’ mailbox, such as the mailbox of an
+other user to
# which the person has access too.
#. login corpdomain/johndoe/marysMailbox j0hnsPa$$word
# $UserDomain is optional. If null, Exch server domain is used.
# $MailboxName can be null if identical to $username (Normal case).
# If $MailboxName is specified, either the $UserDomain MUST be speci
+fied,
# or the $Username must be in UPN (e-mail address) form.
# To specify a particular mailbox, append the mailbox to the username
+string using
# a trailing ‘/’ and then the ‘Alias”
# . login corpdomain/johndoe/johnsMailbox j0hnsPa$$word
my $POP3InboxFolder = $MailboxManager->open(type => 'pop3' , folder
+=>'/'
,username => $UserName, password => $Password
,server_name => $Server , access => 'rw',
,fix_header_errors => 1, fixHeaderErrors=> 1)
or die "Cannot open POP inbox for '$UserName' on $Server\n";
my $msgCount=0;
my ($SentTimeStamp, $SecondsAgo);
foreach my $msg ($POP3InboxFolder->messages(- $OPT{MAXMESSAGES},-1))
+{ # Last 15
my $head = $msg->head;
#my $SentTimeStamp =$head->timestamp;
$OPT{VERBOSE} and print "#RCVD:" , $head->get('Received', 0) , "
+\n";
$OPT{VERBOSE} and print "#Subject=", $msg->subject ;
my $sender = $msg->sender;
$OPT{VERBOSE} and $sender and print qq(\t#Sender: ) ,$sender
+->format , qq(\n) ;
if ($msg->subject =~m/bounce (\d)\s($OPT{NAME1}|$OPT{NAME2})\s.+\
+@(\d+)/){
Parse_Message($msg, $1,$3)
}else{
# Parse BODY for send timestamp ...
my $found = 0;
foreach(@{$msg->body->lines}){
m/bounce (\d)\s($OPT{NAME1}|$OPT{NAME2})\s.+\@(\d+)/ and
Parse_Message($msg, $1,$3) , $found=1, last;
}
next if $found;
##my $mrtgIndex = ; ## Fix this ...
$SecondsAgo = $head->recvstamp - $head->timestamp ;
$OPT{VERBOSE} and print "*UNKNOWN MSG:It took $SecondsAgo sec
+onds in transit = ",
int $SecondsAgo / 3600,":", int $SecondsAgo /60 % 60,
":", $SecondsAgo % 60 , "\n";
##$mrtginfo[$mrtgIndex] = $SecondsAgo;
$OPT{VERBOSE} and print "@{$msg->body->lines}[0..10] \n";
$OPT{DELETEALL} and $msg->delete;
## next; # Skip the msg
}
#for ($head->names){
# print "#\t$_\t ", $head->get($_), ";\n" ;
#}
$OPT{VERBOSE} and print "-" x 50 . " $msgCount\n";
last if $msgCount++ > 18;
}
$POP3InboxFolder->close;
}
#############################################################
sub Parse_Message{
# It was sent by THIS program .. Process it
my ($msg , $mrtgIndex ,$SentTimeStamp) = @_;
my $head = $msg->head;
my $SecondsAgo;
$SecondsAgo = $CurrentTime - $SentTimeStamp;
$OPT{VERBOSE} and print "===This message is from myself! , sent $S
+econdsAgo seconds ago\n";
$OPT{VERBOSE} and print "It was sent ",
int $SecondsAgo / 3600,":", int $SecondsAgo /60 % 60,
":", $SecondsAgo % 60 , " seconds ago, at ",
POSIX::strftime(qq(%H:%M %d %b), localtime($SentTimeStamp)),
"\n";
if ($SecondsAgo > 30 * 60 * 60){ # older than 30 minutes - ignore
$mrtgIndex = $#mrtginfo + $mrtgIndex; #Store this junk at th
+e end
}
$SecondsAgo = ($head->recvstamp || $SentTimeStamp) - $SentTimeStam
+p;
$OPT{VERBOSE} and print "It took $SecondsAgo seconds in transit =
+ ",
int $SecondsAgo / 3600,":", int $SecondsAgo /60 % 60,
":", $SecondsAgo % 60 , "\n";
$mrtginfo[$mrtgIndex] = $SecondsAgo; # Save for MRTG
# This was MY message - I can zap it..
($OPT{DELETEMINE} or $OPT{DELETEALL}) and $msg->delete;
}
################################################################
sub SendMail{
my @smtpopts = @{shift() || die "SendMail:Specify transport + Server"
+};
my %sendopts = @{shift() || die "SendMail:Specify From, To(msg option
+s)"};
my $bodytext = shift || '';
my $body = Mail::Message::Body->new
( mime_type => 'text/plain'
, transfer_encoding => '8bit',
data => $bodytext
);
my $message = Mail::Message->buildFromBody ( $body , %sendopts );
my $mailer = Mail::Transport::SMTP->new(@smtpopts)
or warn "could not create Mail Transport (Mailer) for SMTP\n";
$mailer->send($message) or warn "could not send message \n";
}
#############################################################
Some more setup is required - local and remote e-mail accounts, and auto-responder on the remote e-mail.
This code feeds data into mrtg for tracking mail delivery time graphically.