#!/usr/bin/perl -w
use strict; 

#######################################################################
# mojo_bounce_handler.pl 
#
# A simple bounce handler for The Mojo Mail Mailing List Manager
#
# This script takes forwarded email messages and parses out ALL 
# the email addresses it finds. It can than save these addresses
# into a file, remove these addresses from a list and save the bounced
# message itself. 
#
# Since this script extracts ALL email addresses, it isn't encouraged 
# that this script be used for group lists. 
#
# Instructions on how to set up this script can be found in POD format
# at the end of this file.
#
#######################################################################


#######################################################################
# Begin Serviceable Area #
##########################

# $lib NEEDS to havve the correct path to your mojo directory
BEGIN{

my $lib = '/home/youraccount/publichtml/cgi-bin/mojo';


	  push(@INC, $lib);
	  push(@INC, "$lib/MOJO");
}

# skip these addresses for any removal
my @skip_addresses = qw(MAILER-DAEMON\@yourhost.com); 

# remove addresses as soon as they bounce, 
# If you don't set this, emails will not be removed automatically

my $Remove_Now = 0; 

# Give an absolute path to a file, if you'd like an appended log of
# the entire email messages

my $Bounced_Messages; 

# Give an absolute path to a file, if you'd like an ongoing list of 
# bounced email messages

my $Bounce_Email_Log;

########################
# End Serviceable Area #
#######################################################################


#######################################################################
# Bring in a few.. things
use MOJO::Config;
use MOJO::Guts; 
use MOJO::Log; 
use MOJO::Mail; 
use MOJO::List;
use Mail::Address;
use Fcntl qw(O_WRONLY O_TRUNC O_CREAT); 
#
#######################################################################

#######################################################################
# Do a few things to begin #
############################

#we'll split up the message, 
my ($message, $message_header, $message_body) = fetch_message(); 

#create a MOJO::Mail object 
my $mh = MOJO::Mail->new(); 

#get headers as name/value 
my %mail_headers = $mh->return_headers($message_header);
   %mail_headers = $mh->clean_headers(%mail_headers); 	   
	   
my $To; 
my $list_name; 
my $lh; 
my %list_info; 
my $have_mailing_list = 0; 

if($mail_headers{To}){ 
	# find what list we're working on, and open up the list database
	   $To  = (Mail::Address->parse($mail_headers{To}))[0];
	   $list_name = $To->user();
	   $list_name =~ s/^bounce-//; 
	   $lh = MOJO::List->new(-List=>$list_name); 
	   %list_info = open_database(-List => $list_name); 
	   $have_mailing_list = 1;
}
	   
#
#######################################################################

# find every email in it, 
my @possible_bouncing_emails = parse_out_emails($message);

# remove the bouncing emails
remove_bouncers(@possible_bouncing_emails)      if($Remove_Now == 1); 
save_message($message)                          if($Bounced_Messages); 
save_bouncing_emails(@possible_bouncing_emails) if($Bounce_Email_Log); 



sub fetch_message { 

	my $header; 
	my $body; 
	my $message; 
	
	{ 
		local $/ = ""; 
		$header = <STDIN>; 
		 undef $/; 
		$body = <STDIN>; 
	} 
	
	#patch it back together
	$message = "$header\n\n$body";
	
	
	return($message, $header, $body); 	
}


sub remove_bouncers { 
	my @emails = @_; 
	if($have_mailing_list){
		$lh->remove_from_list(-List => $list_name, -Email_List => [@emails]);
	}
}


sub parse_out_emails { 

	my $string = shift; 
	my %email_report;
	# lookup table for skipped addresses
	my %skip_addresses; 
	foreach (@skip_addresses){$skip_addresses{$_} = 1;}

	my @message_lines = split("\n|\r", $string); 
	my $num = 1;
	
	
	foreach my $string(@message_lines){
		my @word_batch = split(/\s+/, $string); 
   		push(@word_batch, $string); 
		foreach my $word(@word_batch){ 
            next if($word eq ""); 
            $word = strip($word); 
            $word =~ s/<//gi; 
            $word =~ s/>//gi;  
			my $email_check = check_for_valid_email($word); 	
			#skip if we have either the admin, or list owner email in our bounces
			if($email_check == 0){
				if($have_mailing_list){
					if($word ne  $list_info{mojo_email} and 
						$word ne $list_info{admin_email}){ 	
							if(!exists($skip_addresses{$word})){
							$email_report{$word}++;
						}
					}
				} 
			}
		}
		$num++; 
	} 
	return (keys %email_report); 
}

