<?php
$now = time();
// current time
$mailbox = '{your-mailserver-here/imap/novalidate-cert}INBOX';
// see http://www.php.net/manual/en/function.imap-open.php
$mbox = imap_open($mailbox, 'email-address-here', 'password-here');
// log in to mail server
if (!$mbox) echo ('Failed opening mailbox<br>' . print_r(imap_errors(), true));
// remove the print_r for production use
else{ $box = imap_check($mbox);
// get the inbox
for ($imap_idx = 1; $imap_idx <= $box->Nmsgs; $imap_idx++)
// loop through the messages
{ $headers = imap_headerinfo($mbox, $imap_idx);
// http://www.php.net/manual/en/function.imap-headerinfo.php
$raw_headers = imap_fetchheader($mbox, $imap_idx);
// http://www.php.net/manual/en/function.imap-fetchheader.php
$selected_headers = ''; $text_part = ''; $html_part = '';
$original_message = imap_body($mbox, $imap_idx);
// save the copy of the entire thing, attachments and all
// build selected headers string
for ($ii = 0; $ii < count($headers->from); $ii++) $selected_headers .= 'From: ' . $headers->from[$ii]->mailbox . '@' . $headers->from[$ii]->host . "\n"; for ($ii = 0; $ii < count($headers->to); $ii++) $selected_headers .= 'To: ' . $headers->to[$ii]->mailbox . '@' . $headers->to[$ii]->host . "\n"; for ($ii = 0; $ii < count($headers->cc); $ii++) $selected_headers .= 'Cc: ' . $headers->cc[$ii]->mailbox . '@' . $headers->cc[$ii]->host . "\n"; for ($ii = 0; $ii < count($headers->bcc); $ii++) $selected_headers .= 'Bcc: ' . $headers->bcc[$ii]->mailbox . '@' . $headers->bcc[$ii]->host . "\n"; if (!empty($headers->date)) $selected_headers .= 'Date: ' . $headers->date . "\n"; if (!empty($headers->subject)) $selected_headers .= 'Subject: ' . $headers->subject . "\n";
// see below; getMsg uses global variables
getMsg($mbox, $imap_idx); $text_part = $plainmsg;
// text portion of the email
$html_part = $htmlmsg;
// html portion of the email
// check for text portion first
$msg_text = trim(strip_tags($plainmsg, '<a>'));
if ($msg_text == '') {
// text portion is empty, check html portion
$msg_text = trim($htmlmsg);
if ($msg_text == '') {
// no text or html portion auto-detected, check manually
$msg_text = imap_body($mbox, $imap_idx);
// get the entire raw message
// check for quoted-printable encoding with possible boundary markers and headers at the top
$chunks = explode("\n", trim($msg_text));
if (count($chunks) > 1)
// if there are multiple lines
{ $quoted_printable = false; if (strpos($chunks[0], '--') === 0)
// if the first line is a boundary marker (starts with '--')
{ array_shift($chunks);
// remove the first line
if (strpos($chunks[count($chunks) - 1], '--') === 0)
// check the last line
{ array_pop($chunks);
// remove that too
} } if (strpos(strtolower($chunks[0]), 'content-type') === 0) array_shift($chunks);
// remove the first line if it's a content-type header
if (strpos(strtolower($chunks[0]), 'content-transfer-encoding') === 0) { if (strpos(strtolower($chunks[0]), 'quoted-printable')) $quoted_printable = true;
// this email was sent using quoted-printable encoding
array_shift($chunks);
// remove the content-transfer-encoding header
} $msg_text = implode("\n", $chunks);
// put the remaining lines back together
if ($quoted_printable) $msg_text = quoted_printable_decode($msg_text); $msg_text = utf8_decode($msg_text); } } } $from = trim($headers->from[0]->mailbox . '@' . $headers->from[0]->host); $msgId = isset($headers->message_id) ? trim($headers->message_id) : ''; $time = strtotime($headers->date); if ($time == 0) $time = $now;
/****************************************************** At this point: $headers: the object returned from imap_headerinfo $selected_headers: text of some headers to display to a user checking mail (subject, from, etc) $text_part: the text portion, if found $html_part: the html portion, if found $msg_text: either the text part, html part, or manually-decoded part (this is the variable to use as email body) $original_message: the entire unprocessed email body, includingall parts and any attachments $from: From address $msgId: message ID from the headers $time: email delivery time, as a Unix timestamp $attachments: array of attachments (see below) ******************************************************/
// process attachments
foreach ($attachments as $filename => $data) {
// e.g.
file_put_contents('attachments/' . $filename, $data); }
// flag the email for deletion
imap_delete($mbox, $imap_idx); }
// delete emails and close the mailbox
imap_expunge($mbox); imap_close($mbox);}function getMsg($mbox,$mid) {
// input
$mbox = IMAP stream, $mid = message id
// output all the following:
global $htmlmsg,$plainmsg,$charset,$attachments;
// the message may in $htmlmsg, $plainmsg, or both
$htmlmsg = $plainmsg = $charset = ''; $attachments = array();
// HEADER
$h = imap_header($mbox,$mid);
// add code here to get date, from, to, cc, subject...
// BODY
$s = imap_fetchstructure($mbox,$mid); if (empty($s->parts))
// not multipart
getMsgPart($mbox,$mid,$s,0);
// no part-number, so pass 0
else {
// multipart: iterate through each part
foreach ($s->parts as $partno0=>$p) getMsgPart($mbox,$mid,$p,$partno0+1); }}function getMsgPart($mbox,$mid,$p,$partno) {
// $partno = '1', '2', '2.1', '2.1.3', etc if multipart, 0 if not multipart
global $htmlmsg,$plainmsg,$charset,$attachments;
// DECODE DATA
$data = ($partno)? imap_fetchbody($mbox,$mid,$partno):
// multipart
imap_body($mbox,$mid);
// not multipart
// Any part may be encoded, even plain text messages, so check everything.
if ($p->encoding==4) $data = quoted_printable_decode($data); elseif ($p->encoding==3) $data = base64_decode($data);
// no need to decode 7-bit, 8-bit, or binary
// PARAMETERS
// get all parameters, like charset, filenames of attachments, etc.
$params = array(); if ($p->ifparameters) foreach ($p->parameters as $x) $params[ strtolower( $x->attribute ) ] = $x->value; if ($p->ifdparameters) foreach ($p->dparameters as $x) $params[ strtolower( $x->attribute ) ] = $x->value;
// ATTACHMENT
// Any part with a filename is an attachment,
// so an attached text file (type 0) is not mistaken as the message.
if (!empty($params['filename']) || !empty($params['name'])) {
// filename may be given as 'Filename' or 'Name' or both
$filename = (!empty($params['filename']))? $params['filename'] : $params['name'];
// filename may be encoded, so see imap_mime_header_decode() $attachments[$filename] = $data;
// this is a problem if two files have same name
}
// TEXT
elseif ($p->type==0 && $data) {
// Messages may be split in different parts because of inline attachments,
// so append parts together with blank row.
if ($p->ifsubtype && strtolower($p->subtype)=='plain') $plainmsg .= trim($data) ."\n\n"; else $htmlmsg .= $data ."<br><br>"; $charset = $params['charset'];
// assume all parts are same charset }
// EMBEDDED MESSAGE
// Many bounce notifications embed the original message as type 2,
// but AOL uses type 1 (multipart), which is not handled here.
// There are no PHP functions to parse embedded messages,
// so this just appends the raw source to the main message.
elseif ($p->type==2 && $data) { $plainmsg .= trim($data) ."\n\n"; }
// SUBPART RECURSION
if (!empty($p->parts)) { foreach ($p->parts as $partno0=>$p2) getMsgPart($mbox,$mid,$p2,$partno.'.'.($partno0+1));
// 1.2, 1.2.1, etc.
}}
?>