mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-27 02:59:21 +03:00
Added support for rfc7889 and impoved rfc8474
This commit is contained in:
parent
d4117dc723
commit
e4149b655c
6 changed files with 105 additions and 46 deletions
|
|
@ -26,4 +26,8 @@ abstract class FolderResponseStatus
|
|||
const UNSEEN = 'UNSEEN';
|
||||
// rfc4551
|
||||
const HIGHESTMODSEQ = 'HIGHESTMODSEQ';
|
||||
// rfc7889
|
||||
const APPENDLIMIT = 'APPENDLIMIT';
|
||||
// rfc8474
|
||||
const MAILBOXID = 'MAILBOXID';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ abstract class FolderStatus
|
|||
const UNSEEN = 'UNSEEN';
|
||||
// rfc4551
|
||||
const HIGHESTMODSEQ = 'HIGHESTMODSEQ';
|
||||
// rfc7889
|
||||
const APPENDLIMIT = 'APPENDLIMIT';
|
||||
// rfc8474
|
||||
const MAILBOXID = 'MAILBOXID';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,12 +54,12 @@ class FetchResponse
|
|||
{
|
||||
$oResult = null;
|
||||
$aEmails = $this->GetFetchEnvelopeValue($iIndex);
|
||||
if (is_array($aEmails) && 0 < count($aEmails))
|
||||
if (\is_array($aEmails) && \count($aEmails))
|
||||
{
|
||||
$oResult = new \MailSo\Mime\EmailCollection;
|
||||
foreach ($aEmails as $aEmailItem)
|
||||
{
|
||||
if (is_array($aEmailItem) && 4 === count($aEmailItem))
|
||||
if (\is_array($aEmailItem) && 4 === \count($aEmailItem))
|
||||
{
|
||||
$sDisplayName = \MailSo\Base\Utils::DecodeHeaderValue(
|
||||
self::findEnvelopeIndex($aEmailItem, 0, ''), $sParentCharset);
|
||||
|
|
@ -70,7 +70,7 @@ class FetchResponse
|
|||
$sLocalPart = self::findEnvelopeIndex($aEmailItem, 2, '');
|
||||
$sDomainPart = self::findEnvelopeIndex($aEmailItem, 3, '');
|
||||
|
||||
if (0 < strlen($sLocalPart) && 0 < strlen($sDomainPart))
|
||||
if (\strlen($sLocalPart) && \strlen($sDomainPart))
|
||||
{
|
||||
$oResult->append(
|
||||
new \MailSo\Mime\Email($sLocalPart.'@'.$sDomainPart, $sDisplayName)
|
||||
|
|
@ -87,9 +87,9 @@ class FetchResponse
|
|||
{
|
||||
$aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE);
|
||||
|
||||
if (is_array($aBodyStructureArray))
|
||||
if (\is_array($aBodyStructureArray))
|
||||
{
|
||||
if (0 < strlen($sRfc822SubMimeIndex))
|
||||
if (\strlen($sRfc822SubMimeIndex))
|
||||
{
|
||||
return BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex);
|
||||
}
|
||||
|
|
@ -100,6 +100,7 @@ class FetchResponse
|
|||
}
|
||||
|
||||
/**
|
||||
* Like: UID, RFC822.SIZE, MODSEQ, INTERNALDATE, FLAGS, BODYSTRUCTURE
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetFetchValue(string $sFetchItemName)
|
||||
|
|
@ -124,11 +125,15 @@ class FetchResponse
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like: BODY[HEADER.FIELDS (RETURN-PATH RECEIVED MIME-VERSION MESSAGE-ID CONTENT-TYPE FROM TO CC BCC SENDER REPLY-TO DELIVERED-TO IN-REPLY-TO REFERENCES DATE SUBJECT SENSITIVITY X-MSMAIL-PRIORITY IMPORTANCE X-PRIORITY X-DRAFT-INFO RETURN-RECEIPT-TO DISPOSITION-NOTIFICATION-TO X-CONFIRM-READING-TO AUTHENTICATION-RESULTS X-DKIM-AUTHENTICATION-RESULTS LIST-UNSUBSCRIBE X-SPAM-STATUS X-SPAMD-RESULT X-BOGOSITY X-VIRUS X-VIRUS-SCANNED X-VIRUS-STATUS)]
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetHeaderFieldsValue(string $sRfc822SubMimeIndex = '') : string
|
||||
{
|
||||
$bNextIsValue = false;
|
||||
|
||||
$sRfc822SubMimeIndex = 0 < \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
|
||||
$sRfc822SubMimeIndex = \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
|
||||
|
||||
if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -334,6 +334,25 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC 7889
|
||||
* APPENDLIMIT=<number> indicates that the IMAP server has the same upload limit for all mailboxes.
|
||||
* APPENDLIMIT without any value indicates that the IMAP server supports this extension,
|
||||
* and that the client will need to discover upload limits for each mailbox,
|
||||
* as they might differ from mailbox to mailbox.
|
||||
*/
|
||||
public function AppendLimit() : ?int
|
||||
{
|
||||
if ($this->aCapabilityItems) {
|
||||
foreach ($this->aCapabilityItems as $string) {
|
||||
if ('APPENDLIMIT=' === \substr($string, 0, 12)) {
|
||||
return (int) \substr($string, 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
|
|
@ -416,21 +435,36 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
*/
|
||||
public function FolderStatus(string $sFolderName, array $aStatusItems) : ?array
|
||||
{
|
||||
if (!\count($aStatusItems)) {
|
||||
return null;
|
||||
}
|
||||
$oFolderInfo = $this->oCurrentFolderInfo;
|
||||
$bReselect = false;
|
||||
$bWritable = false;
|
||||
if ($oFolderInfo && $sFolderName === $oFolderInfo->FolderName) {
|
||||
// Not supported by Outlook/Hotmail/Office365
|
||||
/**
|
||||
* There's a long standing IMAP CLIENTBUG where STATUS command is executed
|
||||
* after SELECT/EXAMINE on same folder (it should not).
|
||||
* So we must unselect the folder to be able to get the APPENDLIMIT and UNSEEN.
|
||||
*/
|
||||
/*
|
||||
if ($this->IsSupported('ESEARCH')) {
|
||||
$aResult = $oFolderInfo->getStatusItems();
|
||||
// SELECT or EXAMINE command then UNSEEN is the message sequence number of the first unseen message
|
||||
$aResult['UNSEEN'] = $this->simpleESearchOrESortHelper(false, 'UNSEEN', ['COUNT'])['COUNT'];
|
||||
return $aResult;
|
||||
}
|
||||
// $this->FolderUnSelect();
|
||||
*/
|
||||
$bWritable = $oFolderInfo->IsWritable;
|
||||
$bReselect = true;
|
||||
$this->FolderUnSelect();
|
||||
}
|
||||
return \count($aStatusItems)
|
||||
? $this->SendRequestGetResponse('STATUS', array($this->EscapeString($sFolderName), $aStatusItems))
|
||||
->getStatusFolderInformationResult()
|
||||
: null;
|
||||
$aResult = $this->SendRequestGetResponse('STATUS', array($this->EscapeString($sFolderName), $aStatusItems))
|
||||
->getStatusFolderInformationResult();
|
||||
if ($bReselect) {
|
||||
$this->selectOrExamineFolder($sFolderName, $bWritable, false);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -461,18 +495,26 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
$aParameters[] = $this->EscapeString($sParentFolderName);
|
||||
$aParameters[] = $this->EscapeString(\strlen(\trim($sListPattern)) ? $sListPattern : '*');
|
||||
|
||||
// RFC 5819
|
||||
if ($bUseListStatus && !$bIsSubscribeList && $this->IsSupported('LIST-STATUS'))
|
||||
{
|
||||
// RFC 5819
|
||||
$aL = array(
|
||||
Enumerations\FolderStatus::MESSAGES,
|
||||
Enumerations\FolderStatus::UNSEEN,
|
||||
Enumerations\FolderStatus::UIDNEXT
|
||||
);
|
||||
|
||||
// RFC 4551
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aL[] = Enumerations\FolderStatus::HIGHESTMODSEQ;
|
||||
}
|
||||
// RFC 7889
|
||||
if ($this->IsSupported('APPENDLIMIT')) {
|
||||
$aL[] = Enumerations\FolderStatus::APPENDLIMIT;
|
||||
}
|
||||
// RFC 8474
|
||||
if ($this->IsSupported('OBJECTID')) {
|
||||
$aTypes[] = Enumerations\FolderStatus::MAILBOXID;
|
||||
}
|
||||
|
||||
$aReturnParams[] = 'STATUS';
|
||||
$aReturnParams[] = $aL;
|
||||
|
|
@ -560,11 +602,17 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
throw new \MailSo\Base\Exceptions\InvalidArgumentException;
|
||||
}
|
||||
|
||||
$aParams = array($this->EscapeString($sFolderName));
|
||||
/*
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aParams[] = ['CONDSTORE'];
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* IMAP4rev2 SELECT/EXAMINE are now required to return an untagged LIST response.
|
||||
*/
|
||||
$this->oCurrentFolderInfo = $this->SendRequestGetResponse($bIsWritable ? 'SELECT' : 'EXAMINE',
|
||||
array($this->EscapeString($sFolderName)))
|
||||
$aParams)
|
||||
->getCurrentFolderInformation($sFolderName, $bIsWritable);
|
||||
|
||||
return $this;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ trait Status
|
|||
*/
|
||||
$HIGHESTMODSEQ,
|
||||
|
||||
/**
|
||||
* RFC7889
|
||||
* Message upload size limit.
|
||||
* @var int
|
||||
*/
|
||||
$APPENDLIMIT,
|
||||
|
||||
/**
|
||||
* RFC8474
|
||||
* A server-allocated unique identifier for the mailbox.
|
||||
|
|
@ -81,7 +88,7 @@ trait Status
|
|||
public function getStatusItems() : array
|
||||
{
|
||||
return \array_filter(\get_object_vars($this), function($v, $k){
|
||||
return isset($v) && \property_exists(__TRAIT__, $k);
|
||||
return \property_exists(__TRAIT__, $k);
|
||||
}, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -519,8 +519,7 @@ class MailClient
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function initFolderValues(string $sFolderName, int &$iCount, int &$iUnseenCount,
|
||||
int &$iUidNext, int &$iHighestModSeq) : void
|
||||
protected function initFolderValues(string $sFolderName) : array
|
||||
{
|
||||
$aTypes = array(
|
||||
FolderResponseStatus::MESSAGES,
|
||||
|
|
@ -528,24 +527,31 @@ class MailClient
|
|||
FolderResponseStatus::UIDNEXT
|
||||
);
|
||||
|
||||
if ($this->oImapClient->IsSupported('CONDSTORE'))
|
||||
{
|
||||
if ($this->oImapClient->IsSupported('CONDSTORE')) {
|
||||
$aTypes[] = FolderResponseStatus::HIGHESTMODSEQ;
|
||||
}
|
||||
if ($this->oImapClient->IsSupported('APPENDLIMIT')) {
|
||||
$aTypes[] = FolderResponseStatus::APPENDLIMIT;
|
||||
}
|
||||
if ($this->oImapClient->IsSupported('OBJECTID')) {
|
||||
$aTypes[] = FolderResponseStatus::MAILBOXID;
|
||||
}
|
||||
|
||||
$aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, $aTypes);
|
||||
|
||||
$iCount = (int) $aFolderStatus[FolderResponseStatus::MESSAGES] ?? 0;
|
||||
return [
|
||||
$aFolderStatus[FolderResponseStatus::MESSAGES] ?: 0,
|
||||
|
||||
$iUnseenCount = (int) $aFolderStatus[FolderResponseStatus::UNSEEN] ?? 0;
|
||||
$aFolderStatus[FolderResponseStatus::UNSEEN] ?: 0,
|
||||
|
||||
$iUidNext = (int) $aFolderStatus[FolderResponseStatus::UIDNEXT] ?? 0;
|
||||
$aFolderStatus[FolderResponseStatus::UIDNEXT] ?: 0,
|
||||
|
||||
if (isset($aFolderStatus[FolderResponseStatus::HIGHESTMODSEQ])) {
|
||||
$iHighestModSeq = (int) $aFolderStatus[FolderResponseStatus::HIGHESTMODSEQ];
|
||||
} else {
|
||||
$iHighestModSeq = 0;
|
||||
}
|
||||
$aFolderStatus[FolderResponseStatus::HIGHESTMODSEQ] ?: 0,
|
||||
|
||||
$aFolderStatus[FolderResponseStatus::APPENDLIMIT] ?: $this->oImapClient->AppendLimit(),
|
||||
|
||||
$aFolderStatus[FolderResponseStatus::MAILBOXID] ?: ''
|
||||
];
|
||||
}
|
||||
|
||||
public function GenerateImapClientHash() : string
|
||||
|
|
@ -652,12 +658,7 @@ class MailClient
|
|||
}
|
||||
}
|
||||
|
||||
$iCount = 0;
|
||||
$iUnseenCount = 0;
|
||||
$iUidNext = 0;
|
||||
$iHighestModSeq = 0;
|
||||
|
||||
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $iUidNext, $iHighestModSeq);
|
||||
list($iCount, $iUnseenCount, $iUidNext, $iHighestModSeq, $iAppendLimit, $sMailboxId) = $this->initFolderValues($sFolderName);
|
||||
|
||||
return array(
|
||||
'Folder' => $sFolderName,
|
||||
|
|
@ -667,6 +668,8 @@ class MailClient
|
|||
'UidNext' => $iUidNext,
|
||||
'MessageFlags' => $aFlags,
|
||||
'HighestModSeq' => $iHighestModSeq,
|
||||
'AppendLimit' => $iAppendLimit,
|
||||
'MailboxId' => $sMailboxId,
|
||||
'NewMessages' => 'INBOX' === $sFolderName && \MailSo\Config::$CheckNewMessages ?
|
||||
$this->getFolderNextMessageInformation($sFolderName, $iPrevUidNext, $iUidNext) : array()
|
||||
);
|
||||
|
|
@ -679,12 +682,7 @@ class MailClient
|
|||
*/
|
||||
public function FolderHash(string $sFolderName) : string
|
||||
{
|
||||
$iCount = 0;
|
||||
$iUnseenCount = 0;
|
||||
$iUidNext = 0;
|
||||
$iHighestModSeq = 0;
|
||||
|
||||
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $iUidNext, $iHighestModSeq);
|
||||
list($iCount, $iUnseenCount, $iUidNext, $iHighestModSeq) = $this->initFolderValues($sFolderName);
|
||||
|
||||
return $this->GenerateFolderHash($sFolderName, $iCount, $iUidNext, $iHighestModSeq);
|
||||
}
|
||||
|
|
@ -1555,11 +1553,6 @@ class MailClient
|
|||
$mAllSortedUids = null;
|
||||
$mAllThreads = null;
|
||||
|
||||
$iMessageRealCount = 0;
|
||||
$iMessageUnseenCount = 0;
|
||||
$iUidNext = 0;
|
||||
$iHighestModSeq = 0;
|
||||
|
||||
$bUseSortIfSupported = $bUseSortIfSupported && $this->oImapClient->IsSupported('SORT');
|
||||
|
||||
$bUseThreadSortIfSupported = $bUseThreadSortIfSupported ?
|
||||
|
|
@ -1575,7 +1568,7 @@ class MailClient
|
|||
$oCacher = null;
|
||||
}
|
||||
|
||||
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $iUidNext, $iHighestModSeq);
|
||||
list($iMessageRealCount, $iMessageUnseenCount, $iUidNext, $iHighestModSeq) = $this->initFolderValues($sFolderName);
|
||||
|
||||
if ($bUseFilter)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue