piping
No way, man, that is fraught with loads of problems.
Try using the imap functions.
Here is the basis of some stuff I’m currently working on. This script is to be used to take email attachments from certain customers that are allowed to send us their inventories via email. I take the attachment, save it in a directory and then insert a record into a database so another cron job can process the attachment.
<?php
$mailpass="mypassword";
$mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
$mailuser="help@mysite.com";
include "libs/database/db_mysql.php";
$db = new Database;
$mailbox=imap_open($mailhost,$mailuser,$mailpass) or die("<br />\
FAILLED! ".imap_last_error());
// The IMAP.xml file contains the email address and user_id of the users that we accept
// their files via email
$xml = simplexml_load_string(file_get_contents('IMAP.xml'));
$result = $xml->xpath('item');
while(list( , $node) = each($result)) {
$email = $node->LI_email;
$user_id = $node->LI_user_id;
$search = "RECENT FROM \\"$email\\"";
$result2 = imap_search($mailbox, $search);
if($result2) {
$index = $result2[0];
$structure = imap_fetchstructure($mailbox, $index);
$attachments = array();
if(isset($structure->parts) && count($structure->parts)) {
for($i = 0; $i < count($structure->parts); $i++) {
$attachments[$i] = array(
'is_attachment' => false,
'filename' => '',
'name' => '',
'attachment' => '');
if($structure->parts[$i]->ifdparameters) {
foreach($structure->parts[$i]->dparameters as $object) {
if(strtolower($object->attribute) == 'filename') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['filename'] = $object->value;
}
}
}
if($structure->parts[$i]->ifparameters) {
foreach($structure->parts[$i]->parameters as $object) {
if(strtolower($object->attribute) == 'name') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['name'] = $object->value;
}
}
}
if($attachments[$i]['is_attachment']) {
$attachments[$i]['attachment'] = imap_fetchbody($mailbox, $index, $i+1, FT_PEEK);
if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}
elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
}
}
} // for($i = 0; $i < count($structure->parts); $i++)
} // if(isset($structure->parts) && count($structure->parts))
// Now add a record into the file_upload table
for($i = 0; $i < count($attachments); $i++) {
if (strlen(trim($attachments[$i]['filename'])) > 0) {
$path_parts = pathinfo($attachments[$i]['filename']);
// Some users zip their inventory files, so we have to unzip them
if(strtolower($path_parts['extension']) == 'zip') {
// copy the zip attachment to the temp dir
$filename = 'file_uploads/temp/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
$fp = fopen($filename, "w");
fwrite($fp, $attachments[$i]['attachment']);
fclose($fp);
// open the zip file
$zip = new ZipArchive();
if ($zip->open($filename) !== TRUE) {
die ('Could not open archive');
}
$zippedfile = $zip->statIndex(0);
$path_parts = pathinfo($zippedfile['name']);
$newfilename = 'file_uploads/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
// extract the parts
$zip->extractTo('file_uploads/', $zippedfile['name']);
$zip->close();
// delete the zip file
unlink($filename);
// I need to rename the file to our naming convention
rename('file_uploads/'.$zippedfile['name'], $newfilename);
$filestr = preg_replace('`[\\r\
]+`',"\
", file_get_contents($newfilename));
$fp = fopen($newfilename, "w+");
fwrite($fp, $filestr);
fclose($fp);
// now process just like regular CSV or delimited files
// remove the directory from the filename
$filename = $user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
// Now insert into file_upload table
$insert_sql = "INSERT INTO `file_uploads` VALUES(NULL,$user_id, '$filename', 0, NOW())";
$db->query($insert_sql) or die("Can't insert record");
} else {
$filename = 'file_uploads/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
$fp = fopen($filename, "w");
$attachments[$i]['attachment'] = preg_replace('`[\\r\
]+`',"\
",$attachments[$i]['attachment']);
fwrite($fp, $attachments[$i]['attachment']);
fclose($fp);
// remove the directory from the filename
$filename = $user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
// Now insert into file_upload table
$insert_sql = "INSERT INTO `file_uploads` VALUES(NULL,$user_id, '$filename', 0, NOW())";
$db->query($insert_sql) or die("Can't insert record:".mysql_error());
}
} // if (strlen(trim($attachments['name'])) > 0
} // for($i = 0; $i < count($attachments); $i++)
// This is a stop gap to circumvent the message being processed twice
imap_setflag_full($mailbox, "$index", "\\Seen \\Flagged");
// Now move the message to completed uploads mailbox
// imap_mail_move copies the message and then sets the deleted flag.
// Won't work with POP3 accounts
// imap_mail_move($mailbox, "$index", "INBOX/completed+uploads") or die("can't move: ".imap_last_error());
// This clear out the deleted messages
// imap_expunge($mailbox);
} // if($result2)
} // while(list( , $node) = each($result))
imap_close($mailbox);
?>
I originally wrote something like this to take scores for a baseball league. The managers sent their scores in using a specific format in the subject and I parsed the scores into our games table. Very clean and functional.