#!/usr/bin/perl
#
# $Id$
#
use strict;
use Getopt::Std;
use File::Find;


my %opts;
getopts('hdve:f:l:m:r:',\%opts);

my $gzfile     = $opts{f};
my $export_dir = $opts{e};
my $listfile   = $opts{l};
my $maxfiles   = $opts{m} || 1000;
my $repo_path  = $opts{r} || '';
my $verbose    = $opts{v};
my $dry_run    = $opts{d};

help_exit() if $opts{h};
help_exit() if not ($gzfile || $listfile);

if ($gzfile) {
    process_file($gzfile,$export_dir,$repo_path,$dry_run,$verbose);
}

if ($listfile) {
    open my $lh, $listfile or "die Cannot open listfile: $!\n";
    while (my $gzfile = <$lh>) {
        chomp $gzfile;
        # Fetch up to $maxfiles in inbox
        if ($maxfiles) {
        my $inbox_count = inbox_count($export_dir,'.+\.eml');
        if ($inbox_count > $maxfiles) {
            my $waitfactor = $inbox_count - $maxfiles;
            my $waitnext = $waitfactor * 0.5;
            select(undef,undef,undef,$waitnext);
        }
    }

        process_file($gzfile,$export_dir,$repo_path,$dry_run,$verbose);
    }
    close $lh;
    exit;
}

help_exit();

### SUBS ####

### process_file
sub process_file
{
    my ($gzfile,$export_dir,$repo_path,$dry_run,$verbose) = @_;

    my $benno_hash;
    my $sender;
    my @recipient_headers;

    verbose("Read $gzfile");
    my $hash_re      = qr/^===== Hash:\s(.+)$/;
    my $sender_re    = qr/^Sender:.+?(\S+\@\S+)/;
    my $recipient_re = qr/^Recipient:.+?(\S+\@\S+)/;
    my $defective_re = qr/Defective: YES/;

    if ($export_dir) {
        if (! -d $export_dir) {
            print STDERR "No directory: $export_dir\n";
            exit 1;
        }
    }

    # uncompress file to pipe
    open(FILE, "gzip -c -d $gzfile|") || print STDERR "Cannot unzip file. $!\n";

    my ($fileprefix) = $gzfile =~ /^(.+?)\.gz$/;

    my $repopath_re = qr/^$repo_path/;
    $fileprefix =~ s/$repopath_re// if $repo_path;
    $fileprefix =~ s/\///g;          # remove slashes

    my $tmpfile = $export_dir.'/'.$fileprefix.'.tmp';
    my $outfile = $export_dir.'/'.$fileprefix.'.eml';
    $outfile =~ s!\/\/!\/!g;    # multi slashes

    if (!$dry_run) {
        open(TMPF, ">$tmpfile") || print STDERR "Cannot open : $!\n";
    }

    my $error;
    my $sender_set;
    my $recipient_set;
    foreach my $line (<FILE>) {
        if ((!$benno_hash) && ($line =~ $defective_re)) {
            print STDERR "DEFECTIVE: $gzfile\n";
        }

        if ($line =~ $sender_re)    { $sender = $1; $sender_set = 1; }
        if ($line =~ $recipient_re) {
            push @recipient_headers, $1;
            $recipient_set = 1;
        }

        if ($line =~ $hash_re) {
            $benno_hash = $1;

            my @recipients;
            foreach my $address (@recipient_headers) {
                $address =~ s/[<>]//g;
                push @recipients,$address;
            }

            if (!$dry_run) {
                print TMPF "X-REAL-MAILFROM: $sender\n";
                foreach my $recipient (@recipients) {
                    print TMPF "X-REAL-RCPTTO: $recipient\n";
                }
            }

            verbose("Checksum: $benno_hash");
            verbose("Sender: $sender");
            verbose("Recipients: @recipients");
            next;
        }
        if(!$benno_hash) { next; }

        if(!$dry_run)    { print TMPF $line; }
    }

    unless ($sender_set) {
        print STDERR "NO_SENDER: $gzfile\n";
        if (!$dry_run) {
            close TMPF or warn "Cannot close $tmpfile. $!\n";
            unlink $tmpfile;
        }
        return 1;
    }


    if (!$dry_run) {
        close TMPF or warn "Cannot close $tmpfile. $!\n";
        if (link($tmpfile, $outfile)) {
            unlink $tmpfile;
        }
        else {
            print STDERR "Cannot link to outfile $outfile. $!\n";
        }
    }
    print "Write $outfile\n";
}


### 
#
# check number of inboxfiles
#
sub inbox_count
{
    my ($inboxdir,$filepattern) = @_;
    my $counter = 0;

    opendir INBOXDIR, $inboxdir or die "Cannto open $inboxdir: $!";
    while (my $filename = readdir INBOXDIR) {
        next unless $filename =~ /^$filepattern$/;
        $counter++;
    }
    close INBOXDIR;
    return $counter;
}


### verbose
sub verbose
{
    my $msg = shift;
    if ($verbose) {
        print $msg, "\n";
    }
}

### help_exit()
sub help_exit
{
    print "Usage: $0 [-h] [-d] [-v] [-e <export directory] [-f <benno file>|-l <filelist>]\n";
    print "\n";
    print "    -e            export files to this directory\n";
    print "    -r            strip repository path from filename\n";
    print "    -f            benno file\n";
    print "    -l <filelist> read filenames from file\n";
    print "    -m <num>      max. files in inbox\n";
    print "    -d            dry run\n";
    print "    -v            verbose\n";
    print "\n";

    exit 1;
}
