|
Ryan Haggerty |
e50d1d |
#!/usr/local/bin/perl
|
|
Ryan Haggerty |
e50d1d |
##
|
|
Ryan Haggerty |
e50d1d |
## Sendmail mailer for Mailman
|
|
Ryan Haggerty |
e50d1d |
##
|
|
Ryan Haggerty |
e50d1d |
## Simulates these aliases:
|
|
Ryan Haggerty |
e50d1d |
##
|
|
Ryan Haggerty |
e50d1d |
##testlist: "|/home/mailman/mail/mailman post testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-admin: "|/home/mailman/mail/mailman admin testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-bounces: "|/home/mailman/mail/mailman bounces testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-confirm: "|/home/mailman/mail/mailman confirm testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-join: "|/home/mailman/mail/mailman join testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-leave: "|/home/mailman/mail/mailman leave testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-owner: "|/home/mailman/mail/mailman owner testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-request: "|/home/mailman/mail/mailman request testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-subscribe: "|/home/mailman/mail/mailman subscribe testlist"
|
|
Ryan Haggerty |
e50d1d |
##testlist-unsubscribe: "|/home/mailman/mail/mailman unsubscribe testlist"
|
|
Ryan Haggerty |
e50d1d |
##owner-testlist: testlist-owner
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Some assembly required.
|
|
Ryan Haggerty |
e50d1d |
$MMWRAPPER = "/etc/mail/mailman";
|
|
Ryan Haggerty |
e50d1d |
$MMLISTDIR = "/etc/mailman/lists";
|
|
Ryan Haggerty |
e50d1d |
$SENDMAIL = "/usr/lib/sendmail -oem -oi";
|
|
Ryan Haggerty |
e50d1d |
$VERSION = '$Id: mm-handler,v 1.2 2002/04/05 19:41:09 bwarsaw Exp $';
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Comment this if you offer local user addresses.
|
|
Ryan Haggerty |
e50d1d |
$NOUSERS = "\nPersonal e-mail addresses are not offered by this server.";
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
# uncomment for debugging....
|
|
Ryan Haggerty |
e50d1d |
#$DEBUG = 1;
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
use FileHandle;
|
|
Ryan Haggerty |
e50d1d |
use Sys::Hostname;
|
|
Ryan Haggerty |
e50d1d |
use Socket;
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
($VERS_STR = $VERSION) =~ s/^\$\S+\s+(\S+),v\s+(\S+\s+\S+\s+\S+).*/\1 \2/;
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$BOUNDARY = sprintf("%08x-%d", time, time % $$);
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Informative, non-standard rejection letter
|
|
Ryan Haggerty |
e50d1d |
sub mail_error {
|
|
Ryan Haggerty |
e50d1d |
my ($in, $to, $list, $server, $reason) = @_;
|
|
Ryan Haggerty |
e50d1d |
my $sendmail;
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
if ($server && $server ne "") {
|
|
Ryan Haggerty |
e50d1d |
$servname = $server;
|
|
Ryan Haggerty |
e50d1d |
} else {
|
|
Ryan Haggerty |
e50d1d |
$servname = "This server";
|
|
Ryan Haggerty |
e50d1d |
$server = &get_ip_addr;
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
#$sendmail = new FileHandle ">/tmp/mm-$$";
|
|
Ryan Haggerty |
e50d1d |
$sendmail = new FileHandle "|$SENDMAIL $to";
|
|
Ryan Haggerty |
e50d1d |
if (!defined($sendmail)) {
|
|
Ryan Haggerty |
e50d1d |
print STDERR "$0: cannot exec \"$SENDMAIL\"\n";
|
|
Ryan Haggerty |
e50d1d |
exit (-1);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$sendmail->print ("From: MAILER-DAEMON\@$server
|
|
Ryan Haggerty |
e50d1d |
To: $to
|
|
Ryan Haggerty |
e50d1d |
Subject: Returned mail: List unknown
|
|
Ryan Haggerty |
e50d1d |
Mime-Version: 1.0
|
|
Ryan Haggerty |
e50d1d |
Content-type: multipart/mixed; boundary=\"$BOUNDARY\"
|
|
Ryan Haggerty |
e50d1d |
Content-Disposition: inline
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
--$BOUNDARY
|
|
Ryan Haggerty |
e50d1d |
Content-Type: text/plain; charset=us-ascii
|
|
Ryan Haggerty |
e50d1d |
Content-Description: Error processing your mail
|
|
Ryan Haggerty |
e50d1d |
Content-Disposition: inline
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
Your mail for $list could not be sent:
|
|
Ryan Haggerty |
e50d1d |
$reason
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
For a list of publicly-advertised mailing lists hosted on this server,
|
|
Ryan Haggerty |
e50d1d |
visit this URL:
|
|
Ryan Haggerty |
e50d1d |
http://$server/
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
If this does not resolve your problem, you may write to:
|
|
Ryan Haggerty |
e50d1d |
postmaster\@$server
|
|
Ryan Haggerty |
e50d1d |
or
|
|
Ryan Haggerty |
e50d1d |
mailman-owner\@$server
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$servname delivers e-mail to registered mailing lists
|
|
Ryan Haggerty |
e50d1d |
and to the administrative addresses defined and required by IETF
|
|
Ryan Haggerty |
e50d1d |
Request for Comments (RFC) 2142 [1].
|
|
Ryan Haggerty |
e50d1d |
$NOUSERS
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
The Internet Engineering Task Force [2] (IETF) oversees the development
|
|
Ryan Haggerty |
e50d1d |
of open standards for the Internet community, including the protocols
|
|
Ryan Haggerty |
e50d1d |
and formats employed by Internet mail systems.
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
For your convenience, your original mail is attached.
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
[1] Crocker, D. \"Mailbox Names for Common Services, Roles and
|
|
Ryan Haggerty |
e50d1d |
Functions\". http://www.ietf.org/rfc/rfc2142.txt
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
[2] http://www.ietf.org/
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
--$BOUNDARY
|
|
Ryan Haggerty |
e50d1d |
Content-Type: message/rfc822
|
|
Ryan Haggerty |
e50d1d |
Content-Description: Your undelivered mail
|
|
Ryan Haggerty |
e50d1d |
Content-Disposition: attachment
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
");
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
while ($_ = <$in>) {
|
|
Ryan Haggerty |
e50d1d |
$sendmail->print ($_);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$sendmail->print ("\n");
|
|
Ryan Haggerty |
e50d1d |
$sendmail->print ("--$BOUNDARY--\n");
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
close($sendmail);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Get my IP address, in case my sendmail doesn't tell me my name.
|
|
Ryan Haggerty |
e50d1d |
sub get_ip_addr {
|
|
Ryan Haggerty |
e50d1d |
my $host = hostname;
|
|
Ryan Haggerty |
e50d1d |
my $ip = gethostbyname($host);
|
|
Ryan Haggerty |
e50d1d |
return inet_ntoa($ip);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Split an address into its base list name and the appropriate command
|
|
Ryan Haggerty |
e50d1d |
## for the relevant function.
|
|
Ryan Haggerty |
e50d1d |
sub split_addr {
|
|
Ryan Haggerty |
e50d1d |
my ($addr) = @_;
|
|
Ryan Haggerty |
e50d1d |
my ($list, $cmd);
|
|
Ryan Haggerty |
e50d1d |
my @validfields = qw(admin bounces confirm join leave owner request
|
|
Ryan Haggerty |
e50d1d |
subscribe unsubscribe);
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
if ($addr =~ /(.*)-(.*)\+.*$/) {
|
|
Ryan Haggerty |
e50d1d |
$list = $1;
|
|
Ryan Haggerty |
e50d1d |
$cmd = "$2";
|
|
Ryan Haggerty |
e50d1d |
} else {
|
|
Ryan Haggerty |
e50d1d |
$addr =~ /(.*)-(.*)$/;
|
|
Ryan Haggerty |
e50d1d |
$list = $1;
|
|
Ryan Haggerty |
e50d1d |
$cmd = $2;
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
if (grep /^$cmd$/, @validfields) {
|
|
Ryan Haggerty |
e50d1d |
if ($list eq "owner") {
|
|
Ryan Haggerty |
e50d1d |
$list = $cmd;
|
|
Ryan Haggerty |
e50d1d |
$cmd = "owner";
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
} else {
|
|
Ryan Haggerty |
e50d1d |
$list = $addr;
|
|
Ryan Haggerty |
e50d1d |
$cmd = "post";
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
return ($list, $cmd);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## The time, formatted as for an mbox's "From_" line.
|
|
Ryan Haggerty |
e50d1d |
sub mboxdate {
|
|
Ryan Haggerty |
e50d1d |
my ($time) = @_;
|
|
Ryan Haggerty |
e50d1d |
my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
|
|
Ryan Haggerty |
e50d1d |
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
|
|
Ryan Haggerty |
e50d1d |
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
|
|
Ryan Haggerty |
e50d1d |
localtime($time);
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
## Two-digit year handling complies with RFC 2822 (section 4.3),
|
|
Ryan Haggerty |
e50d1d |
## with the addition that three-digit years are accommodated.
|
|
Ryan Haggerty |
e50d1d |
if ($year < 50) {
|
|
Ryan Haggerty |
e50d1d |
$year += 2000;
|
|
Ryan Haggerty |
e50d1d |
} elsif ($year < 1900) {
|
|
Ryan Haggerty |
e50d1d |
$year += 1900;
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
return sprintf ("%s %s %2d %02d:%02d:%02d %d",
|
|
Ryan Haggerty |
e50d1d |
$days[$wday], $months[$mon], $mday,
|
|
Ryan Haggerty |
e50d1d |
$hour, $min, $sec, $year);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
BEGIN: {
|
|
Ryan Haggerty |
e50d1d |
$sender = undef;
|
|
Ryan Haggerty |
e50d1d |
$server = undef;
|
|
Ryan Haggerty |
e50d1d |
@to = ();
|
|
Ryan Haggerty |
e50d1d |
while ($#ARGV >= 0) {
|
|
Ryan Haggerty |
e50d1d |
if ($ARGV[0] eq "-r") {
|
|
Ryan Haggerty |
e50d1d |
$sender = $ARGV[1];
|
|
Ryan Haggerty |
e50d1d |
shift @ARGV;
|
|
Ryan Haggerty |
e50d1d |
} elsif (!defined($server)) {
|
|
Ryan Haggerty |
e50d1d |
$server = $ARGV[0];
|
|
Ryan Haggerty |
e50d1d |
} else {
|
|
Ryan Haggerty |
e50d1d |
push(@to, $ARGV[0]);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
shift @ARGV;
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
if ($DEBUG) {
|
|
Ryan Haggerty |
e50d1d |
$to = join(',', @to);
|
|
Ryan Haggerty |
e50d1d |
print STDERR "to: $to\n";
|
|
Ryan Haggerty |
e50d1d |
print STDERR "sender: $sender\n";
|
|
Ryan Haggerty |
e50d1d |
print STDERR "server: $server\n";
|
|
Ryan Haggerty |
e50d1d |
exit(-1);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
ADDR: for $addr (@to) {
|
|
Ryan Haggerty |
e50d1d |
$prev = undef;
|
|
Ryan Haggerty |
e50d1d |
$list = $addr;
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$cmd= "post";
|
|
Ryan Haggerty |
e50d1d |
if (! -f "$MMLISTDIR/$list/config.pck") {
|
|
Ryan Haggerty |
e50d1d |
($list, $cmd) = &split_addr($list);
|
|
Ryan Haggerty |
e50d1d |
if (! -f "$MMLISTDIR/$list/config.pck") {
|
|
Ryan Haggerty |
e50d1d |
$was_to = $addr;
|
|
Ryan Haggerty |
e50d1d |
$was_to .= "\@$server" if ("$server" ne "");
|
|
Ryan Haggerty |
e50d1d |
mail_error(\*STDIN, $sender, $was_to, $server,
|
|
Ryan Haggerty |
e50d1d |
"no list named \"$list\" is known by $server");
|
|
Ryan Haggerty |
e50d1d |
next ADDR;
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$wrapper = new FileHandle "|$MMWRAPPER $cmd $list";
|
|
Ryan Haggerty |
e50d1d |
if (!defined($wrapper)) {
|
|
Ryan Haggerty |
e50d1d |
## Defer?
|
|
Ryan Haggerty |
e50d1d |
print STDERR "$0: cannot exec ",
|
|
Ryan Haggerty |
e50d1d |
"\"$MMWRAPPER $cmd $list\": deferring\n";
|
|
Ryan Haggerty |
e50d1d |
exit (-1);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
# Don't need these without the "n" flag on the mailer def....
|
|
Ryan Haggerty |
e50d1d |
#$date = &mboxdate(time);
|
|
Ryan Haggerty |
e50d1d |
#$wrapper->print ("From $sender $date\n");
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
# ...because we use these instead.
|
|
Ryan Haggerty |
e50d1d |
$from_ = <STDIN>;
|
|
Ryan Haggerty |
e50d1d |
$wrapper->print ($from_);
|
|
Ryan Haggerty |
e50d1d |
|
|
Ryan Haggerty |
e50d1d |
$wrapper->print ("X-Mailman-Handler: $VERSION\n");
|
|
Ryan Haggerty |
e50d1d |
while (<STDIN>) {
|
|
Ryan Haggerty |
e50d1d |
$wrapper->print ($_);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
close($wrapper);
|
|
Ryan Haggerty |
e50d1d |
}
|
|
Ryan Haggerty |
e50d1d |
}
|