I'm trying to build an email message parser for our site. What I'm eventually going to do is iterate through the messages that have attachments and save the attachment if the message comes from a particular email address.
This is just the initial test, however, I am running into problems, see comments below.
<?php
echo "Loading..."."<br />\n";
$mailuser="help@mysite.com";
echo "User=$mailuser"."<br />\n";;
$mailpass="mypassword";
echo "Pass=$mailpass"."<br />\n";
// had to use this because we have SSL on site and regular port 110 didn't work
$mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
echo "Host=$mailhost"."<br />\n";
$mailbox=imap_open($mailhost,$mailuser,$mailpass) or die("<br />\nFAILLED! ".imap_last_error());
$check = imap_check($mailbox);
// last message parsed will be stored in the file msgcounter.dat
$firstmsg = file_get_contents('msgcounter.dat') + 1;
$lastmsg = $firstmsg+$check->Recent; // should be == last msg index +开发者_如何学Python count of latest messages
echo 'First:'.$firstmsg.' - Last:'.$lastmsg."<br>";
$result = imap_fetch_overview($mailbox,"$firstmsg:$lastmsg");
print_r($result);
foreach ($result as $overview) {
echo "#{$overview->msgno} ({$overview->date}) - From: {$overview->from}
{$overview->subject}\n";
}
// the following approach didn't work either, Kept getting warnings about
// Bad message number
//
// Some messages in the sequence HAVE been deleted.
/*
for ($index = $firstmsg-1; $index <= ($lastmsg); $index++ ) {
if (strlen(trim(imap_fetchheader($mailbox, $index))) > 0) {
echo 'in message index loop:'.$index;
}
}
*/
imap_close($mailbox);
echo "completed.". "<br />\n";;
?>
IMAP is a cesspool of poor standards and worse implementations. If you don't mind a little profanity (or, er, a lot), there's an infamous IMAP rant by a Ruby library dev with some interesting insights.
You should probably consider using someone else's code to do the dirty work.
Ok I have a big part of what I'm trying to do working, now. The only problem I have left is actually moving the message to another "folder". imap_mail_move is not supported on POP3 mailboxes and si I have had to come up with a different way of doing things.
The last problem I have is knowing what message FILE goes with what message that I have just opened. I know I can use the std rename() function to move the file but I found that I can lookup the msgnum in the courierimapuiddb file and the filename will be there.
Here's the code I now have working, with the exception of the moving of the file:
<?php
function showProgressMsg($msg)
{
echo $msg."<br>";
ob_flush();
flush();
usleep(2500);
}
$mailpass="mymailpass";
$mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
$mailuser="help@myserver.com";
include "libs/database/db_mysql.php";
$db = new Database;
$debug=false;
if($_GET['debug']= 'yes') {
$debug = true;
ini_set('output_buffering', 'Off');
ob_start();
}
if($debug) {showProgressMsg('Opening Mailbox');}
$mailbox=imap_open($mailhost,$mailuser,$mailpass) or die("<br />\nFAILLED! ".imap_last_error());
// The IMAP.xml file contains the email address and user_id of the users that we accept
// their files via email
if($debug) {showProgressMsg('Reading IMAP.xml');}
$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\"";
if($debug) {showProgressMsg('Searching for '.$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)) {
if($debug) {showProgressMsg('Handling attachments');}
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']);
if($debug) {showProgressMsg('Processing '.$attachments[$i]['filename']);}
if(strtolower($path_parts['extension']) == 'zip') {
// I am going to do something different with ziped files
$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);
$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'];
$zip->extractTo('file_uploads/', $zippedfile['name']);
$zip->close();
unlink($filename);
rename('file_uploads/'.$zippedfile['name'], $newfilename);
$filestr = preg_replace('`[\r\n]+`',"\n", file_get_contents($newfilename));
$fp = fopen($newfilename, "w+");
fwrite($fp, $filestr);
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_upload` 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\n]+`',"\n",$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_upload` 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++)
// Now move the message to completed uploads mailbox
// imap_mail_move copies the message and then sets the deleted flag.
// Found out that imap_mail_move is unsupported on POP3 accounts
// imap_mail_move($mailbox, "$index", "INBOX/completed+uploads") or die("can't move: ".imap_last_error());
// This is a stop gap to circumvent the message being processed twice
// Found out that this also is not supported by POP3 boxes
if($debug) {showProgressMsg('Setting \Seen flag');}
imap_setflag_full($mailbox, "$index", "\Seen \Flagged");
// This clears out the deleted messages
// imap_expunge($mailbox);
/*
So, I'm going to have to open the courierimapuiddb file and locate the msgnum
then get the filename and use rename() to move the file to the completed uploads
directory.
*/
if($debug) {showProgressMsg(',oving message');}
} // if($result2)
// Now, move the message to completed uploads
} // while(list( , $node) = each($result))
if($debug) {
showProgressMsg('Closing mailbox and cleaning up');
ob_flush();
flush();
ob_end_clean();
ini_set('output_buffering', 4096);
}
imap_close($mailbox);
?>
The problem was that I wasn't checking the imap mailbox in this line:
$mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
This is the correct line to use:
$mailhost="{localhost/imap/ssl/novalidate-cert}";
精彩评论