August 11, 2010 – 6:04 pm
At a place I go to everyday I have a need to strip attachments out of emails to a certain address.
There are some easy ways to do it with PHP, but they involve continually querying an IMAP server. I didn't want to do that, I wanted to work with them as they were received by the mail server.
I came up with a method using Perl's Mail::Audit, Procmail, and mpack/munpack.
I've zipped all of the files mentioned below into one convenient archive, click this to get a copy.
To Begin:
Install Mail::Audit
Install mpack
The version of mpack I linked works alright on Fedora 8, 9, 10, and 11, if it doesn't work for you, you can Google for your own OS, just make sure the package includes munpack.
You probably already have Procmail and Perl.
Create a user that will receive the mail.
Place the .procmailrc file in the user's home directory. Change /your/home/directory/ to your user's home directory.
Place demo_mail_audit.pl in the user's home directory. Edit the file and change $base_dir to be your user's home directory.
Place list_attachments.php in the user's home directory. Edit the file and change $base_dir to be your user's home directory.
Then:
cd /your/home/directory
mkdir mail_temp attachment_temp
chmod 777 mail_temp attachment_temp
touch attachment.log
chmod 666 attachment.log
chmod 755 list_attachments.php demo_mail_audit.pl
Then send the user you made a message with an attachment.
- Procmail will get the email from sendmail (or whatever) and pass it to demo_mail_audit.pl.
- demo_mail_audit.pl will write the message as a text file to /your/home/directory/mail_temp and call list_attachments.php.
- list_attachments.php will run munpack on the text file from the previous step, stripping the attachments and placing them in /your/home/directory/attachment_temp
- list_attachments.php will then loop through the attachment_temp directory and print what it finds to /your/home/directory/attachment.log.
Now you can take list_attachments.php and modify it for your needs. Have it copy the files to another place on disk, insert them into a DB, whatever!
Wall of code:
#!/usr/bin/perl
#
# demo_mail_audit.pl
#
use Mail::Audit;
$base_dir = "/home/dictations";
$attachment_temp = "$base_dir/attachment_temp";
$mail_temp = "$base_dir/mail_temp";
chdir($base_dir);
my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year = $year + 1900;
$mon = $mon + 1;
if($mday < 10) { $mday = "0$mday"; }
if($mon < 10) { $mon = "0$mon"; }
if($min < 10) { $min = "0$min"; }
if($hour < 10) { $hour = "0$hour"; }
my $did = "$year$mon$mday$hour$min$sec";
$temp_file = "$mail_temp/$did.txt";
sub logger {
$message = $_[0];
my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year = $year + 1900;
$mon = $mon + 1;
if($mday < 10) { $mday = "0$mday"; }
if($mon < 10) { $mon = "0$mon"; }
if($min < 10) { $min = "0$min"; }
if($hour < 10) { $hour = "0$hour"; }
my $did = "$year$mon$mday $hour:$min";
open(LOG, ">>attachment.log");
my $to_log = "perl: $did - $message\n";
print LOG "$to_log";
close(LOG);
return($to_log);
}
my $item = Mail::Audit->new;
my $from = $item->from();
study $from;
my $to = $item->to();
my $cc = $item->cc();
my $subject = $item->subject();
chomp($from, $to, $subject);
logger("=================================================================================");
logger("New Message From: $from, Subj: $subject");
logger("Writing $temp_file");
$item->accept($temp_file, { noexit => 1 });
$php_script = "$base_dir/list_attachments.php $temp_file";
logger("Handing off: $php_script");
system($php_script);
<?PHP
#
# list_attachments.php
#
$base_dir = "/home/dictations";
error_reporting(0);
function logger($message) {
global $base_dir;
$now_time = date("Ymd G:i:s");
$fh = fopen("$base_dir/attachment.log", 'a') or die("can't open file");
fwrite($fh, "php : $now_time - $message\n");
fclose($fh);
}
$file = $argv[1];
if(!$file) {
logger("Called without a file.");
exit;
}
logger("Called: $file");
chdir("$base_dir/attachment_temp");
$t = `munpack $file`;
chdir($base_dir);
logger($t);
$i = 0;
if($handle = opendir("$base_dir/attachment_temp")) {
while(false !== ($file = readdir($handle))) {
if($file != "." && $file != "..") {
$i++;
logger("$base_dir/attachment_temp/$file");
}
}
closedir($handle);
}
logger("Saw $i attachments.");
?>
Posted in Code | 3 Comments »