#!/usr/local/bin/perl # MessageSaver -- AIM Message Queue Service # $Id: MessageSaver.pl,v 1.0 2002/01/28 12:00:00 scovetta Exp $ # Created by Michael Scovetta (michael.scovetta@gmail.com) ######################################################################### #use strict; use lib '.'; use Net::AIM; use Mail::POP3Client; ######################################################################### ## GLOBAL DEFINES SECTION ## ######################################################################### ## User Information my $AIM_USER = "XXXXXXXXX"; # AIM screen name my $AIM_PASS = "XXXXXXXXX"; # AIM password my $CHECK_EMAIL = 0; # Enable/Disable Email checking my $EMAIL_USER = "XXXXXXXXX"; # Email username my $EMAIL_PASS = "XXXXXXXXX"; # Email password my $EMAIL_HOST = "mail.yourisp.com"; # Email POP3 host ## Log files my $MSG_BACKUP_FILE = "savedb.txt"; # Place to save backups of messages my $TRANSACTION_FILE = "num.txt"; # Holds number of transactions my $LOG_FILE = "aim.log"; # Main log file my $MORON_FILE = "morons.log"; # List of morons ## Program data my $PROGRAM_TITLE = "MessageSaver"; # Text of program title my $PROGRAM_VERSION = "2.4"; # Text of version my $LAST_UPDATE = "4/30/02"; # Date of last update my $FOOTER = "
Help the cause. Donate a buck to the MessageSaver fund. Click here"; # Optional footer ## Options my $LOG_ALL_MESSAGES = 1; # Log all messages received? my $LOG_NUM_TRANSACTIONS = 1; # Log number of transactions? my $LOG_MORONS = 1; # Log morons my $CHECK_MAIL = 1200; # Min seconds to wait to check mail my @ADMIN_LIST = ("your-screen-name"); # List of administrators ######################################################################### ## YOU SHOULD NOT NEED TO EDIT BELOW THIS LINE ## ######################################################################### ## Debugging information my $DEBUG_LEVEL = 3; # Debug Mode: my $DBG_NO_MSG = 0; # 0=no messages, ever. my $DBG_ERRORS = 1; # 1=only errors my $DBG_ERRWRN = 2; # 2=+warnings+connection details my $DBG_ALL = 3; # 3=everything my $DBG_DETAIL = 4; # 4=detailed $AUTOFLUSH = 1; # Flush all files automatically my $MAX_BUDDIES = 160; # Maximum set by AOL ## Global variables my %morons; my %suspects = (); # People suspected of warning me my %stats = (); # statistics (messages received, etc) my %msgs = (); my %users_online = (); my $lastTime = 0; # Internal, last time email was checked ######################################################################### ######################################## # [ BEGIN ] # # Initial execution. Checks ARGV and # # files, if necessary. # ######################################## BEGIN { print "$PROGRAM_TITLE $PROGRAM_VERSION\n"; if ($ARGV[1] =~ /-\?|--\?|-h|\/\?|\/h/i) { print "Usage:\n"; print " perl $0 [username password]\n"; exit; } if (exists $ARGV[1] && exists $ARGV[2]) { $AIM_USER = $ARGV[0]; $AIM_PASS = $ARGV[1]; } } ######################################## # Create the objects # ######################################## BEGIN(); my $aim = new Net::AIM; $aim->debug(1) if $DEBUG_LEVEL >= $DBG_DETAIL; print "MSG: Creating connection to AIM server...\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $aim->newconn( Screenname => $AIM_USER, Password => $AIM_PASS, AutoReconnect => 1 ) or die "ERR: Can't connect to AIM server.\n"; ######################################### # Grab the total number of transactions # ######################################### if ($LOG_NUM_TRANSACTIONS == 1) { open (TRN_FILE, $TRANSACTION_FILE); $stats{msgs_received} = ; $stats{email_received} = unless eof(TRN_FILE); close (TRN_FILE); } if ($LOG_MORONS == 1 && open (MORON_LOG, "$MORON_FILE")) { while (my $line = ) { $line =~ s/\s*//g; $morons{$line} = 1; } close(MORON_LOG); } ######################################### # Install Handler Routines # ######################################### print "INFO: Installing handler routines...\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; my $conn = $aim->getconn(); $conn->set_handler('error', \&on_error); $conn->set_handler('im_in', \&on_im); $conn->set_handler('nick', \&on_nick); $conn->set_handler('eviled', \&on_eviled); $conn->set_handler('config', \&on_config); $conn->set_handler('update_buddy', \&on_update_buddy); ######################################### # Start the Service # ######################################### $aim->start; ######################################################################### # BEGIN SUBROUTINES # ######################################################################### ######################################### # [ on_im ] # # Called when an IM is received. # ######################################### sub on_im { my ($self, $evt, $from, $to) = @_; my $args = $evt->args(); my ($nick, $friend, $msg) = @$args; my $stripped = $msg; my $time = time; my $ADMIN = 0; print "DBG: on_im called, nick=$nick\n" if $DEBUG_LEVEL >= $DBG_DETAIL; foreach my $admin (@ADMIN_LIST) { $ADMIN = 1 if ($nick =~ /^$admin$/i); } # Increase the number of messages received $stats{msgs_received}++; # Record new total number of transactions if ($LOG_NUM_TRANSACTIONS == 1 && open(TRN_FILE, ">$TRANSACTION_FILE") ) { print TRN_FILE "$stats{msgs_received}\n"; print TRN_FILE "$stats{email_received}\n"; close TRN_FILE; } # Remove tags, extra whitespace, etc. from the message chomp($stripped); $stripped =~ s/<[^>]+>//g; $stripped =~ s/^\s+//g; # Output the message received print "RCV: $nick: $stripped\n" if $DEBUG_LEVEL >= $DBG_ALL; # Set the "last message received" variable $self->{_last_msg_dest} = $from; # Log the message to the log-file if necessary if ($LOG_ALL_MESSAGES == 1 && open(LOG_FILE, ">>$LOG_FILE")) { print LOG_FILE "<$from> $stripped\n"; close LOG_FILE; } # Check to see if a moron IMed us foreach my $mn (keys %morons) { $mn =~ s/\s*//g; $mn =~ tr/A-Z/a-z/; my $mnick = $nick; $mnick =~ s/\s*//g; $mnick =~ tr/A-Z/a-z/; if ($mn =~ /$mnick/) { # Ignore, return print "Moron($mnick) IMed me. Ignoring him.\n" if $DEBUG_LEVEL >= $DBG_ALL; return; } } ################################################################# # # # MSG ::= [TELL_CMD|CLEAR_CMD|BLOCK_CMD|UNBLOCK_CMD|LIST_CMD| # # SAVE_CMD|LOAD_CMD|EMAIL_CMD|BAD_CMD] # # TELL_CMD ::= tell SN MSG # # CLEAR_CMD ::= clear [SN|all] # # BLOCK_CMD ::= block SN # # UNBLOCK_CMD ::= unblock SN # # LIST_CMD ::= list buddies # # SAVE_CMD ::= save # # LOAD_CMD ::= load # # EMAIL_CMD ::= email # # EVIL_CMD ::= evil SN # # EVILANON_CMD::= evilanon SN # # DEBUG_CMD ::= debug # # TELLOBO_CMD ::= tellobo "from" "to" msg # # BAD_CMD ::= {anything else} # # # ################################################################# # TELL_CMD if ( ($stripped =~ /^tell \"([^\"]*)\" (.*)$/i) || ($stripped =~ /^tell ([^\s]*) (.*)$/i) ) { $buddy = $1; $message = $2; $buddy =~ tr/A-Z/a-z/; # convert to lowercase # Protect against empty message if (length($message) == 0) { $self->send_im($nick, "You must type a message also."); return; } # Protect against foul language if ($message =~ /fuck|bitch|shit|ass|gay|dick/) { $self->send_im($nick, "Sorry, foul language is not permitted. Please rephrase your message."); return; } # Protect against people typing "tell screenname message" if (( $nick =~ /^\s*(screenname|messagesaver)\s*$/i ) || ( $message =~ /^\s*(message|help|help me)\s*$/i )) { $self->send_im($nick, "No, don't type \"screenname\" or \"messagesaver\", type the screenname of the buddy you want to send the message to."); return; } if (&getMessageCount() > $MAX_BUDDIES) { print "WRN: $MAX_BUDDIES buddies reached! Denying message from $nick\n" if $DEBUG_LEVEL >= $DEBUG_ERRWRN; $self->send_im($nick, "Sorry, the maximum number of buddies ($MAX_BUDDIES) has been reached. Please try again later."); } else { # Add the message to the buddy's queue $msgs{$buddy} .= "
$nick wanted to tell you: $message but you weren't online at the time.$FOOTER"; } # Add the buddy to the buddy list addBuddy($buddy); # Report back to the user $self->send_im($nick, "Scovetta.Com MessageSaver

