I'm using IMAP to do some data entry by reading a mailbox. The code works perfectly for almost all emails except for one instance where the attachment's filename contains asterisk (*) character, in such case the code can't grab the file (or more exactly, the PDF attachment is not readable)
The code that I write to fetch email content (including getting PDF attachment) is:
public function fetchBody ($message_num) {
if ($this->imap) {
$body = '';
$body_type = 'text';
$attachments = array();
$structure = imap_fetchstructure($this->imap, $message_num);
//pr($structure);
if (!$structure) {
return false;
} else {
if ($structure->type == 0) {
if (strtolower($structure->subtype) == 'html') {
$body_type = 'html';
}
$body = $this->decodeBody(imap_body($this->imap, $message_num), $structure->encoding, FT_PEEK);
} elseif ($structure->type == 1) {
// Grab the text portion of a multipart email
if (count($structure->parts)) {
foreach ($structure->parts as $i => $part) {
if (strtolower($part->subtype) == 'alternative') {
if (count($part->parts)) {
foreach ($part->parts as $j => $subpart) {
if (strtolower($subpart->subtype) == 'plain' || strtolower($subpart->subtype) == 'text') {
$body = $this->decodeBody(imap_fetchbody($this->imap, $message_num, ($i + 1) . '.' . ($j + 1), FT_PEEK), $subpart->encoding);
}
}
}
} elseif (strtolower($part->subtype) == 'related') {
if (count($part->parts)) {
foreach ($part->parts as $j => $subpart) {
if ( isset($subpart->parts) && count($subpart->parts)) {
foreach ($subpart->parts as $k => $subsubpart) {
if (strtolower($subsubpart->subtype) == 'plain' || strtolower($subsubpart->subtype) == 'text') {
$body = $this->decodeBody(imap_fetchbody($this->imap, $message_num, ($i + 1) . '.' . ($j + 1) . '.' . ($k + 1), FT_PEEK), $subsubpart->encoding);
}
}
}
}
}
} elseif (strtolower($part->subtype) == 'plain' || strtolower($part->subtype) == 'text') {
$body = $this->decodeBody(imap_fetchbody($this->imap, $message_num, $i + 1, FT_PEEK), $structure->encoding);
} else {
CakeLog::write('debug', print_r($part, true));
if (($part->type >= 2 && $part->type <= 7) && (!isset($part->parts))) {
$attachments[] = $this->processAttachment($part, $i);
}elseif (strtolower($part->subtype) == 'mixed' || (count($part->parts) && $part->subtype == 'RFC822')) {
if (count($part->parts)) {
foreach ($part->parts as $j => $subpart) {
if (strtolower($subpart->subtype) == 'plain' || strtolower($subpart->subtype) == 'text') {
$body = $this->decodeBody(imap_fetchbody($this->imap, $message_num, ($i + 1) . '.' . ($j + 1) . '.' . ($k + 1), FT_PEEK), $mixedsubpart->encoding);
}else{
if ($subpart->type >= 2 && $subpart->type <= 7) {
$attachments[] = $this->processAttachment($subpart, $i);
}
}
}
}
}
}
}
}
}
}
$data['body'] = $this->cleanUp($body, $structure);
$data['body_type'] = $body_type;
$data['attachments'] = $attachments;
return $data;
} else {
return false;
}
}
Also, this is the debug output when the code detects attachment's filename contains asterisk characters:
2016-02-19 17:13:46 Debug: stdClass Object
(
[type] => 2
[encoding] => 0
[ifsubtype] => 1
[subtype] => RFC822
[ifdescription] => 0
[ifid] => 0
[lines] => 343
[bytes] => 25561
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 0
[parameters] => stdClass Object
(
)
[parts] => Array
(
[0] => stdClass Object
(
[type] => 3
[encoding] => 3
[ifsubtype] => 1
[subtype] => PDF
[ifdescription] => 1
[description] => *MEA - Invoice No. 91135811 *
[ifid] => 0
[bytes] => 23602
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => name
[value] => *MEA - Invoice No. 91135811 *.pdf
)
)
)
)
)
I can still save all the information (title, filename, etc) to the database though, only the file when saved to the server is unreadable for some reason (see attached photo)
Has anybody come across this situation before?