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


BEGIN{ 


#CHANGE! $lib to where you placed the MOJO folder, 



$lib = '/home/acount/public_html/cgi-bin/mojo';




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


######################################################################
# That should be all you need to do. Happy sending. 
######################################################################
# No other variables need to be changed in this file!
# to set  up an e-mail address, make a alias email address that
# pipes to this script. MAKE SURE THIS SCRIPT CAN READ FILES FROM THE
# $FILES DIRECTORY! You may need to at least change the $FILE_CHMOD variable 
# in the Config.pm file to 0666. 
#
# a better explaination of this can be found at the BOTTOM of this script, in 
# pod format, you may want to run this script through pod2somethingorother
#
#
######################################################################
#load some modules that we need... 

use Mail::Address;
use Getopt::Long; 

use MOJO::Config;             # configuration variables 
use MOJO::Mail;               # use the MOJO::Mail module to send e-mails with
use MOJO::Guts;               # use MOJO::Guts for misc subroutines
use MOJO::List; 
use strict; 


# get header, footer
my $header; 
my  $body; 

{ 
local $/ = ""; 
$header = <STDIN>; 
 undef $/; 
$body = <STDIN>; 
} 

my $test = 0; 
GetOptions("test" => \$test); 
			
warn "Test: " . $test;			
#create a MOJO::Mail object
my $mh = MOJO::Mail->new(); 
#get headers in name=>value pair
my %mail_headers = $mh->return_headers($header);
   
   # 'normalize' the headers
   %mail_headers = $mh->clean_headers(%mail_headers); 
    
# extract 'To:' addresses
my @To_addresses  = Mail::Address->parse($mail_headers{To});

# extract anything in the CC: header 
my @Cc_addresses  = Mail::Address->parse($mail_headers{Cc});
  
# plop them together 
@To_addresses  = (@To_addresses, @Cc_addresses); 
  
  
# extract the 'From:' address
my $From_address  = (Mail::Address->parse($mail_headers{From}))[0]; 

my $from_to_check = 0; 
foreach my $this_address(@To_addresses){ 
	my $from_test = $From_address->address;
 	if($this_address->address =~ /$from_test/i){ 
		$from_to_check = 1; 
		last; 
	}
}

if($from_to_check == 1){ 
	warn("$PROGRAM_NAME $VER ERROR, quitting script to stop possible infinite loop!"); 
	exit;
}

my @available_lists = available_lists();
my @sending_lists;  

# check to see if the list is present.
# If it aint, we're not going to *try* to send the e-mail 


foreach my $this_address(@To_addresses){
	my $list_exists = check_if_list_exists(-List=>$this_address->user);
	if(($list_exists) && ($this_address->user ne "")){
		push(@sending_lists, $this_address->user);
	}
}

# @sending_lists now has a list of all the lists this email goes to
# (hopefully only one) 

#process 'em
foreach my $email_list(@sending_lists){ 
	my %list_info = open_database(-List => $email_list,-Format => "replaced"); 
	if($list_info{group_list} eq "1"){ 
		&send_group_email($email_list); 
	}else{ 
		&send_announce_email($email_list); 
	} 
}




sub send_announce_email{ 

my $list = shift; 
my $lh = MOJO::List->new(-List=>$list); 

my %list_info =  open_database(-List => $list,-Format => "replaced"); 								

my $mh = MOJO::Mail->new(\%list_info); 

# ok, now we check to see that the "From" corresponds with the list owner.
# Pretty tricky are we. 
# We'll allow both the list owner and the list administrator to 
# send e-mails to the group. 

# js - lowercase domain part of the email
$list_info{mojo_email}  = lc_email($list_info{mojo_email});
$list_info{admin_email} = lc_email($list_info{admin_email});

if($From_address->address =~ m/$list_info{mojo_email}/i || 
   $From_address->address =~ m/$list_info{admin_email}/i){ 

# js - escape the listname for the url 

my $escaped_list = uriescape($list);
my $s_link = subscribe_link(-list   => $list,
							-email  => '[email]', 
							-pin    => '[pin]');

my $us_link = unsubscribe_link(-list   => $list,
							   -email  => '[email]', 
						 	   -pin    => '[pin]');
						  
my $send_message_body = $list_info{mailing_list_message};
   $send_message_body =~ s/\[list_unsubscribe_link\]/$us_link/g; 
   $send_message_body =~ s/\[list_subscribe_link\]/$s_link/g; 
   $send_message_body =~ s/\[message_body\]/$body/g; 

my $message_id = message_id();

my %mailing = (

 Precedence                  =>    $list_info{precedence}, 
 To                          =>     $list_info{mojo_email}, 
'Content-Type'       		 =>    $mail_headers{'Content-Type'}, 
'MIME-Version'       		 =>    $mail_headers{'MIME-Version'},
'List-ID'            		 =>    $message_id, 
 References          		 =>    $mail_headers{References},
 'In-Reply-To'       		 =>    $mail_headers{'In-Reply-To'},
 'Content-Disposition'       =>    $mail_headers{'Content-Disposition'}, 
 'Content-Transfer-Encoding' =>    $mail_headers{'Content-Transfer-Encoding'},
 'Content-Base'              =>    $mail_headers{'Content-Base'},
# subject and Body 
  Subject                    =>    $mail_headers{Subject},
  Body                       =>    $send_message_body,
); 
 
$mh->do_not_send_to([$From_address->address]);
$mh->bulk_test(1) if($test == 1); 
$mh->bulk_send(%mailing); 

#Now lets archive the message, if needed. 
unless($list_info{archive_messages} eq "0") { 
	#archive the message

	archive_message(
	-List    =>  $list_info{list}, 
	-Subject =>  $mail_headers{Subject}, 
	-Body    =>  $body, 
	-Id      =>  $message_id, 
	); 

}


}else{ 

# if the "From" isn't one of those people, we aren't going to allow the sending of this 
# list message. We'll write an e-mail saying so, and quit. 


my $No_Post_Body = $list_info{not_allowed_to_post_message};


my %mailing = (

From           => "$list_info{mojo_email}",
To             => "$mail_headers{From}", 
Subject        => "$PROGRAM_NAME Error - Not Allowed To Post On $list_info{list_name}", 
Body           => $No_Post_Body,
); 

$mh->send(%mailing); 

#and we go!
warn("$PROGRAM_NAME $VER ERROR - Attempt to send a list message from an unknown email address: $mail_headers{From} by using mojo_send.pl"); 
exit; 




}




} 


sub send_group_email{

my $list = shift; 
my %list_info =  open_database(-List => $list,-Format => "replaced"); 								
my $lh = MOJO::List->new(-List => $list); 


my $mh = MOJO::Mail->new(\%list_info); 

# ok, well, first we have to do a check to see if the person e-mailing the
# list is allowed to: 

my $in_list = $lh->check_for_double_email(-List =>$list_info{list_name}, -Email => $From_address->address);

$in_list++ if($From_address->address =~ /$list_info{mojo_email}/i || $From_address->address =~ /$list_info{admin_email}/i);

if($in_list >= 1){ 
#we are good to go!


#now we'll check to see what the content-type of the message is, 
if($list_info{only_allow_group_plain_text} == 1){ 
	if($mail_headers{'Content-Type'} =~ m/HTML|multipart/oi){ 
		send_back_email(-Reason => 'not_plain_text', -info => \%list_info); 
	exit;
	}
} 
 
 


my $email; 

my $escaped_list = uriescape($list);
my $s_link = subscribe_link(-list   => $list);

my $us_link = unsubscribe_link(-list   => $list);
							   

my $send_message_body = $list_info{mailing_list_message};
$send_message_body =~ s/\[list_unsubscribe_link\]/$us_link/g; 
$send_message_body =~ s/\[list_subscribe_link\]/$s_link/g; 
$send_message_body =~ s/\[message_body\]/$body/g; 
  
if($list_info{allow_group_interpolation} == 1){ 
	$send_message_body = interpolate_string(-String      => $send_message_body, 
											-List_Db_Ref => \%list_info);
}
  
my $group_subject = $mail_headers{Subject}; 
my $add_list_name = $list_info{append_list_name_to_subject}; 
  
if($add_list_name ne "0"){ 
 
 	my $ln = $list_info{list_name}; 
	
	$group_subject =~ s/\[$ln\]//; 
	$group_subject =~ s/^((RE:|AW:)\s+)+//i;
	
	my $re = $1;
	   $re =~ s/^(\s+)//; 
	   $re =~ s/(\s+)$//; 
	    
	   $re = ' ' . $re if $re; 
	   
	$group_subject =~ s/^(\s+)//;
	$group_subject = "[$ln]$re $group_subject"; 

}
 
  
my $message_id = message_id();  

my %mailing = ( 
# headers
 From                       =>    $mail_headers{From}, 
 
 To                         =>    $list_info{mojo_email},

'Content-Type'              =>    $mail_headers{'Content-Type'}, 
'MIME-Version'              =>    $mail_headers{'MIME-Version'},
'List-ID'                   =>    $message_id, 
 References                 =>    $mail_headers{References},
 'In-Reply-To'              =>    $mail_headers{'In-Reply-To'},
'Content-Disposition'       =>    $mail_headers{'Content-Disposition'}, 
'Content-Transfer-Encoding' =>    $mail_headers{'Content-Transfer-Encoding'},
'Content-Base'              =>    $mail_headers{'Content-Base'},

# Subject and body
 Subject                    =>    $group_subject,
 Body                       =>    $send_message_body,
); 
 


$mailing{'Reply-To'} = $mail_headers{To} unless $list_info{add_reply_to} eq "0";

$mh->do_not_send_to([@To_addresses]);

$mh->do_not_send_to([$From_address->address]) unless $list_info{mail_group_message_to_poster} eq "1"; 

#send away!
$mh->bulk_send(%mailing); 

#all set. 


#Now lets archive the message, if needed. 

unless($list_info{archive_messages} eq "0") { 
	#archive the message

	archive_message(
	-List    =>  $list_info{list}, 
	-Subject =>  $mail_headers{Subject}, 
	-Body    =>  $body, 
	-Id      =>  $message_id, 
	); 
	}


}else{ 
#we have problems. this is not going to work abort!

my $No_Post_Body = $list_info{not_allowed_to_post_message};




my %mailing = (

From           => "$list_info{mojo_email}",
To             => $From_address->address, 
Subject        => "Mojo Mail Error - Not Allowed To Post On $list_info{list}", 
Body           => $No_Post_Body,
); 

$mh->send(%mailing); 

#and we go!
warn("$PROGRAM_NAME $VER ERROR - Attempt to send a list message from an unknown email address: $mail_headers{From} by using mojo_send.pl"); 
exit; 



}

}



sub send_back_email { 
my %args = ( 
-Reason => undef,
-info    => undef, 
@_,
);


my $list_info = $args{-info};  
my %list_info = %$list_info; 

my %reasons; 

$reasons{not_plain_text} = <<EOF

Hello! 

I'm sorry, but your e-mail has been giving back to you because 
group messages posted to "$list_info{list_name}" have to be in 
plain text format. 


You probably are trying to send your message in HTML format, or 
something similar. 

You may want to contact the list owner at $list_info{mojo_email} if 
this isn't the cause, or you're having other problems, 

Thanks! 

A copy of your message: 
================================================================

$header

$body

EOF
;  




my %mailing = ( 
To             => $From_address->address, 
From           => $list_info{mojo_email},
Subject        => "\[$list_info{list_name}\] Error, please read below:",
Body           => $reasons{$args{-Reason}},
); 
$mh->send(%mailing); 
exit; 



}


# and we are done here. 








=pod

=head1 Configuring mojo_send.pl

Mojo Mail can now send announce-only and group e-mails by using any
e-mail program you normally use, instead of using your list's control
panel. This is done by configuring mojo_send.pl. This script is located
in the 'mojo' folder when you downloaded the script.

Note: These features may not be available to you. Not all hosting
companies allow you take advantage of what Mojo Mail needs to get this
setup. What you need to do is set up an alias e-mail address. An alias
e-mail address is an address that goes somewhere else. You can have an
address called "bob@skazat.com" that really goes to "justin@skazat.com".
Instead of going to another address, we're going to tell it to go to a
script - mojo_send.pl. The setup of this feature is NOT cut and dry.

Its hard to tell if you can do this at all and much banging of heads on
desks might result. Please understand that all servers and mail programs
are set up differently and I'm limited on what machines I can test this
on. If you configure this script differently that whats written here,
please share your findings to help others! Consider this script an
advanced feature. As hard as this is, its factors easier than setting up
something similar, like majordomo.

=head1 Before You Set Up.

Before you go right into all of this, it might be a good idea to ask
your system administrator if this is actually possible. You need to ask
them if you are able to set up email addresses that alias to a file. You
may not be able to. If you're server is using Sendmail, which is a very
popular Mail User Agent, be aware that Sendmail can be configured to
disallow mail aliasing to a program. You'll know if this can't be done
if you get a 'Cannot send mail directly to a program.' error. Never
hurts to ask!

I'll be giving you instructions on how to set up mojo_send.pl using
qmail and sendmail. Most likely, you're using sendmail. I am not as 
familiar with sendmail as I am with Qmail. 

=head1 Setup mojo_send.pl

Open mojo_send.pl in your favorite text editor. You need to change one
thing in that file. In the first part of the script, there's a line that
says:

	$lib = '/usr/home/path/toyour/mojo_directory';

You have to change this to the directory that you put the mojo.cgi
script and the MOJO folder. mojo_send.pl needs certain things in the
MOJO folder to work correctly, so you need to tell it where it is.

Upload mojo_send.pl into your cgi-bin directory. For simplicity, upload
it into the same directory as your mojo.cgi script and MOJO folder.
Change the permissions of the script to 755, just like you did for the
mojo.cgi script. If you want to, you may move this script in other
places, for better security.

Making An Aliased E-mail address.

=head1 Configuring for Qmail

Qmail uses a seperate '.qmail' file for each e-mail alias. An alias is
called .qmail-alias, where 'alias' is your alias address. If I wanted
bob@skazat.com to go to justin@skazat.com, I would make a .qmail file
called

	.qmail-bob

and inside write this:


	&justin@skazat.com

which is the email address I want it to really go. Notice the Ampersand
'&' character before the address. That's important. .qmail files are
usually found in your home directory. My home directory is:

	/usr/home/justin

mojo_send.pl always looks for an address that's the same name as the
list's short name with underscores instead of spaces. For the list short
name, 'skazat design newsletter', i would want to make an e-mail alias
'skazat_design_newsletter@skazat.com'

To do this in Qmail, I would write a .qmail file called
".qmail-skazat_design_newsletter" and write:


	|/usr/home/pathtothe/mojo_send.pl

where '/usr/home/pathtothe/mojo_send.pl ' is the Absolute Path to the
mojo_send.pl script. The vertical bar, '|' before the path is very
important, it tells Qmail to pipe the message to the mojo_send.pl
script, whos absolute pathname you specified after the vertical bar.

Test the script out by saving your mojo_send.pl changes and the .qmail
file. Send a message to yourlist@yourdomain.com where 'yourlist 'is the
name of your list's short name and 'yourdomain' is the name of your
domain. Only the list owner and list administrator are allowed to send
messages this way unless you specify that you want to have a group list.
You can do this by going to the "Mailing List Options" screen of each
list's control panel.


=head1 Configuring for Sendmail 

This particular set of instructions takes into account that you do have
root access to the machine your using. If you do not have root access, 
these instructions will not work.

make an  /etc/mail/aliases file, if you don't already have one and 
write in it: 

	# My Mojo Mail List
	listname: "|mojo_send.pl"

where 'listname' is my list's B<shortname> that I wanted to use. 
In 2.6, there are shortnames and list names, shortnames are kinda
like login names, they're supposed to be short and lowercase,
 having a short name allows you to be more creative
with the listname and also allows you to change the list name, which was a
big request. Lists made with 2.5 below shortnames will be their original
list names, which might not work correctly. 

You may also need to tweak the virtusertable file in sendmail. 
For this example add this line: 

 listname@mydomain.com          listname

You then have to issue this command: 

 makemap hash /etc/mail/virtusertable < /etc/mail/virtusertable


After that, make a directory for the sendmail restricted shell, if you don't already have one:

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

In this directory, you list all the apps that you allow sendmail to run via
pipes (like in my aliases file), for more info, type in

	man smrsh

in a telnet or ssh session

Make a soft link to mojo_send.pl:

	ln -s /Library/WebServer/CGI-Executables/mojo/mojo_send.pl
	/usr/adm/sm.bin/mojo_send.pl

Type: 

	newaliases 

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

 Make sure in your sendmail.cf file (mine was in
/etc/mail/sendmail.cf) has the alias file thingy uncommented, like this:

	# location of alias file
	O AliasFile=/etc/mail/aliases

Also, you want to set this to True:

	# use Errors-To: header?
	O UseErrorsTo=False

Sendmail sucks, don't it? 

=head1 CONFIGURING USING PROCMAIL

If your server has Procmail installed (and there's a good chance that it does) you
can use it with mojo_send.pl, even if you can't configure Sendmail or Qmail. 

Procmail uses 'recipes' to filter mail and send it to various locations. Here's a 
simple recipe for mojo_send.pl:

	:0
	* ^[TO|CC].*listname
	|/usr/home/pathtothe/mojo_send.pl

This recipe will look for any messages that are in the To: or Cc: headers
and have B<listname> in it. 

Nothing to it. Obviously, this is not a lesson in Procmail, get Procmail working
before trying this. A B<great> tutorial on all this is at: 

http://www.ii.com/internet/robots/procmail/qs/

More than you ever need can also be found here:

http://www.ii.com/internet/robots/procmail/

B<DO NOT> ask me how to set up Procmail, I'm afraid I'm too green at it all. 
But here's some more info. Please understand that all this may be very local to the server
setup I'm using.  Anyways, for a list called 'info' I needed to setup a .qmail file called
B<.qmail-info> or the recipe would not work. my .qmail file looks like this: 

	| preline /usr/local/bin/procmail -p

my B<.procmailrc> file, among other things, had this thingy in it: 

 PMDIR=$HOME/Procmail
 INCLUDERC=$PMDIR/list.rc

B<list.rc> is where I had the recipe kept.

Debugging also helps (in .procmailrc): 

	VERBOSE=yes
	LOGABSTRACT=all


=head1 Troubleshooting.

What's really hard to do for this script is find out what went wrong, if
anything, since you don't get immediate feedback. Your Error Logs are
GREAT places to start looking. Also, it's a really good idea to test
your script on a command line. If you have telnet access you can type
in:

	perl -c mojo_send.pl

which will tell perl to compile -but not run the script, and report back
any errors. Very handy.


You can also use the script right on the command line, just write out a
mail message with the mail headers and your body, your headers and body
should be seperated by two lines:

	To: newsletter@skazat_design.com 
	From: justin@skazat.com 
	Subject: This
	is a test from the command line in telnet
	
	Hello, is anyone there? I should receive this, as should everyone 
	else on my list!

Type Control-D when your done writing to tell Perl that you are done.

To test the script, add the '--test' flag when you execute the script: 

 perl mojo_send.pl --test

And then write your message. The message will now only be sent to the list owner. 

Another great idea is to change the $MAIL_SETTINGS variable, located in
the Config.pm file, to a file name, like this:

	$MAIL_SETTINGS = '>>/usr/home/path/to/testfile.txt';

the '>>' tells Mojo to append every mail message to the end of the file,
instead of writting over it. Changing the $mail_setttings to a filename
will make every e-mail you 'send' be appended to this file, instead of
being actually e-mailed out. Running the script on the command line and
changing the $MAIL_SETTINGS to a file takes the entire mail program out
of the system, so you can see if its the mail program giving you
trouble, or something else.

=head1 How The Script Works

This script receives your e-mail message and parses the headers - the
part of the e-mail you usually don't see - that contain information
about who the e-mails from and where it's to. If the E-mails From: is
the same as the name of the special email alias address you just setup
(essentially, the To: is the same as the From:), it'll stop cold and
write an error to your log. This usually means that the script is trying
to send a message to iteself, and it will do so, for a very long time,
unless we stop it right away.

After that, the script sees if there's a list short name that matches
what you named the special e-mail address. If nothing matches. It stops.
mojo_send.pl should write something in your error log that says it
couldn't find the list. It also sends an e-mail to the person trying to
send to the unknown list telling them there isn't a list by that name.

If it finds the list, it opens up that list's information and sees if
the e-mail from either the list owner or list administrator if its an
announce-only list, or, if its from anyone that's subscribed to the list
if your list is a group list. If it isn't from the right people it will
e-mail back to the person telling them they aren't allowed to send email
messages to the list. You can edit what this message looks like in your
list's control panel under "Customize E-mail Messages".

If the right person is sending to the e-mail list, the message gets
sent. E-mails will be formatted as you specify in the "Customize E-mail
Messages" section in your list's Control Panel. mojo_send.pl will also
archive your message just like it does when you send messages from your
control panel.

=head1 A Word of Caution

mojo_send.pl may not be the most secure script to use, some nasty person
can fake e-mail headers, and send to a list its not supposed to. Sending
e-mails from your list's Control Panel is much more secure, though you
lack the Group E-mail feature. You can't change or retreive any of your
list's information using mojo_send.pl, which is good. Be aware that
there's reasons why programs such as Majordomo are so hard to setup -
they're also much more secure when sending e-mails to scripts this way.

=head1 Special Commands Sent to mojo_send.pl

mojo_send.pl doesn't support any special e-mail commands, such as
subscribe, unsubscribe or information about the list. We find the
web-based way of getting this information is alot easier to use. This
also makes mojo_send.pl much simpler and certainly easy to customize if
you know perl well enough. You can add these features to a similar
script, perhaps set up an email address called mojo@yourdomain.com and a
script that reads information sent from that address. The script could
take care of subscribe/unsubscribe requests by email. Just a thought!



=cut




=head1 COPYRIGHT 

Copyright (c) 1999 - 2002 Justin Simoni (justin@skazat.com) http://justinsimoni.com 
All rights reserved. 

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.


=cut



