/** * @param CAccount $oAccount * @param string $sFolderFullNameRaw * @param int $iOffset = 0 * @param int $iLimit = 20 * @param string $sSearch = '' * @param bool $bUseThreads = false * @param array $aFilters = array() * @param string $sInboxUidnext = '' * * @return CApiMailMessageCollection * * @throws CApiInvalidArgumentException */ public function MessageList($oAccount, $sFolderFullNameRaw, $iOffset = 0, $iLimit = 20, $sSearch = '', $bUseThreads = false, $aFilters = array(), $sInboxUidnext = '') { if (0 === strlen($sFolderFullNameRaw) || 0 > $iOffset || 0 >= $iLimit || 999 < $iLimit) { throw new CApiInvalidArgumentException(); } $oMessageCollection = false; $oSettings =& CApi::GetSettings(); $oImapClient =& $this->getImapClient($oAccount, 20, 60 * 2); $oImapClient->FolderExamine($sFolderFullNameRaw); $aList = $this->folderInformation($oImapClient, $sFolderFullNameRaw); $iMessageCount = $aList[0]; $iRealMessageCount = $aList[0]; $iMessageUnseenCount = $aList[1]; $sUidNext = $aList[2]; $oMessageCollection = CApiMailMessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderFullNameRaw; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->Filters = implode(',', $aFilters); $aThreads = array(); $bUseThreadsIfSupported = !!$oSettings->GetConf('WebMail/UseThreadsIfSupported'); if ($bUseThreadsIfSupported) { $bUseThreadsIfSupported = $bUseThreads; } $oMessageCollection->FolderHash = $aList[3]; $bSearch = false; if (0 < $iRealMessageCount) { $bIndexAsUid = false; $aIndexOrUids = array(); $bUseSortIfSupported = !!$oSettings->GetConf('WebMail/UseSortImapForDateMode'); if ($bUseSortIfSupported) { $bUseSortIfSupported = $oImapClient->IsSupported('SORT'); } if ($bUseThreadsIfSupported) { $bUseThreadsIfSupported = $oImapClient->IsSupported('THREAD=REFS') || $oImapClient->IsSupported('THREAD=REFERENCES') || $oImapClient->IsSupported('THREAD=ORDEREDSUBJECT'); } if (0 < strlen($sSearch) || 0 < count($aFilters)) { $sCutedSearch = $sSearch; $sCutedSearch = \preg_replace('/[\\s]+/', ' ', $sCutedSearch); $sCutedSearch = \preg_replace('/attach[ ]?:[ ]?/i', 'attach:', $sCutedSearch); $bSearchAttachments = false; $fAttachmentSearchCallback = null; $aMatch = array(); if (CApi::GetConf('labs.use-body-structures-for-has-attachments-search', false) && \preg_match('/has[ ]?:[ ]?attachments/i', $sSearch) || \preg_match('/attach:([^\\s]+)/i', $sSearch, $aMatch)) { $bSearchAttachments = true; $sAttachmentName = isset($aMatch[1]) ? trim($aMatch[1]) : ''; $sAttachmentRegs = !empty($sAttachmentName) && '*' !== $sAttachmentName ? '/[^>]*' . str_replace('\\*', '[^>]*', preg_quote(trim($sAttachmentName, '*'), '/')) . '[^>]*/ui' : ''; if (CApi::GetConf('labs.use-body-structures-for-has-attachments-search', false)) { $sCutedSearch = trim(preg_replace('/has[ ]?:[ ]?attachments/i', '', $sCutedSearch)); } $sCutedSearch = trim(preg_replace('/attach:([^\\s]+)/', '', $sCutedSearch)); $fAttachmentSearchCallback = function ($oBodyStructure, $sSize, $sInternalDate, $aFlagsLower, $sUid) use($sFolderFullNameRaw, $sAttachmentRegs) { $bResult = false; if ($oBodyStructure) { $aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts(); if ($aAttachmentsParts && 0 < count($aAttachmentsParts)) { $oAttachments = CApiMailAttachmentCollection::NewInstance(); foreach ($aAttachmentsParts as $oAttachmentItem) { $oAttachments->Add(CApiMailAttachment::NewBodyStructureInstance($sFolderFullNameRaw, $sUid, $oAttachmentItem)); } $bResult = $oAttachments->HasNonInlineAttachments(); if ($bResult && !empty($sAttachmentRegs)) { $aList = $oAttachments->FilterList(function ($oAttachment) use($sAttachmentRegs) { if ($oAttachment && !$oAttachment->IsInline() && !$oAttachment->Cid()) { return !!preg_match($sAttachmentRegs, $oAttachment->FileName()); } return false; }); return is_array($aList) ? 0 < count($aList) : false; } } } unset($oBodyStructure); return $bResult; }; } if (0 < strlen($sCutedSearch) || 0 < count($aFilters)) { $bSearch = true; $sSearchCriterias = $this->getImapSearchString($oImapClient, $sCutedSearch, $oAccount->GetDefaultTimeOffset() * 60, $aFilters); $bIndexAsUid = true; $aIndexOrUids = null; if ($bUseSortIfSupported) { $aIndexOrUids = $oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, $bIndexAsUid); } else { if (!\MailSo\Base\Utils::IsAscii($sCutedSearch)) { try { $aIndexOrUids = $oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { // Charset is not supported. Skip and try request without charset. $aIndexOrUids = null; } } if (null === $aIndexOrUids) { $aIndexOrUids = $oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); } } if ($bSearchAttachments && is_array($aIndexOrUids) && 0 < count($aIndexOrUids)) { $aIndexOrUids = $this->specialUidsSearch($oImapClient, $fAttachmentSearchCallback, $sFolderFullNameRaw, $aIndexOrUids, $iOffset, $iLimit); } } else { if ($bSearchAttachments) { $bIndexAsUid = true; $aIndexOrUids = $this->specialIndexSearch($oImapClient, $fAttachmentSearchCallback, $sFolderFullNameRaw, $iOffset, $iLimit); } } } else { if ($bUseThreadsIfSupported && 1 < $iMessageCount) { $bIndexAsUid = true; $aThreadUids = array(); try { $aThreadUids = $oImapClient->MessageSimpleThread(); } catch (\MailSo\Imap\Exceptions\RuntimeException $oException) { $aThreadUids = array(); } $aThreads = $this->compileThreadArray($aThreadUids); $aIndexOrUids = array_keys($aThreads); $iMessageCount = count($aIndexOrUids); } else { if ($bUseSortIfSupported && 1 < $iMessageCount) { $bIndexAsUid = true; $aIndexOrUids = $oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), 'ALL', $bIndexAsUid); } else { $bIndexAsUid = false; $aIndexOrUids = array(1); if (1 < $iMessageCount) { $aIndexOrUids = array_reverse(range(1, $iMessageCount)); } } } } if (is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iRealMessageCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 < strlen($sSearch) || 0 < count($aFilters) ? count($aIndexOrUids) : $iMessageCount; if (0 < count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = array_slice($aIndexOrUids, $iOffset, $iLimit); if ($bIndexAsUid) { $oMessageCollection->Uids = $aRequestIndexOrUids; } if (is_array($aRequestIndexOrUids) && 0 < count($aRequestIndexOrUids)) { $aFetchResponse = $oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::INDEX, \MailSo\Imap\Enumerations\FetchType::UID, \MailSo\Imap\Enumerations\FetchType::RFC822_SIZE, \MailSo\Imap\Enumerations\FetchType::INTERNALDATE, \MailSo\Imap\Enumerations\FetchType::FLAGS, \MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE, \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK), implode(',', $aRequestIndexOrUids), $bIndexAsUid); if (is_array($aFetchResponse) && 0 < count($aFetchResponse)) { $aFetchIndexArray = array(); $oFetchResponseItem = null; foreach ($aFetchResponse as &$oFetchResponseItem) { $aFetchIndexArray[$bIndexAsUid ? $oFetchResponseItem->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID) : $oFetchResponseItem->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INDEX)] =& $oFetchResponseItem; unset($oFetchResponseItem); } foreach ($aRequestIndexOrUids as $iFUid) { if (isset($aFetchIndexArray[$iFUid])) { $oMailMessage = CApiMailMessage::NewFetchResponseInstance($oMessageCollection->FolderName, $aFetchIndexArray[$iFUid]); if (!$bIndexAsUid) { $oMessageCollection->Uids[] = $oMailMessage->Uid(); } $oMessageCollection->Add($oMailMessage); unset($oMailMessage); } } } } } } } if (!$bSearch && $bUseThreadsIfSupported && 0 < count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads) { $iUid = $oMessage->Uid(); if (isset($aThreads[$iUid]) && is_array($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); } }); } if (0 < strlen($sInboxUidnext) && 'INBOX' === $oMessageCollection->FolderName && $sInboxUidnext !== $oMessageCollection->UidNext) { $oMessageCollection->New = $this->GetNextMessages($oAccount, 'INBOX', $sInboxUidnext); } return $oMessageCollection; }
/** * @param string $sRawFolderFullName * @param \MailSo\Imap\FetchResponse $oFetchResponse * @param \MailSo\Imap\BodyStructure $oBodyStructure = null * @param array $aAscPartsIds = array() * * @return CApiMailMessage */ public function InitByFetchResponse($sRawFolderFullName, $oFetchResponse, $oBodyStructure = null, $sRfc822SubMimeIndex = '', $aAscPartsIds = array()) { if (!$oBodyStructure) { $oBodyStructure = $oFetchResponse->GetFetchBodyStructure(); } $aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : array(); $aICalPart = $oBodyStructure ? $oBodyStructure->SearchByContentType('text/calendar') : null; $oICalPart = is_array($aICalPart) && 0 < count($aICalPart) ? $aICalPart[0] : null; $aVCardPart = $oBodyStructure ? $oBodyStructure->SearchByContentType('text/vcard') : null; $aVCardPart = $aVCardPart ? $aVCardPart : ($oBodyStructure ? $oBodyStructure->SearchByContentType('text/x-vcard') : null); $oVCardPart = is_array($aVCardPart) && 0 < count($aVCardPart) ? $aVCardPart[0] : null; $sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID); $sSize = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE); $sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE); $aFlags = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::FLAGS); $this->sFolder = $sRawFolderFullName; $this->iUid = is_numeric($sUid) ? (int) $sUid : 0; $this->iSize = is_numeric($sSize) ? (int) $sSize : 0; $this->iTextSize = 0; $this->aFlags = is_array($aFlags) ? $aFlags : array(); $this->aFlagsLowerCase = array_map('strtolower', $this->aFlags); $this->iInternalTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseInternalDateString($sInternalDate); if ($oICalPart) { $sICal = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY . '[' . $oICalPart->PartID() . ']'); if (!empty($sICal)) { $sICal = \MailSo\Base\Utils::DecodeEncodingValue($sICal, $oICalPart->MailEncodingName()); $sICal = \MailSo\Base\Utils::ConvertEncoding($sICal, \MailSo\Base\Utils::NormalizeCharset($oICalPart->Charset(), true), \MailSo\Base\Enumerations\Charset::UTF_8); if (!empty($sICal) && false !== strpos($sICal, 'BEGIN:VCALENDAR')) { $sICal = preg_replace('/(.*)(BEGIN[:]VCALENDAR(.+)END[:]VCALENDAR)(.*)/ms', '$2', $sICal); } else { $sICal = ''; } if (!empty($sICal)) { $this->AddExtend('ICAL_RAW', $sICal); } } } if ($oVCardPart) { $sVCard = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY . '[' . $oVCardPart->PartID() . ']'); if (!empty($sVCard)) { $sVCard = \MailSo\Base\Utils::DecodeEncodingValue($sVCard, $oVCardPart->MailEncodingName()); $sVCard = \MailSo\Base\Utils::ConvertEncoding($sVCard, \MailSo\Base\Utils::NormalizeCharset($oVCardPart->Charset(), true), \MailSo\Base\Enumerations\Charset::UTF_8); if (!empty($sVCard) && false !== strpos($sVCard, 'BEGIN:VCARD')) { $sVCard = preg_replace('/(.*)(BEGIN\\:VCARD(.+)END\\:VCARD)(.*)/ms', '$2', $sVCard); } else { $sVCard = ''; } if (!empty($sVCard)) { $this->AddExtend('VCARD_RAW', $sVCard); } } } $sCharset = $oBodyStructure ? $oBodyStructure->SearchCharset() : ''; $sCharset = \MailSo\Base\Utils::NormalizeCharset($sCharset); $this->sHeaders = trim($oFetchResponse->GetHeaderFieldsValue($sRfc822SubMimeIndex)); if (!empty($this->sHeaders)) { $oHeaders = \MailSo\Mime\HeaderCollection::NewInstance()->Parse($this->sHeaders, false, $sCharset); $sContentTypeCharset = $oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::CHARSET); if (!empty($sContentTypeCharset)) { $sCharset = $sContentTypeCharset; $sCharset = \MailSo\Base\Utils::NormalizeCharset($sCharset); } if (!empty($sCharset)) { $oHeaders->SetParentCharset($sCharset); } $bCharsetAutoDetect = 0 === \strlen($sCharset); $this->sSubject = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SUBJECT, $bCharsetAutoDetect); $this->sMessageId = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::MESSAGE_ID); $this->sContentType = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE); $aReceived = $oHeaders->ValuesByName(\MailSo\Mime\Enumerations\Header::RECEIVED); $sReceived = !empty($aReceived[0]) ? trim($aReceived[0]) : ''; $sDate = ''; if (!empty($sReceived)) { $aParts = explode(';', $sReceived); if (0 < count($aParts)) { $aParts = array_reverse($aParts); foreach ($aParts as $sReceiveLine) { $sReceiveLine = trim($sReceiveLine); if (preg_match('/[\\d]{4} [\\d]{2}:[\\d]{2}:[\\d]{2} /', $sReceiveLine)) { $sDate = $sReceiveLine; break; } } } } if (empty($sDate)) { $sDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE); } if (!empty($sDate)) { $this->iReceivedOrDateTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($sDate); } $this->oFrom = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::FROM_, $bCharsetAutoDetect); $this->oTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::TO_, $bCharsetAutoDetect); $this->oCc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::CC, $bCharsetAutoDetect); $this->oBcc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::BCC, $bCharsetAutoDetect); $this->oSender = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::SENDER, $bCharsetAutoDetect); $this->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, $bCharsetAutoDetect); $this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO); $this->sReferences = \preg_replace('/[\\s]+/', ' ', $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES)); // Sensitivity $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING; $sSensitivity = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SENSITIVITY); switch (strtolower($sSensitivity)) { case 'personal': $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PERSONAL; break; case 'private': $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PRIVATE_; break; case 'company-confidential': $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::CONFIDENTIAL; break; } // Priority $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL; $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY); if (0 === strlen($sPriority)) { $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IMPORTANCE); } if (0 === strlen($sPriority)) { $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_PRIORITY); } if (0 < strlen($sPriority)) { switch (str_replace(' ', '', strtolower($sPriority))) { case 'high': case '1(highest)': case '2(high)': case '1': case '2': $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH; break; case 'low': case '4(low)': case '5(lowest)': case '4': case '5': $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW; break; } } // ReadingConfirmation $this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO); if (0 === strlen($this->sReadingConfirmation)) { $this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO); } $this->sReadingConfirmation = trim($this->sReadingConfirmation); $sDraftInfo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_DRAFT_INFO); if (0 < strlen($sDraftInfo)) { $sType = ''; $sFolder = ''; $sUid = ''; \MailSo\Mime\ParameterCollection::NewInstance($sDraftInfo)->ForeachList(function ($oParameter) use(&$sType, &$sFolder, &$sUid) { switch (strtolower($oParameter->Name())) { case 'type': $sType = $oParameter->Value(); break; case 'uid': $sUid = $oParameter->Value(); break; case 'folder': $sFolder = base64_decode($oParameter->Value()); break; } }); if (0 < strlen($sType) && 0 < strlen($sFolder) && 0 < strlen($sUid)) { $this->aDraftInfo = array($sType, $sUid, $sFolder); } } \CApi::Plugin()->RunHook('api-mail-message-headers-parse', array(&$this, $oHeaders)); } if (is_array($aTextParts) && 0 < count($aTextParts)) { if (0 === \strlen($sCharset)) { $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8; } $sHtmlParts = array(); $sPlainParts = array(); $iHtmlSize = 0; $iPlainSize = 0; foreach ($aTextParts as $oPart) { if ($oPart) { if ('text/html ' === $oPart->ContentType()) { $iHtmlSize += $oPart->EstimatedSize(); } else { $iPlainSize += $oPart->EstimatedSize(); } } $sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY . '[' . $oPart->PartID() . ('' !== $sRfc822SubMimeIndex && is_numeric($sRfc822SubMimeIndex) ? '.1' : '') . ']'); // if (null === $sText) // { // $sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$oPart->PartID(). // ('' !== $sRfc822SubMimeIndex && is_numeric($sRfc822SubMimeIndex) ? '.1' : '').']<0>'); // } if (is_string($sText) && 0 < strlen($sText)) { $sTextCharset = $oPart->Charset(); if (empty($sTextCharset)) { $sTextCharset = $sCharset; } $sTextCharset = \MailSo\Base\Utils::NormalizeCharset($sTextCharset, true); $sText = \MailSo\Base\Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName()); $sText = \MailSo\Base\Utils::ConvertEncoding($sText, $sTextCharset, \MailSo\Base\Enumerations\Charset::UTF_8); $sText = \MailSo\Base\Utils::Utf8Clear($sText); if ('text/html' === $oPart->ContentType()) { $sHtmlParts[] = $sText; } else { $sPlainParts[] = $sText; } } } if (0 < count($sHtmlParts)) { $this->sHtml = trim(implode('<br />', $sHtmlParts)); $this->iTextSize = strlen($this->sHtml); } else { $this->sPlain = trim(implode("\n", $sPlainParts)); $this->iTextSize = strlen($this->sPlain); } if (0 === $this->iTextSize) { $this->iTextSize = 0 < $iHtmlSize ? $iHtmlSize : $iPlainSize; } unset($sHtmlParts, $sPlainParts); } if ($oBodyStructure) { $aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts(); if ($aAttachmentsParts && 0 < count($aAttachmentsParts)) { $this->oAttachments = CApiMailAttachmentCollection::NewInstance(); foreach ($aAttachmentsParts as $oAttachmentItem) { $this->oAttachments->Add(CApiMailAttachment::NewBodyStructureInstance($this->sFolder, $this->iUid, $oAttachmentItem)); } $this->oAttachments->ForeachList(function ($oAttachment) use($aAscPartsIds, $oFetchResponse) { if ($oAttachment && in_array($oAttachment->MimeIndex(), $aAscPartsIds)) { $mContent = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY . '[' . $oAttachment->MimeIndex() . ']'); if (is_string($mContent)) { $oAttachment->SetContent(\MailSo\Base\Utils::DecodeEncodingValue($mContent, $oAttachment->ContentTransferEncoding())); } } }); } } \CApi::Plugin()->RunHook('api-mail-message-parse', array(&$this, $oFetchResponse, $oBodyStructure, $sRfc822SubMimeIndex)); return $this; }