Mail Alert
Email is the ultimate communication tool, right? It's fast, easy, and cheap. And best of all, there's no phone tag. At companies with "an email culture," checking for email messages becomes at least as important as checking your voicemail.
Checking your mail takes just a moment at the office, but what happens when you travel on vacation? As anyone who has battled with laptops, modems, and cramped hotel rooms can attest, checking your email while on vacation can quickly become a chore. Especially when you intend to only respond to critical messages.
Enter perl to the rescue. I wrote the following script to solve
the problem described above. mailalert.pl regularly scans your email inbox, searching for new messages from someone on a "buddy list." Whenever it finds such a message, it pages you. Of course, you must have an alphanumeric pager. And most every pager service includes a free email address corresponding to your pager. (Example: 1234567@skytel.com.)
mailalert.pl is smart: it doesn't send any repeat pages because it remembers every page it's sent. And mailalert.pl is safe: it doesn't affect your normal email, and all messages are left undisturbed on the mail server until you really want to check for mail.
mailalert.pl has other uses as well, and it need not be used with pagers at all. For example, if you have a personal email account which doesn't get much traffic, you can configure the script to send you email at work whenever you have a new message at home.
Feel free to use, copy, or modify this script. I've used it since December 1998 without incident. I use it on Linux, but can't vouch for it on any "lesser" operating
systems. Please send bug reports, modifications, or feature requests to bob at lisbonne.com.
Note: Please make sure you understand the various security implications of running mailalert.pl. While in general it is no less secure than any standard email client, it does know your password and have access to your email server-- things which always attract Bad Guys.
mailalert.pl
#!/usr/bin/perl -w
# Copyright (C) 1999, Bob Lisbonne
#
# 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.
#------------------------------------------------------------------------------------
#
# ma.pl (Mail Alert)
#
# Periodically scans an email inbox using POP3. If it finds mail from
# someone on a "buddy list," an email notification to a different email address
# is sent. Mail in inbox is left untouched on the server. Can be used
# to generate pager notifications when used with an email->pager gateway.
#
# Usage: ma.pl [-m]
# -m is mark-only mode, in which mailbox is scanned but no notifications sent.
#
# by Bob Lisbonne, 1999
#
# revision history:
# 7/19/99 v1.0
#
#------------------------------------------------------------------------------------
use Net::POP3;
# if you don't have this module, you can get it at:
# http://www.perl.com/CPAN-local/modules/by-module/Net/
# look for the libnet file
use Mail::Mailer;
# if you don't have this module, you can get it at:
# http://www.perl.com/CPAN-local/modules/by-module/Mail/
# look for the MailTools file
use Digest::MD5 qw(md5_base64);
# if you don't have this module, you can get it at:
# http://www.perl.com/CPAN-local//modules/by-module/MD5/
# look for the Digest-MD5 file
use Getopt::Std;
use vars qw($opt_m);
$popserver = "mail.isp.com";
$user = "neil";
$pw = "onesmallstepforman"; #your email password.
# Sorry for the cleartext, but POP authentication is usually also done cleartext!
$pager = '1234567@skytel.com'; #any valid smtp email address. usually set to your pager's email address.
$logfile = "ma.log"; #keeps a log file of all activity
$dbmfile = "ma.dbm"; #maintains database of previous notifications in this dbm file
#reminder that if I add myself to the buddy list, I may have an infinite loop problem!
@buddylist = qw(jack lyndon richard gerald jimmy ronald george bill);
#use push() for long buddy lists to avoid weird bug when really long list spans multiple lines
push @buddylist, qw(mom dad);
#just add \w* as a buddy if you want all senders to be acted upon
#@buddylist = qw(\w*);
open(LOGFILE,">>".$logfile)
or die "Can't open logfile: $!\n";
print LOGFILE "######## RUN STARTED AT ",scalar(localtime);
getopts('m');
if ($opt_m) {
print LOGFILE "\t*** Mark-only mode ***\n";
$markonly = 1;
} else {
$markonly = 0;
print LOGFILE "\n";
}
dbmopen %NODUPS,$dbmfile,0666;
print LOGFILE "DB hash currently has ",scalar(keys %NODUPS)," entries.\n";
$pop = Net::POP3->new($popserver,Debug => 0)
or die "Can't open connection to mail server: $!\n";
$count = $pop->login($user,$pw)
or die "Can't authenticate: $!\n";
print LOGFILE "There are $count messages in the inbox.\n";
#note that msg #'s start at 1 and not zero
for ($i=1;$i<=$count;$i++) {
$date = "";
$from = "";
$subject = "";
#reminder: headerptr is a reference to an array of strings comprising the mail header
$headerptr = $pop->top($i,0);
#scan message and find key fields in header
foreach (@$headerptr) {
if (/^Date: */) {
$date = $_;
}
if (/^From: */) {
$from = $_;
}
if (/^Subject: */) {
$subject = $_;
}
}
#determine whether message is from someone on a "buddy list"
foreach $buddy (@buddylist) {
if ($from =~ /$buddy/i) {
#this message is from a buddy
#now check whether we've already sent a notification
$dupfound = 0;
$digest = md5_base64(@$headerptr);
foreach $u (%NODUPS) {
if ($u eq $digest) {
$dupfound = 1;
}
}
if ($dupfound) {
#then we've already sent a notification
print LOGFILE "Skip $digest\n";
} else {
#we need to send a notification now, so...
#first log it and update NODUPS
$NODUPS{$digest} = scalar(localtime);
print LOGFILE "Adding nodups{} MD5 ",$digest," at ",$NODUPS{$digest},"\n";
if (not $markonly) {
#now really send the notification
print LOGFILE "Notification going out for MD5: $digest\n", $date, $from, $subject;
print "Notififcation sent. MD5 $digest:\n", $date, $from, $subject,"\n";
$mailer = Mail::Mailer->new("smtp",$popserver); #assumes that $popserver is also your smtp server
$mailer->open({ From => "MailAlert",
To => $pager,
Subject => "",
}) or die "Can't send notification message: $!\n";
print $mailer $from, $subject;
$mailer->close();
}
}
}
}
}
$pop->quit();
dbmclose %NODUPS;
print LOGFILE "######## RUN ENDED AT ",scalar(localtime),"\n";
close(LOGFILE);