$buddy will be given the message
$message
next time they come online.

Served: ".$stats{msgs_received}." messages"); } # CLEAR_CMD elsif ($ADMIN == 1 && $stripped =~ /^clear (.*)$/i) { my $sn = $1; if ($sn =~ /all/i) { foreach $sn (keys %msgs) { delete $msgs{$sn}; $self->remove_buddy(0,'Buddies',$sn); } $self->send_config(); } else { delete $msgs{$sn}; $self->remove_buddy(0,'Buddies',$sn); $self->send_config(); } } # BLOCK_CMD elsif ($ADMIN == 1 && $stripped =~ /^block (.*)$/i) { my $blockedBuddy = $1; $morons{$blockedBuddy}++; my $moronList = ""; foreach $moron (sort keys %morons) { $moronList .= "$moron(".$morons{$moron}."), "; } # Remove trailing comma if ($moronList =~ /, $/) { chop($moronList); chop($moronList); } $self->add_deny(1,'Buddies',$blockedBuddy); # Output the result $self->send_im($nick, "Added $blockedBuddy to the block list.
Block list: $moronList"); # Save to the moron file if ($LOG_MORONS && open (MORON_LOG, ">>$MORON_FILE")) { print MORON_LOG "$blockedBuddy\n"; close(MORON_LOG); } } # UNBLOCK_CMD elsif ($ADMIN == 1 && $stripped =~ /^unblock (.*)$/i) { my $blockedBuddy = $1; my $moronList = ""; delete $moron{$blockedBuddy}; foreach $moron (sort keys %morons) { $moronList .= "$moron(".$morons{$moron}."), "; } $self->remove_buddy(0,'Buddies',$blockedBuddy); $self->send_config(); # Remove trailing comma if ($moronList =~ /, $/) { chop($moronList); chop($moronList); } # Output the result $self->send_im($nick, "Removed $blockedBuddy from the block list.
Block list: $moronList"); } # LIST_CMD elsif ($ADMIN == 1 && $stripped =~ /^list buddies\s*$/i) { my $buddy_list = "Buddy list contains: ".&getMessageCount()." buddies:
"; my %no_rep_list = (); foreach $buddy (keys %msgs) { $no_rep_list{$buddy} = 1; } foreach $buddy (keys %no_rep_list) { $buddy_list .= "$buddy, "; } # remove the extra ", " at the end, if necessary if ($buddy_list =~ /, $/) { chop($buddy_list); chop($buddy_list); } $self->send_im($nick, $buddy_list); print "INFO: LIST_CMD executed by $nick at $time\n" if $DEBUG_LEVEL >= $DBG_ALL; } # SAVE_CMD elsif ($ADMIN == 1 && $stripped =~ /^save\s*$/i) { if (open(SAVE_FILE, ">$MSG_BACKUP_FILE")) { foreach $buddy (keys %msgs) { $msg = $msgs{$buddy}; $msg =~ s/\"/'/; # convert double to single quotes print SAVE_FILE "\"$buddy\",\"".$msg."\"\n"; } print "INFO: Messages backed up.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->send_im($nick, "Messages backed up."); close SAVE_FILE; } else { print "ERR: Cannot save buddies" if $DEBUG_LEVEL >= $DBG_ERRORS; $self->send_im($nick, "ERROR: Cannot save buddy list."); } } # LOAD_CMD elsif ($ADMIN == 1 && $stripped =~ /^load$/i) { # Number of messages retrieved. Should also equal number of buddies. my $msgCount = 0; # Clear buddies first foreach my $grp (keys %{$self->{_config}}) { while ( my ($sn, $type) = each %{$self->{_config}->{$grp}}) { $self->remove_buddy(0,$grp,$sn); } } $self->send_config(); # Clear message queue foreach my $buddy (keys %msgs) { delete $msgs{$buddy}; } print "INFO: Buddy list and message queue cleared...\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; if (open (LOAD_FILE, "$MSG_BACKUP_FILE")) { while ($line = ) { $line =~ /^\"([^\"]*)\",\"([^\"]*)\"$/; $buddy = $1; $msg = $2; $msgs{$buddy} = $msg; $self->add_buddy(0,'Buddies',$buddy); #addBuddy($buddy); $msgCount++; } $aim->send_config(); print "INFO: Messages restored.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->send_im($nick, "Messages restored. ($msgCount messages)"); close(LOAD_FILE); } else { print "ERR: Cannot load buddies" if $DEBUG_LEVEL >= $DBG_ERRORS; $self->send_im($nick, "ERROR: Cannot load buddy list."); } } elsif ($ADMIN == 1 && $stripped =~ /^reset$/i) { # Clear buddies first foreach my $grp (keys %{$self->{_config}}) { while ( my ($sn, $type) = each %{$self->{_config}->{$grp}}) { $self->remove_buddy(0,'Buddies',$sn); $self->send_config(); } } $self->send_config(); # Remake buddy list foreach my $buddy (keys %msgs) { $self->add_buddy(1,'Buddies',$buddy); } $self->send_config(); print "INFO: Buddy list reset...\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; } # EMAIL_CMD elsif ($ADMIN == 1 && $stripped =~ /^email$/i) { &emailHandler(); } # EVIL_CMD: Warn user elsif ($ADMIN == 1 && $stripped =~ /^evil (.*)$/i) { my $buddy = $1; print "WRN: Eviling $buddy by command." if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->evil($self->normalize($buddy)); } # EVIL_ANON_CMD: Warn user anonymously elsif ($ADMIN == 1 && $stripped =~ /^evilanon (.*)$/i) { my $buddy = $1; print "WRN: Eviling $buddy by command." if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->evil($self->normalize($buddy), 1); } # DEBUG_CMD elsif ($ADMIN == 1 && $stripped =~ /^debug$/i) { my $configstr = ""; print "Messages:\n"; foreach $buddy (keys %msgs) { print "$buddy: $msgs{$buddy}\n"; } print "Config:\n"; $configstr = "Mode: ".$self->{_config}->{mode}."\n"; foreach my $group ( keys %{ $self->{_config} } ) { next if $group eq 'mode'; $configstr .= "g $group\n"; while (my ($sn, $type) = each %{ $self->{_config}->{$group} } ) { $configstr .= " $type $sn\n" unless $sn eq 'unknown'; } } print $configstr; } # TELLOBO_CMD : tell on behalf of... elsif ($stripped =~ /^tellobo \"([^\"]+)\" \"([^\"]+)\" (.*)$/) { my $fromBuddy = $1; my $toBuddy = $2; my $message = $3; $fromBuddy =~ tr/A-Z/a-z/; # convert to lowercase $toBuddy =~ tr/A-Z/a-z/; # Protect against empty message return if length($message) == 0; # Protect against foul language return if $message =~ /fuck|bitch|shit|ass|gay|dick/; # Protect against people typing "tell screenname message" return if $toBuddy =~ /^\s*(screenname|messagesaver)\s*$/i; $msgs{$toBuddy} .= "
$fromBuddy wanted to tell you: $message but you weren't online at the time.$FOOTER"; # Add the buddy to the buddy list addBuddy($toBuddy); } # BAD_CMD else { $self->send_im($nick, "Usage:
tell screenname message
This will tell screenname the message when they come online. If the person has a screenname with spaces in it, you can either ignore the spaces or use \"quotes\" around the name (tell \"Philly Cheese\" yo dude!). You can also use the web interface (www.scovetta.com/AIMAccessory)."); } } ######################################### # [ on_nick ] # # Called # ######################################### sub on_nick { my ($self, $evt, $from, $to) = @_; my $args = $evt->args(); my $nick = $args->[0]; print "DBG: on_nick called, nick=$nick\n" if $DEBUG_LEVEL >= $DBG_DETAIL; } ######################################### # [ on_update_buddy ] # # Called when a buddy signs on or off # ######################################### sub on_update_buddy { my ($self, $evt, $from, $to) = @_; my ($nick) = $from; my ($buddy, $online, $evil, $signon_time, $idle_amount, $user_class) = @{$evt->args()}; print "DBG: Update Buddy: $buddy\n" if $DEBUG_LEVEL >= $DBG_ALL; # If the user signs online and has a message waiting... # Took out dependency on !exists $users_online{buddy}, 1/28/02 if ($online eq 'T') { $users_online{$buddy} = $signon_time; print "MSG: $buddy has signed online at ".scalar localtime($signon_time)."\n" if $DEBUG_LEVEL >= $DBG_ALL; $buddy =~ tr/A-Z/a-z/; # Check to see if they have a message in the queue if (exists $msgs{$buddy}) { my $msg = $msgs{$buddy}; $msg = substr($msg, 0, 1023) if length($msg) > 1023; print "Sending \"$msg\" to $buddy\n" if $DEBUG_LEVEL >= $DBG_ALL; $self->send_im($buddy, $msg); delete $msgs{$buddy}; $self->remove_buddy(0,'Buddies',$buddy); $self->send_config(); delete $users_online{$buddy}; } else { # They shouldn't be in the buddy list delete $users_online{$buddy}; $self->remove_buddy(1,'Buddies',$buddy); # $self->send_config(); } } # If the user signs offline, then remove him from $users_online, announce elsif ($online eq 'F') { delete $users_online{$buddy}; $self->remove_buddy(0,'Buddies',$buddy); $self->send_config(); print "MSG: $buddy has signed off at ".scalar localtime($signon_time)."\n" if $DEBUG_LEVEL >= $DBG_ALL; } } ######################################### # [ on_config ] # # Called upon startup. # ######################################### sub on_config { my ($self, $evt, $from, $to) = @_; my $str = shift @{$evt->args()}; print "DBG: on_config called, str=$str\n";# if $DEBUG_LEVEL >= $DBG_DETAIL; $self->set_config_str($str, 1); $self->set_info("Scovetta.Com MessageSaver

