#!/usr/bin/perl -w
use strict;
use MIME::Parser;
use Getopt::Std;

my $logfile='mailparser.log';
my $attachdir='/tmp';
my $counter = 1;
my $separator = "X-Mozilla-Status"; #"From \- ";
my (%message,%opts,$message);
my $debug = 5;

getopts('hmo:',\%opts);

if ($opts{'h'}) {
	help();
	exit;
}

if ($opts{'o'}) {
	$attachdir = $opts{'o'};
}
else {
	my $log = "No output directory specified. will save attachments to $attachdir";
	print "$log\n" if ($debug > 4);
	logit($log);
}

while (<STDIN>) {
	if ($opts{'m'}) {
                if ($_ =~ $separator) {
			$counter++;
			print "Found separator \"$separator\" in stream. Mails parsed: $counter\r" if ($debug > 5);
	        }
                else {
                        $message{$counter} .= $_;
                }
	}
	else { 
		$message{$counter} .= $_;
	}
}
print "parsed $counter mails\n" if ($debug > 5);
foreach my $count (keys %message) {
        parse($message{$count});
}

exit;

sub parse {
	my $message = shift;
	my $parser=new MIME::Parser;
	$parser->ignore_errors(1);
	$parser->extract_uuencode(1);
	$parser->tmp_recycling(0);
	$parser->output_to_core(1);
	my $entity=$parser->parse_data($message);

	my $from=$entity->head->get('From');
	my $subject=$entity->head->get('Subject');
	my @parts=$entity->parts;
	my $defaultname='attachment001';
	chomp ($from,$subject);
	while(my $part = shift(@parts)) {
		if($part->parts) {
			push @parts,$part->parts;
			next;
		}
		my $type=$part->head->mime_type || $part->head->effective_type;
		if($type !~ /^(text|message)/i) {
			my $filename=$part->head->recommended_filename || $defaultname;
			$defaultname++;
			my $data=$part->open("r");
			$filename =~ s/[;<>*|`&\$!#\(\)\[\]\{\}:'"\n]//g;
			if (-e "$attachdir/$filename") {
				logit ("File: $filename already exists. Not overwritten");
			}
			else {
				saveit ($data,$filename);
				logit ("Saved file: $filename  From: $from  Subject: $subject");		
			}
			$data->close;
		}
	}
}

sub logit {
	my $log = shift;
	open(LOG,">> $logfile") || die $_;
	print localtime()." $log\n" if ($debug > 5);
	print LOG localtime()." $log\n";
} 

sub saveit {
	my $data = shift;
	my $filename = shift;
	open(FILE,"> $attachdir/$filename") || die $_;
	my $buf;
		while($data->read($buf,1024)) {
		print FILE $buf;
	}
	close(FILE);
}

sub help {
	print <<eof
	-h : This help
	-m : Inputfile consists of multiple mails (Separator is "From \- " to match Mozillas save format. You may want to modify this)
	-o : Specifies output directory (default is /tmp)
 
	this script parses mails or files from STDIN 
	and writes attachments to files.
eof
}

