#!/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 () { 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 |-l ]\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 read filenames from file\n"; print " -m max. files in inbox\n"; print " -d dry run\n"; print " -v verbose\n"; print "\n"; exit 1; }