#!/usr/bin/perl -w

use strict;
use 5.005;

my $TMPDIR = $ENV{TMPDIR} || $ENV{TEMP} || '/usr/tmp';

# The default mailbox for delivery.
my $default = "/var/spool/mail/".getpwuid($>);

# A pattern to break out words in email names.
my $wordpat = qr/[-a-zA-Z0-9_.]+/;
my $wordpat_nodot = qr/[-a-zA-Z0-9_]+/;

# Destination for special emails.
sub incoming { $ENV{HOME}."/Mail/Incoming/".$_[0].".spool" }

# Destination for mailing lists.
sub maillist { incoming("maillists.".$_[0]) }

# Destination for SPAM.
sub spambox  { incoming("spam.".$_[0]) }

use Mail::Procmail;

################ The Process ################

eval { ################ BEGIN PROTECTED EXECUTION ################

# Setup Procmail module.
my $m_obj = pm_init ( logfile => 'stderr', loglevel => 3 );

# Init local values for often used headers.
my $m_from		    = pm_gethdr("from");
my $m_to		    = pm_gethdr("to");
my $m_cc		    = pm_gethdr("cc");
my $m_subject		    = pm_gethdr("subject");
my $m_sender		    = pm_gethdr("sender");
my $m_apparently_to	    = pm_gethdr("apparently-to");
my $m_resent_to		    = pm_gethdr("resent-to");
my $m_resent_cc		    = pm_gethdr("resent-cc");
my $m_resent_from	    = pm_gethdr("resent-from");
my $m_resent_sender	    = pm_gethdr("resent-sender");
my $m_apparently_resent_to  = pm_gethdr("apparently-resent-to");

my $m_header                = $m_obj->head->as_string || '';
my $m_body                  = join("", @{$m_obj->body});
my $m_size		    = length($m_body);
my $m_lines		    = @{$m_obj->body};

# These mimic procmail's TO and FROM patterns.
my $m_TO   = join("\n", $m_to, $m_cc, $m_apparently_to,
	                $m_resent_to, $m_resent_cc,
                        $m_apparently_resent_to);
my $m_FROM = join("\n", $m_from, $m_sender,
		        $m_resent_from, $m_resent_sender);

# Start logging.
pm_log(1, "Mail from $m_from");
pm_log(1, "To: $m_to");
pm_log(1, "Subject: $m_subject");

################ Get rid of some SPAMs ################

pm_ignore("Non-ASCII in subject")
  if $m_subject =~ /[\232-\355]{3}/;

pm_ignore("Bogus address: \@internet.sciurius.nl")
  if $m_TO =~ /\@internet.sciurius.nl/mi;

################ Dispatching ################

# External mail to xxx@sciurius.nl is delivered to me. Dispatch here.
# Internal mail to xxx@sciurius.nl is delivered via aliases.

if ( $m_TO =~ /jjkenzen@/mi ) {
    # Maybe CC to me?
    pm_deliver($default, continue => 1)
      if $m_TO =~ /jv(romans)?@/mi;
    pm_resend("jojan");
}

################ Intercepting ################

# I always want to see these.
pm_deliver($default, continue => 1)
  if $m_header =~ /getopt(ions|(-|::)?long)/i
  || $m_body   =~ /getopt(ions|(-|::)?long)/i;

pm_deliver($default)
  if $m_subject =~ /MODERATE/;

################ Mailing lists ################

# More or less standard mailing lists.
if ( $m_sender =~ /owner-($wordpat)@($wordpat)/i
     || $m_sender =~ /($wordpat)-owner@($wordpat)/i ) {
    my ($topic, $host) = ($1, $2);

    # Fix some list names.
    if ( $host eq "perl.org" ) {
	$topic = "perl-" . $topic
	  unless $topic =~ /^perl/;
    }
    elsif ( $topic eq "announce" ) {
	if ( $host eq "htmlscript.com" ) {
	    $topic = "htmlscript";
	}
    }

    pm_deliver(maillist($topic));
}

for ( pm_gethdr("x-mailing-list"),
      pm_gethdr("list-post"),
      pm_gethdr("mailing-list"),
      pm_gethdr("x-loop"),
    ) {

    my ($topic, $host);

    if ( ($topic, $host) = /($wordpat)@($wordpat)/i ) {

	if ( $host eq "perl.org" ) {
	    $topic = "perl6-bootstrap" if lc eq "bootstrap";
	    $topic = "perl-" . $topic unless $topic =~ /^perl/;
	    $topic =~ s/-help$//;
	}
    }

    pm_deliver(maillist($topic)) if defined $topic;
}

###### Miscellaneous

# Wannabe mailing lists (without standard headers).
for ( qw( j2ee-interest
	  cwnl-developers
	  tex-nl
	  bbdb-info bbdb-announce
	  nbui nbdev
	  info-cvs
	)
    ) {
    if ( $m_sender =~ /\b$_@/i || $m_TO =~ /\b$_@/mi ) {
	$_ = "bbdb-info" if /^bbdb-/i;
	pm_deliver(maillist($_));
    }
}

# A mailing list that catches SPAM.
if ( $m_TO =~ /(info|bug-)?vm[@%]/mi 
     || $m_FROM =~ /(info|bug-)?vm(-request)[@%]/mi ) {

    deliver_continue($default)
      if $m_subject =~ /^\[announcement\]/i;

    # Make sure VM is at least mentioned in the body...
    pm_deliver(maillist("vm"))
      if $m_body =~ /\bvm\b/i;
    spam("VM spam");
}

# A mailing list with several aliases.
pm_deliver(maillist("gnu-prog-disc"))
  if $m_TO =~ /gnu-prog(-disc(uss)?)?[@%]/mi;

# Host dependent actions
if ( $pm_hostname =~ /\.sciurius\.nl/i ) {

    # Notice mail to obsolete adresses.
    pm_deliver($ENV{HOME}."/Mail/AddrChange", continue => 1)
      if $m_TO =~ m/(jv|johan|johan.vromans|jvromans)
		    \@
		    (mh\.nl|((solair1\.)?inter\.)?nl\.net)/xmi;
}

# Discard mail that is not addressed to me.
spam("Apparently not for me")
  if $m_apparently_to =~ /<(jv|johan)/i;

# It's probably a real message for me.
pm_deliver($default);

}; ################ END PROTECTED EXECUTION ################

if ( $@ ) {
    # Something went seriously wrong...
    my $msg = $@;
    $msg =~ s/\n.*//s;

    # Log it using syslog.
    my ($tool, $facility, $level) = qw(procmail mail crit);
    require Sys::Syslog;
    import Sys::Syslog;
    openlog($tool, "pid,nowait", $facility);
    syslog($level, "%s", $msg);
    closelog();

    # Also, log normally.
    pm_log(0, "FATAL: $msg");

    # Turn it into temporary failure and hope someone notices...
    exit Mail::Procmail::TEMPFAIL;
}

################ Subroutines ################

sub spam {
    my ($tag, $reason, %atts) = ("spam", @_);
    my $line = (caller(1))[2];
    pm_log(2, $tag."[$line]: $reason");
    pm_deliver(spambox($tag), %atts);
}
