#!/usr/bin/perl
#
#
#
use strict;
use Getopt::Std;
use Sys::Syslog;
use File::Temp;
use Benno;
no warnings 'utf8';

$main::VERSION = '2.8.0';

our(%opts);
getopts('dhvVc:e:g:i:R:s:',\%opts);

if ($opts{V}) { print "$main::VERSION\n"; exit; }

my %conf = Benno->config($opts{c}) if $opts{c};

my $delete          = $opts{d};
my $emailregex      = $opts{E} || $conf{emailregex}   || '^.+\.eml$';
my $gwheader        = $opts{g};
my $inbox           = $opts{i} || $conf{inbox}        || '/srv/benno/inbox';
my $runuser         = $opts{R} || $conf{runuser}      || 'benno';
my $spooldir        = $opts{s};
my $verbose         = $opts{v};
my $version         = $opts{V};

$inbox    =~ s!/$!!;
$spooldir =~ s!/$!!;

help_exit() if $opts{h};
if ($version) {
    print "Version $main::VERSION\n";
    exit;
}

Benno->run_as($runuser);
openlog('benno-copy2inbox','nowait,pid','mail');

my $importfile;
## READ FROM STDIN AND EXIT ####################################################
unless ($spooldir) {
    my $msg = "Read files from STDIN\n";
    syslog('INFO',$msg);
    print "$msg\n" if $verbose;

    eval {
        $importfile = copy2inbox($inbox,'--');
        syslog('INFO',"Email archived: $importfile");
        print "Email archived: $importfile\n" if $verbose;
    };
    if ($@) {
        my $err = $@;
        syslog('ERR',"Cannot copy file: $err");
        print "Cannot copy file: $err";
    } 
    closelog;
    exit;
}
## /READ FROM STDIN AND EXIT ###################################################


## READ FILES FROM DIRECTORY ###################################################
my $msg = "Read files from \"$spooldir\"";
$msg .= ' and delete after sent'    if $delete;

syslog('INFO',$msg);
print "$msg\n" if $verbose;

# read directory and process files
opendir my $dh, $spooldir or die "Cannot read directory \"$spooldir\": $!";
my $return;
foreach my $filename (readdir $dh) {
    next if $filename =~ /^\./;
    next if $filename !~ /$emailregex/;
    chomp $filename;
    my $file = "$spooldir/$filename";

    eval {
        $importfile = copy2inbox($inbox,$file,$gwheader);
        syslog('INFO',"Email \"$filename\" archived: $importfile");
        print "Email \"$filename\" archived: $importfile\n" if $verbose;
    };
    if ($@) {
        my $err = $@;
        syslog('ERR',"Cannot process file \"$file\": $err");
        print "Cannot process file \"$file\": $err";
        next;
    } 
    unlink $file if $delete;
    print "Delete $file from $spooldir.\n" if ($verbose && $delete);
}
closedir $dh;
closelog;
## /READ FILES FROM DIRECTORY ##################################################



### SUBS ###

### copy2inbox
sub copy2inbox
{
    my ($inbox,$filename,$gwheader) = @_;

    my ($tmpfile, $infh, $outfh, $emlfile);
    eval 
    {
        local $/ = undef;
        if ($filename eq '--') {
            $infh  = \*STDIN;
            my $outfh = new File::Temp('copy2inbox_XXXXXXXXXX',
                                        DIR => $inbox,
                                        SUFFIX => '.tmp');
            $tmpfile = $outfh->filename;
        }
        else {
            open $infh, $filename or die "Error read $filename: $!\n";
            my ($basename) = $filename =~ m!.*?([^/]+?)$!;
            $tmpfile = $inbox.'/'.$basename.'.tmp';
            open $outfh, ">",$tmpfile or die "Cannot open temporary file $tmpfile: $!\n";
        }

        ($emlfile = $tmpfile) =~ s/(\.tmp$)/.eml/;
        $emlfile =~ s/\.eml\.eml$/.eml/;
        if (-f $emlfile) {
            die "Target $emlfile exists. Abort.\n";
        }
        if ($gwheader) {
            $gwheader =~ s/^X-BENNO-GW:\s?//i;
            print $outfh "X-BENNO-GW: $gwheader\r\n";
        }
        while (my $line = <$infh>) {
            print $outfh $line;
        }
        close $infh; close $outfh;

        link $tmpfile, $emlfile or die "Rename error: $! $tmpfile\n";
        unlink $tmpfile or die "Cannot unlink $tmpfile: $!\n";
    };
    if ($@) {
        close $infh; close $outfh;
        die $@;
    }

    return $emlfile;
}



###
# read configuration from file
#
sub read_config
{
  my $configfile = shift;
  my %config;
  # _very_ simple config file parser
  #
  # Config format:   var = val
  #
  open CONF, "$configfile" or die "Cannot open config file $configfile. $!\n";
  foreach my $line (<CONF>) {
      next if $line =~ /^$/;
      next if $line =~ /^#/;
      chomp $line;
      my ($var,$val) = split(/=/, $line,2);
      # strip ws
      $var =~ s/\s//g;
      $val =~ s/^\s+//g;
      $val =~ s/\s+$//g;
      $config{$var} = $val;
  }
  close CONF;
  return %config;
}


### print help and exit
sub help_exit
{
    my $msg = shift;

    if ($msg) {
        print $msg,"\n\n";
    }

    print "Usage: $0 [-h] [<options>]\n";
    print "\n";
    print "\n";
    print "     -c <configfile> configuration file\n";
    print "     -i <inbox>      inboxdir (default /srv/benno/inbox)\n";
    print "     -s <spooldir>   read mails from spooldir (or STDIN if not set)\n";
    print "     -e <regex>      email filename regex (default: '^.+\.eml')\n";
    print "     -d              delete mail after import\n";
    print "\n";
    print "     -g <GW-HEADER>  add X-BENNO-GW header with value\n";
    print "\n";
    print "     -V              print version\n";
    print "     -v              verbose\n";
    print "     -h              print this help\n";
    print "\n";
    
    exit 1;
}


### EOP ###
1;


__END__

