#!/usr/bin/perl

use strict;

use Carp qw(verbose);
use Sendmail::PMilter qw(:all);
use Data::Dumper;
use Sys::Syslog;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Time::HiRes qw(gettimeofday);
use Getopt::Long;

my $savedir = "/var/piler/imap";
my $username = 'piler';
my $conn = 'inet:33333@127.0.0.1';

my $miltername = 'pilter';
my $priority = "mail|info";
my $fname = '';
my $msglen = 0;
my $newdir = "new";
my $curdir = "cur";
my $newname;
my $curname;
my $messageid;
my $help = 0;

my $opts = GetOptions(
                     "conn=s" => \$conn,
                     "username=s" => \$username,
                     "savedir=s" => \$savedir,
                     "h" => \$help,
                     "help" => \$help
                    );

if($help == 1) { die("usage: $0 --conn inet:33333\@127.0.0.1 --username piler --savedir /var/piler/imap"); }

chdir $savedir || die("cannot chdir to $savedir");

my %cbs;
for my $cb (qw(close connect helo abort envfrom envrcpt header eoh body eom)) {
	$cbs{$cb} = sub {
		my $ctx = shift;
                my ($seconds, $microseconds);

                ###if($cb eq "connect") {
                if($cb eq "envrcpt") {
                   ($seconds, $microseconds) = gettimeofday;
                   $fname = $seconds . "-" . $microseconds . "-" . $$ . "-" . &get_random_name;

                   ###syslog $priority, "fname=$fname";

                   if(! -d $newdir) { mkdir $newdir, 0700; }

                   $newname = $newdir . "/" . $fname;
                   $curname = $curdir . "/" . $fname;

                   $msglen = 0;
                   $messageid = '';

                   if(!open(F, ">$newname")) { return SMFIS_TEMPFAIL; }
                }

                elsif($cb eq "header") {
                   $msglen += length ( @_[0] . ": " . @_[1] . "\n" );
                   print F @_[0] . ": " . @_[1] . "\n";

                   if(@_[0] =~ /^message-id$/i) { $messageid = @_[1]; }
                }

                elsif($cb eq "eoh") {
                   print F "\n";
                }

                elsif($cb eq "body") {
                   $msglen += @_[1];
                   print F @_[0];
                }

                elsif($cb eq "eom") {
                   close F;

                   if(! -d $curdir) { mkdir $curdir, 0755; }

                   rename $newname, $curname;

                   syslog $priority, "message-id=$messageid, fname=$fname, size=$msglen";

                }

                #if ($cb =~ /^(connect|help|envfrom|envrcpt)$/) {
                #       print Dumper($ctx->{symbols})."\n";
                #}

		SMFIS_CONTINUE;
	}
}

openlog($miltername, 'pid', 'mail');

$< = $> = getpwnam $username;

syslog $priority, "$miltername starting";


my $milter = new Sendmail::PMilter;
$milter->setconn($conn);

$milter->register($miltername, \%cbs, SMFI_CURR_ACTS);

my $dispatcher = Sendmail::PMilter::prefork_dispatcher(
	max_children => 5,
	max_requests_per_child => 100,
);

$milter->set_dispatcher($dispatcher);

$milter->main();



sub get_random_name {
   my @chars = ('A'..'Z', 0..9);
   my $s = '';

   srand;

   $s .= $chars[rand @chars] for 1..8;

   return $s;
}