sub save_message {
	my $message = shift; 
	if($have_mailing_list == 1){ 
		$Bounced_Messages =~ s/\[list\]/$list_name/g;
	}else{ 
		$Bounced_Messages =~ s/UNKNOWN/$list_name/g;
	}
	
	
	open(MESSAGE_Log, ">>$Bounced_Messages") or 
			warn "$PROGRAM_NAME $VER Error, can't write to Bounce Messages Log at: '$Bounced_Messages', details: $!";
	print MESSAGE_Log $message;
	print MESSAGE_Log "\n";
	close(MESSAGE_Log); 
}

sub save_bouncing_emails {
	my @emails = @_; 
	
	if($have_mailing_list == 1){ 
		$Bounce_Email_Log =~ s/\[list\]/$list_name/g;
	}else{ 
		$Bounce_Email_Log =~ s/\[list\]/UNKNOWN/g;
	}
	
	open(EMAILLOG, ">>$Bounce_Email_Log") or 
			warn "$PROGRAM_NAME $VER Error, can't write to Bounce Email Log at: '$Bounce_Email_Log', details: $!";
	foreach(@emails){ 
		print EMAILLOG $_, "\n"; 
	}
	close(EMAILLOG); 
}

__END__

=pod

=head1 NAME mojo_bounce_handler.pl


=head1 DESCRIPTION

A simple boune handler for Mojo Mail. 

=head1 SETUP

A few things have to be tweaked at the top of the script, let's get to
that, first: 

=head2 $lib 

This script needs to be told specifically where you put the MOJO 
directory. usually, this will look like:

	my $lib = '/home/account/www/cgi-bin/mojo';


=head2 @skip_addresses

you can list what addresses you don't ever want this script to filter out
by listing them here, like this: 

	my @skip_addresses = qw(address1 address2); 

=head2 $Remove_Now

Set this to '1' if you want bounces to be automatically removed. 

=head2 $Bounced_Messages

Set this to an absolute path to keep a log of the bounced messages. 

=head2 $Bounce_Email_Log

Set this to an absolute path to keep a log of all email addresses found
in bounced messages

=head1 INSTALLATION 

upload this file to your server and chmod it to 755. For starters, 
you may just want to install it in the same directory as mojo.cgi
but it's better to put it in a more secure location that can't be 
accessed via a web browser. 

Messages are received by this script via an aliased email address that
points to this script. The email address should look like this: 

	bounce-listshortname@domain.com 

every address that goes to this script should start out with 'bounce-'

listshortname is your list's shortname. A good shortname should be small, 
all lowercase and shouldn't contain any weird characters that can't be 
made into an email address. Only a valid short name can be created using 
Mojo version 2.6. Lists made with a previous version of Mojo Mail will 
have a shortname that may not work well with this script. 

Set this address as your B<admin email address>. All error messages will go
to this address. 

=head2 Sendmail Alias Setup

Make sure in the /etc/mail/sendmail.cf file that this: 

	# use Errors-To: header?
	O UseErrorsTo=False
	
is set to True:

	# use Errors-To: header?
	O UseErrorsTo=True
	
Or this script just won't work.

Make a new alias in /etc/mail/aliases that looks like this: 

	# bounce handler for listname
	 bounce-listname: "|mojo_bounce_handler.pl"
		
where listname is the name of your list's SHORT name. Add 
mojo_bounce_handler.pl to your list of things that the sendmail secure shell
is allowed to use: 

	ln -s /home/justin/www/cgi-bin/mojo/mojo_bounce_handler.pl
	/usr/adm/sm.bin/mojo_bounce_handler.pl
	
Where '/home/justin/www/cgi-bin/mojo/mojo_bounce_handler.pl' is the absolute 
path to mojo_bounce_handler.pl
	
if you don't have a /usr/adm/sm.bin directory, make one: 

	sudo mkdir -p /usr/adm/sm.bin -m 755

Type: 

	newaliases 

in a telnet or ssh session for sendmail to see the new alias that you 
made and then restart sendmail

You should be all set to go

=head2 Qmail Alias Setup

In your home directory, make a new .qmail file, called: 

	.qmail-bounce-listname

where listname is the name of your list's SHORT name

in it, type:

	|/home/account/www/cgi-bin/mojo/mojo_bounce_handler.pl

where '/home/account/www/cgi-bin/mojo/mojo_bounce_handler.pl' is the path 
to mojo_bounce_handler.pl

Save the .qmail file. 

You should be all set to go


=cut

