#! /usr/bin/perl 
#
# 
# parse out mime attachments and dump to a directory

#warnings are usually helpful
use strict;

use MIME::Parser;
use MIME::Entity;
use File::Basename;
use File::Copy;
use Digest::MD5 qw(md5 md5_hex);


use Sys::Syslog;



my $filename;

my $line;
my $output_filename;
my $payload_dir;
my $entity;
my $attachment_filename;
my $attachment_dirname;
my $i;
my $part;
my $email_size;
my $attachment_size;
my $attachment_hash;
my $transfer_encoding;
my $mime_type;
my $effective_mime_type;
my $mime_index;
my $attachment_path;
my $payload_path;
my $log_entry;

my $unlink_email = 1;


my $parser = new MIME::Parser;
openlog("MIME", "ndelay,pid", "local2");



if ( @ARGV > 0 )
{
	$payload_dir = $ARGV[0];
	$parser->output_dir($payload_dir);
}


while(<STDIN>)
{
	$filename = $_;
	chomp($filename);
	
	$email_size = -s $filename;		
		
	$entity = $parser->parse_open($filename);
	
	#$entity->dump_skeleton();
		
	$mime_index = 0;
	foreach $part ($entity->parts_DFS())
	{
				
		
		
		$transfer_encoding = $part->head->get('Content-Transfer-Encoding');
		chomp($transfer_encoding);
		
		if (!($transfer_encoding))
		{
			$transfer_encoding = "-";
		}
		
		$mime_type = $part->mime_type();
		if (!($mime_type))
		{
			$mime_type = "-";
		}
		
		$effective_mime_type = $part->effective_type();
		if (!($effective_mime_type))
		{
			$effective_mime_type = "-";
		}
				
		$payload_path = $payload_dir."/".basename($filename)."_mime-".$mime_index;
		
		if ($part->bodyhandle)
		{
			$attachment_filename = basename($part->bodyhandle->path);
			$attachment_dirname = dirname($part->bodyhandle->path);
			$attachment_size = -s $part->bodyhandle->path;
			$attachment_path = $part->bodyhandle->path;
			
		
			if (open(PAYLOAD_FILE, $attachment_path))
                        {
                            binmode(PAYLOAD_FILE);
                            $attachment_hash = Digest::MD5->new->addfile(*PAYLOAD_FILE)->hexdigest;
                            close(PAYLOAD_FILE);
                        } else
                        {
                            warn("couldn't open attachment for hashing: ".$attachment_filename);
                            $attachment_hash = "-";
                        }
				
			#($effective_mime_type eq "application/pdf")
			#if ( ($attachment_filename =~ m/\.zip$/) )
			#{
				move( $attachment_path , $payload_path ) or warn ("Couldn't copy $attachment_path to $payload_path");		
			#}
		
			
		
		
			print($payload_path."\n");
		
		
		} else
		{
			$attachment_filename = "-";
			$attachment_size = "-";
			$attachment_hash = "-";
		}
		
		
		#print the log here.
		$log_entry = basename($payload_path)." ".$email_size." ".$attachment_hash." ".$transfer_encoding." ".$mime_type." ".$effective_mime_type." ".$attachment_size." ".$attachment_filename; 
		syslog("info", "%s", $log_entry);		
		
		
		
		$mime_index++;
	}


	#$parser->filer->purge();

	#purge the temp files
	
	
	if ( $unlink_email )
	{
		unlink($filename);
	}
		
	
	#if ($attachment_dirname)
	#{
	#	rename($attachment_dirname,dirname($attachment_dirname)."/".$filename);	
	#}
}





#recusively infer the output directory, if any
#this doesn't return the actual directory but one of the extracted attachments. you should run dirname() on return of this.
sub find_output_dir
{
	my ($local_entity) = shift();
	my $dirname;
	my $part;
	
	if ($local_entity->bodyhandle)
	{
		return $local_entity->bodyhandle->path;
	}
	
	
	foreach $part ($local_entity->parts())
	{
		$dirname = find_output_dir($part);
		if ($dirname)
		{
			return $dirname;
		}
	}
	return undef;	
}

