diff --git a/examples/get_and_parse_unseen_emails_save_attachments_one_by_one.php b/examples/get_and_parse_unseen_emails_save_attachments_one_by_one.php new file mode 100644 index 00000000..dcd800b0 --- /dev/null +++ b/examples/get_and_parse_unseen_emails_save_attachments_one_by_one.php @@ -0,0 +1,90 @@ + + */ + + require_once __DIR__ . '/../vendor/autoload.php'; + use PhpImap\Mailbox; + use PhpImap\Exceptions\ConnectionException; + + $mailbox = new Mailbox( + '{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder + 'some@gmail.com', // Username for the before configured mailbox + '*********' // Password for the before configured username + ); + + try { + $mail_ids = $mailbox->searchMailbox('UNSEEN'); + } catch(ConnectionException $ex) { + die("IMAP connection failed: " . $ex->getMessage()); + } catch (Exception $ex) { + die("An error occured: " . $ex->getMessage()); + } + + foreach ($mail_ids as $mail_id) { + echo "+------ P A R S I N G ------+\n"; + + $email = $mailbox->getMail( + $mail_id, // ID of the email, you want to get + false // Do NOT mark emails as seen (optional) + ); + + echo "from-name: " . (isset($email->fromName)) ? $email->fromName : $email->fromAddress . "\n"; + echo "from-email: " . $email->fromAddress . "\n"; + echo "to: " . $email->to . "\n"; + echo "subject: " . $email->subject . "\n"; + echo "message_id: " . $email->messageId . "\n"; + + echo "mail has attachments? "; + if ($email->hasAttachments()) { + echo "Yes\n"; + } else { + echo "No\n"; + } + + if (! empty($email->getAttachments())) { + echo count($email->getAttachments()) . " attachements\n"; + } + + // Save attachments one by one + if (! $mbox_connection->getAttachmentsIgnore()) { + $attachments = $email_content->getAttachments(); + + foreach ($attachments as $attachment) { + echo "--> Saving " . $attachment->name . "..."; + + // Set individually filePath for each single attachment + // In this case, every file will get the current Unix timestamp + $attachment->setFilePath(__DIR__.'/files/'.time()); + + if ($attachment->saveToDisk()) { + echo "OK, saved!\n"; + } else { + echo "ERROR, could not save!\n"; + } + } + } + + if ($email->textHtml) { + echo "Message HTML:\n" . $email->textHtml; + } else { + echo "Message Plain:\n" . $email->textPlain; + } + + if (!empty($email->autoSubmitted)) { + // Mark email as "read" / "seen" + $mailbox->markMailAsRead($mail_id); + echo "+------ IGNORING: Auto-Reply ------+\n"; + } + + if (!empty($email_content->precedence)) { + // Mark email as "read" / "seen" + $mailbox->markMailAsRead($mail_id); + echo "+------ IGNORING: Non-Delivery Report/Receipt ------+\n"; + } + } + + $mailbox->disconnect(); \ No newline at end of file diff --git a/src/PhpImap/DataPartInfo.php b/src/PhpImap/DataPartInfo.php index cbfb89a4..d4585043 100644 --- a/src/PhpImap/DataPartInfo.php +++ b/src/PhpImap/DataPartInfo.php @@ -31,10 +31,6 @@ public function __construct($mail, $id, $part, $encoding, $options) public function fetch() { - if (isset($this->data)) { - return $this->data; - } - if (0 == $this->part) { $this->data = $this->mail->imap('body', [$this->id, $this->options]); } else { @@ -66,8 +62,12 @@ public function fetch() break; } - if (isset($this->charset) and !empty($this->charset)) { - $this->data = $this->mail->convertStringEncoding($this->data, $this->charset, $this->mail->getServerEncoding()); + if (isset($this->charset) and !empty(trim($this->charset))) { + $this->data = $this->mail->convertStringEncoding( + $this->data, // Data to convert + $this->charset, // FROM-Encoding (Charset) + $this->mail->getServerEncoding() // TO-Encoding (Charset) + ); } return $this->data; diff --git a/src/PhpImap/IncomingMailAttachment.php b/src/PhpImap/IncomingMailAttachment.php index 66966f8b..3e40980d 100644 --- a/src/PhpImap/IncomingMailAttachment.php +++ b/src/PhpImap/IncomingMailAttachment.php @@ -46,31 +46,28 @@ public function __get($name) return $this->filePath; } + /** + * Sets the file path. + * + * @param string $filePath File path incl. file name and optional extension + * + * @return void + */ public function setFilePath($filePath) { $this->file_path = $filePath; } - public function addDataPartInfo(DataPartInfo $dataInfo) - { - $this->dataInfo = $dataInfo; - } - /** - * Saves the attachment object on the disk. + * Sets the data part info. + * + * @param DataPartInfo $dataInfo Date info (file content) * - * @return bool True, if it could save the attachment on the disk + * @return void */ - public function saveToDisk() + public function addDataPartInfo(DataPartInfo $dataInfo) { - if (false === file_put_contents($this->filePath, $this->dataInfo->fetch())) { - unset($this->filePath); - unset($this->file_path); - - return false; - } - - return true; + $this->dataInfo = $dataInfo; } /** @@ -92,10 +89,33 @@ public function getMimeType() } /** + * Gets the file content. + * * @return string */ public function getContents() { return $this->dataInfo->fetch(); } + + /** + * Saves the attachment object on the disk. + * + * @return bool True, if it could save the attachment on the disk + */ + public function saveToDisk() + { + if (is_null($this->dataInfo)) { + return false; + } + + if (false === file_put_contents($this->filePath, $this->dataInfo->fetch())) { + unset($this->filePath); + unset($this->file_path); + + return false; + } + + return true; + } } diff --git a/src/PhpImap/Mailbox.php b/src/PhpImap/Mailbox.php index 3dda98de..a5f2d730 100644 --- a/src/PhpImap/Mailbox.php +++ b/src/PhpImap/Mailbox.php @@ -267,7 +267,7 @@ public function setConnectionArgs($options = 0, $retriesNum = 0, $params = null) */ public function setAttachmentsDir($attachmentsDir) { - if (empty($attachmentsDir)) { + if (empty(trim($attachmentsDir))) { throw new InvalidParameterException('setAttachmentsDir() expects a string as first parameter!'); } if (!is_dir($attachmentsDir)) { @@ -408,7 +408,7 @@ protected function initImapStream() if (!$imapStream) { $lastError = imap_last_error(); - if (!empty($lastError)) { + if (!empty(trim($lastError))) { // imap error = report imap error throw new Exception('IMAP error: '.$lastError); } else { @@ -716,16 +716,16 @@ public function getMailsInfo(array $mailsIds) $mails = $this->imap('fetch_overview', [implode(',', $mailsIds), (SE_UID == $this->imapSearchOption) ? FT_UID : 0]); if (\is_array($mails) && \count($mails)) { foreach ($mails as &$mail) { - if (isset($mail->subject) and !empty($mail->subject)) { + if (isset($mail->subject) and !empty(trim($mail->subject))) { $mail->subject = $this->decodeMimeStr($mail->subject, $this->getServerEncoding()); } - if (isset($mail->from) and !empty($mail->from)) { + if (isset($mail->from) and !empty(trim($mail->from))) { $mail->from = $this->decodeMimeStr($mail->from, $this->getServerEncoding()); } - if (isset($mail->sender) and !empty($mail->sender)) { + if (isset($mail->sender) and !empty(trim($mail->sender))) { $mail->sender = $this->decodeMimeStr($mail->sender, $this->getServerEncoding()); } - if (isset($mail->to)) { + if (isset($mail->to) and !empty(trim($mail->to))) { $mail->to = $this->decodeMimeStr($mail->to, $this->getServerEncoding()); } } @@ -896,32 +896,32 @@ public function getMailHeader($mailId) $header->precedence = (preg_match("/Precedence\:(.*)/i", $headersRaw, $matches)) ? trim($matches[1]) : ''; $header->failedRecipients = (preg_match("/Failed-Recipients\:(.*)/i", $headersRaw, $matches)) ? trim($matches[1]) : ''; - if (isset($head->date) and !empty($head->date)) { + if (isset($head->date) and !empty(trim($head->date))) { $header->date = self::parseDateTime($head->date); - } elseif (isset($head->Date) and !empty($head->Date)) { + } elseif (isset($head->Date) and !empty(trim($head->Date))) { $header->date = self::parseDateTime($head->Date); } else { $now = new DateTime(); $header->date = self::parseDateTime($now->format('Y-m-d H:i:s')); } - $header->subject = (isset($head->subject) and !empty($head->subject)) ? $this->decodeMimeStr($head->subject, $this->getServerEncoding()) : null; + $header->subject = (isset($head->subject) and !empty(trim($head->subject))) ? $this->decodeMimeStr($head->subject, $this->getServerEncoding()) : null; if (isset($head->from) and !empty($head->from)) { $header->fromHost = isset($head->from[0]->host) ? $head->from[0]->host : (isset($head->from[1]->host) ? $head->from[1]->host : null); - $header->fromName = (isset($head->from[0]->personal) and !empty($head->from[0]->personal)) ? $this->decodeMimeStr($head->from[0]->personal, $this->getServerEncoding()) : ((isset($head->from[1]->personal) and (!empty($head->from[1]->personal))) ? $this->decodeMimeStr($head->from[1]->personal, $this->getServerEncoding()) : null); + $header->fromName = (isset($head->from[0]->personal) and !empty(trim($head->from[0]->personal))) ? $this->decodeMimeStr($head->from[0]->personal, $this->getServerEncoding()) : ((isset($head->from[1]->personal) and (!empty(trim($head->from[1]->personal)))) ? $this->decodeMimeStr($head->from[1]->personal, $this->getServerEncoding()) : null); $header->fromAddress = strtolower($head->from[0]->mailbox.'@'.$header->fromHost); } elseif (preg_match('/smtp.mailfrom=[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}/', $headersRaw, $matches)) { $header->fromAddress = substr($matches[0], 14); } if (isset($head->sender) and !empty($head->sender)) { $header->senderHost = isset($head->sender[0]->host) ? $head->sender[0]->host : (isset($head->sender[1]->host) ? $head->sender[1]->host : null); - $header->senderName = (isset($head->sender[0]->personal) and !empty($head->sender[0]->personal)) ? $this->decodeMimeStr($head->sender[0]->personal, $this->getServerEncoding()) : ((isset($head->sender[1]->personal) and (!empty($head->sender[1]->personal))) ? $this->decodeMimeStr($head->sender[1]->personal, $this->getServerEncoding()) : null); + $header->senderName = (isset($head->sender[0]->personal) and !empty(trim($head->sender[0]->personal))) ? $this->decodeMimeStr($head->sender[0]->personal, $this->getServerEncoding()) : ((isset($head->sender[1]->personal) and (!empty(trim($head->sender[1]->personal)))) ? $this->decodeMimeStr($head->sender[1]->personal, $this->getServerEncoding()) : null); $header->senderAddress = strtolower($head->sender[0]->mailbox.'@'.$header->senderHost); } if (isset($head->to)) { $toStrings = []; foreach ($head->to as $to) { - if (!empty($to->mailbox) && !empty($to->host)) { + if (!empty($to->mailbox) && !empty(trim($to->host))) { $toEmail = strtolower($to->mailbox.'@'.$to->host); $toName = (isset($to->personal) and !empty(trim($to->personal))) ? $this->decodeMimeStr($to->personal, $this->getServerEncoding()) : null; $toStrings[] = $toName ? "$toName <$toEmail>" : $toEmail; @@ -933,7 +933,7 @@ public function getMailHeader($mailId) if (isset($head->cc)) { foreach ($head->cc as $cc) { - if (!empty($cc->mailbox) && !empty($cc->host)) { + if (!empty(trim($cc->mailbox)) && !empty(trim($cc->host))) { $ccEmail = strtolower($cc->mailbox.'@'.$cc->host); $ccName = (isset($cc->personal) and !empty(trim($cc->personal))) ? $this->decodeMimeStr($cc->personal, $this->getServerEncoding()) : null; $ccStrings[] = $ccName ? "$ccName <$ccEmail>" : $ccEmail; @@ -944,7 +944,7 @@ public function getMailHeader($mailId) if (isset($head->bcc)) { foreach ($head->bcc as $bcc) { - if (!empty($bcc->mailbox) && !empty($bcc->host)) { + if (!empty(trim($bcc->mailbox)) && !empty(trim($bcc->host))) { $bccEmail = strtolower($bcc->mailbox.'@'.$bcc->host); $bccName = (isset($bcc->personal) and !empty(trim($bcc->personal))) ? $this->decodeMimeStr($bcc->personal, $this->getServerEncoding()) : null; $bccStrings[] = $bccName ? "$bccName <$bccEmail>" : $bccEmail; @@ -955,7 +955,7 @@ public function getMailHeader($mailId) if (isset($head->reply_to)) { foreach ($head->reply_to as $replyTo) { - if (!empty($replyTo->mailbox) && !empty($replyTo->host)) { + if (!empty(trim($replyTo->mailbox)) && !empty(trim($replyTo->host))) { $replyToEmail = strtolower($replyTo->mailbox.'@'.$replyTo->host); $replyToName = (isset($replyTo->personal) and !empty(trim($replyTo->personal))) ? $this->decodeMimeStr($replyTo->personal, $this->getServerEncoding()) : null; $replyToStrings[] = $replyToName ? "$replyToName <$replyToEmail>" : $replyToEmail; @@ -1032,7 +1032,7 @@ protected function initMailPart(IncomingMail $mail, $partStructure, $partNum, $m $params = []; if (!empty($partStructure->parameters)) { foreach ($partStructure->parameters as $param) { - $params[strtolower($param->attribute)] = (!isset($param->value) || empty($param->value)) ? '' : $this->decodeMimeStr($param->value); + $params[strtolower($param->attribute)] = (!isset($param->value) || empty(trim($param->value))) ? '' : $this->decodeMimeStr($param->value); } } if (!empty($partStructure->dparameters)) { @@ -1082,7 +1082,7 @@ protected function initMailPart(IncomingMail $mail, $partStructure, $partNum, $m $attachment = self::downloadAttachment($dataInfo, $params, $partStructure, $mail->id, $emlParse); $mail->addAttachment($attachment); } else { - if (!empty($params['charset'])) { + if (isset($params['charset']) AND !empty(trim($params['charset']))) { $dataInfo->charset = $params['charset']; } } @@ -1105,7 +1105,9 @@ protected function initMailPart(IncomingMail $mail, $partStructure, $partNum, $m if (TYPETEXT === $partStructure->type) { if ('plain' == strtolower($partStructure->subtype)) { $mail->addDataPartInfo($dataInfo, DataPartInfo::TEXT_PLAIN); - } else { + } elseif (! $partStructure->ifdisposition) { + $mail->addDataPartInfo($dataInfo, DataPartInfo::TEXT_HTML); + } elseif ('attachment' != strtolower($partStructure->disposition)) { $mail->addDataPartInfo($dataInfo, DataPartInfo::TEXT_HTML); } } elseif (TYPEMESSAGE === $partStructure->type) { @@ -1125,16 +1127,16 @@ protected function initMailPart(IncomingMail $mail, $partStructure, $partNum, $m * * @return IncomingMailAttachment[] $attachment */ - public function downloadAttachment($dataInfo, $params, $partStructure, $mailId, $emlOrigin = false) + public function downloadAttachment(DataPartInfo $dataInfo, $params, $partStructure, $mailId, $emlOrigin = false) { if ('RFC822' == $partStructure->subtype && isset($partStructure->disposition) && 'attachment' == $partStructure->disposition) { $fileExt = strtolower($partStructure->subtype).'.eml'; } elseif ('ALTERNATIVE' == $partStructure->subtype) { $fileExt = strtolower($partStructure->subtype).'.eml'; - } elseif (empty($params['filename']) && empty($params['name'])) { + } elseif (!isset($params['filename']) OR empty(trim($params['filename'])) && (!isset($params['name']) OR empty(trim($params['name'])))) { $fileExt = strtolower($partStructure->subtype); } else { - $fileName = !empty($params['filename']) ? $params['filename'] : $params['name']; + $fileName = (isset($params['filename']) AND !empty(trim($params['filename']))) ? $params['filename'] : $params['name']; $fileName = $this->decodeMimeStr($fileName, $this->getServerEncoding()); $fileName = $this->decodeRFC2231($fileName, $this->getServerEncoding()); } @@ -1153,9 +1155,12 @@ public function downloadAttachment($dataInfo, $params, $partStructure, $mailId, $attachment->id = $attachmentId; $attachment->contentId = $partStructure->ifid ? trim($partStructure->id, ' <>') : null; $attachment->name = $fileName; - $attachment->emlOrigin = $emlOrigin; $attachment->disposition = (isset($partStructure->disposition) ? $partStructure->disposition : null); - $attachment->charset = (isset($params['charset']) and !empty($params['charset'])) ? $params['charset'] : null; + $attachment->charset = (isset($params['charset']) and !empty(trim($params['charset']))) ? $params['charset'] : null; + $attachment->emlOrigin = $emlOrigin; + + $attachment->addDataPartInfo($dataInfo); + if (null != $this->getAttachmentsDir()) { $replace = [ '/\s/' => '_', @@ -1171,7 +1176,6 @@ public function downloadAttachment($dataInfo, $params, $partStructure, $mailId, $filePath = substr($filePath, 0, 255 - 1 - \strlen($ext)).'.'.$ext; } $attachment->setFilePath($filePath); - $attachment->addDataPartInfo($dataInfo); $attachment->saveToDisk(); } @@ -1237,7 +1241,7 @@ protected function decodeRFC2231($string, $charset = 'utf-8') */ public function parseDateTime($dateHeader) { - if (empty($dateHeader)) { + if (empty(trim($dateHeader))) { throw new InvalidParameterException('parseDateTime() expects parameter 1 to be a parsable string datetime'); } @@ -1264,8 +1268,6 @@ public function parseDateTime($dateHeader) * @param string $toEncoding the new charset (encoding) * * @return string Converted string if conversion was successful, or the original string if not - * - * @throws Exception */ public function convertStringEncoding($string, $fromEncoding, $toEncoding) { @@ -1282,24 +1284,24 @@ public function convertStringEncoding($string, $fromEncoding, $toEncoding) $convertedString = mb_convert_encoding($string, $toEncoding, $fromEncoding); } elseif (\function_exists('iconv')) { $convertedString = @iconv($fromEncoding, $toEncoding.'//TRANSLIT//IGNORE', $string); - if (false === $convertedString) { - throw new Exception('Mime string encoding conversion failed'); - } } - if ('' == $convertedString) { + if (('' == $convertedString) OR (false === $convertedString)) { return $string; } return $convertedString; } + /** + * Disconnects from the IMAP server / mailbox. + */ public function __destruct() { $this->disconnect(); } /** - * Gets imappath. + * Gets IMAP path. * * @return string */ @@ -1466,7 +1468,7 @@ public function imap($methodShortName, $args = [], $prependConnectionAsFirstArg */ protected function getCombinedPath($folder, $absolute = false) { - if (empty($folder)) { + if (empty(trim($folder))) { return $this->imapPath; } elseif ('}' === substr($this->imapPath, -1)) { return $this->imapPath.$folder;