Usage:
tell screenname message
Example:
tell scovetta4 hi there!

I will tell the person the message next time they come online. For more information, goto: MessageSaver Website. Also, you may send messages from the web to users!


Banned Users: tumblebug595. Feel free to harass these people.


Questions? Comments? Email me \@ mike\@scovetta.com
Last updated:$LAST_UPDATE
Game Central:3--The definitive gaming resource. Reviews. Strategies. Music. And much more.
"); # Deny Some Mode $self->{_config}->{mode} = 4; # Clear buddy list foreach my $grp (keys %{$self->{_config}}) { while ( my ($sn, $type) = each %{$self->{_config}->{$grp}}) { $self->remove_buddy(0,'Buddies',$sn); } } print "INFO: Buddy list cleared...\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; # Deny list # foreach my $sn (keys %morons) { # $self->add_deny(1,'Buddies',$sn); # } $self->send_config(); } ######################################### # [ on_error ] # # Called when there's an AIM error. # ######################################### sub on_error { my ($self, $evt) = @_; my ($error, @stuff) = @{$evt->args()}; my $errstr = $evt->trans($error); $errstr =~ s/\$(\d+)/$stuff[$1]/ge; print "DBG: on_error called, errstr=$errstr\n" if $DEBUG_LEVEL >= $DEBUG_ERR; } ######################################### # [ on_eviled ] # # Called when we get warned. # ######################################### sub on_eviled { my ($self, $evt, $from, $to) = @_; my ($level, $culprit) = @{$evt->args}; $culprit = 'An anonymous user' if ($culprit =~ /^\s*$/); print "WRN: $culprit slapped us! Our evil level is now $level\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; # Log the message to the log-file if necessary if ($LOG_ALL_MESSAGES == 1 && open(LOG_FILE, ">>$LOG_FILE")) { print LOG_FILE "<$from> $stripped\n"; close LOG_FILE; } if ($culprit !~ /^\s*$/) { $morons{$self->normalize($culprit)}++; my $nick = $self->normalize($culprit); if ($LOG_MORONS == 1 && open(MORON_LOG, ">>$MORON_FILE")) { print MORON_LOG "$culprit\n" unless $culprit =~ /An anonymous user/; close MORON_LOG; } # Non-agression # $self->add_deny(1,'Buddies',$nick); return; if ( exists $morons{$nick}) { $self->evil($nick); sleep(1); $self->evil($nick); sleep(1); $self->evil($nick); print "WRN: I warned $culprit and am blocking him.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->add_deny(1,'Buddies',$nick); } else { $morons{$culprit}++; $self->evil($culprit); $self->evil($culprit); print "WRN: I warned $culprit and am blocking him.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->add_deny(1,'Buddies',$nick); } } # Look for suspicious people else { my $lmd = $self->{_last_msg_dest}; if (++$suspects{$lmd} > 3) { $morons{$lmd}++; $self->evil($lmd); if ($LOG_MORONS == 1 && open(MORON_LOG, ">>$MORON_FILE")) { print MORON_LOG "$self->{_last_msg_dest}\n"; close MORON_LOG; } print "WRN: I warned $lmd and am blocking him on suspicion.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; $self->add_deny(1,'Buddies',$lmd); } } $self->send_config(); } ######################################### # [ addBuddy ] # # Adds a buddy to the buddy list. # ######################################### sub addBuddy { my $newBuddy = shift; $aim->remove_buddy(0,'Buddies', $newBuddy); $aim->send_config(); $aim->add_buddy(1,'Buddies', $newBuddy); $aim->send_config(); } ######################################### # [ getMessageCount ] # # Tells how many buddies are in the # # queue to have messages delivered. # ######################################### sub getMessageCount { my $buddyCount = 0; foreach (keys %msgs) { $buddyCount++; } return $buddyCount; } ######################################### # [ emailHandler ] # # Handles checking email and adding # # messages to the queue. # ######################################### sub emailHandler { return unless $CHECK_EMAIL; my ($self, $evt) = @_; my ($fromBuddy, $toBuddy, $msg, $msgDate, $IP, @emailBody); my $numEmailReceived = 0; $lastTime = time - $CHECK_MAIL + 1 unless $lastTime > 0; print "INFO: Email Handler..." if $DEBUG_LEVEL >= $DBG_ERRWRN; if (time-$lastTime > $CHECK_MAIL) { $lastTime = time; print "INFO: Checking email..." if $DEBUG_LEVEL >= $DBG_ERRWRN; $pop = new Mail::POP3Client( USER => $EMAIL_USER, PASSWORD => $EMAIL_PASS, HOST => $EMAIL_HOST, AUTH_MODE => "PASS" ); for ($i=1; $i <= $pop->Count(); $i++) { my @emailBody = $pop->Body($i); foreach my $line (@emailBody) { if ($line =~ /^FROM:\"([^\"]*)\"$/i) { $fromBuddy = $1; } elsif ($line =~ /^TO:\"([^\"]*)\"$/i) { $toBuddy = $1; } elsif ($line =~ /^MESSAGE:\"([^\"]*)\"$/i) { $msg = $1; } elsif ($line =~ /^DATE:\"([^\"]*)\"$/i) { $msgDate = $1; } elsif ($line =~ /^IP:\"([^\"]*)\"$/i) { $IP = $1; } } # Should we log the transaction? if ($LOG_ALL_MESSAGES == 1 && open(LOG_FILE, ">>$LOG_FILE")) { print LOG_FILE "EMAIL: FROM:$fromBuddy, TO:$toBuddy, DATE:$msgDate, IP:$IP, MSG:$msg\n"; close LOG_FILE; } # Add the data to the queue if ( defined($fromBuddy) && defined($toBuddy) && defined($msg) && length($fromBuddy) > 1 && length($toBuddy) > 1 && length($msg) > 1 ) { $msgs{$toBuddy} .= "
$fromBuddy wanted to tell you: $msg but you weren't online at the time.$FOOTER"; addBuddy($toBuddy); $numEmailReceived++; } # Remove the email $pop->Delete($i); } $pop->Close(); print "$numEmailReceived messages received.\n" if $DEBUG_LEVEL >= $DBG_ERRWRN; } }