mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-04 06:57:03 +03:00
Added callable cbUntaggedResponse param to ImapClient.getResponse()
This allows one less foreach() in ImapClient functions: * specificFolderList() * selectOrExamineFolder() * FolderStatus() * Fetch()
This commit is contained in:
parent
f7412db3e5
commit
da0d8f66d5
2 changed files with 80 additions and 73 deletions
|
|
@ -482,17 +482,17 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
$this->FolderUnSelect();
|
$this->FolderUnSelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
$oResponseCollection = $this->SendRequestGetResponse('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems));
|
|
||||||
$oInfo = new FolderInformation($sFolderName, false);
|
$oInfo = new FolderInformation($sFolderName, false);
|
||||||
foreach ($oResponseCollection as $oResponse) {
|
$this->SendRequest('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems));
|
||||||
|
$this->getResponse(null, function(Response $oResponse) use ($oInfo) {
|
||||||
$oInfo->setStatusFromResponse($oResponse);
|
$oInfo->setStatusFromResponse($oResponse);
|
||||||
}
|
return true;
|
||||||
$aResult = $oInfo->getStatusItems();
|
});
|
||||||
|
|
||||||
if ($bReselect) {
|
if ($bReselect) {
|
||||||
$this->selectOrExamineFolder($sFolderName, $bWritable, false);
|
$this->selectOrExamineFolder($sFolderName, $bWritable, false);
|
||||||
}
|
}
|
||||||
return $aResult;
|
return $oInfo->getStatusItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -562,30 +562,37 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
$aParameters[] = $aReturnParams;
|
$aParameters[] = $aReturnParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$bPassthru = false;
|
||||||
$aReturn = array();
|
$aReturn = array();
|
||||||
|
|
||||||
|
// RFC 5464
|
||||||
|
$bMetadata = !$bIsSubscribeList && $this->IsSupported('METADATA');
|
||||||
|
$aMetadata = null;
|
||||||
|
if ($bMetadata) {
|
||||||
|
// Dovecot supports fetching all METADATA at once
|
||||||
|
$aMetadata = $this->getAllMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
$this->SendRequest($sCmd, $aParameters);
|
$this->SendRequest($sCmd, $aParameters);
|
||||||
$bPassthru = false;
|
|
||||||
if ($bPassthru) {
|
if ($bPassthru) {
|
||||||
$this->streamResponse();
|
$this->streamResponse();
|
||||||
} else {
|
} else {
|
||||||
$sDelimiter = '';
|
$sDelimiter = '';
|
||||||
$bInbox = false;
|
$bInbox = false;
|
||||||
foreach ($this->getResponse() as $oResponse) {
|
$oImapClient = $this;
|
||||||
if (Enumerations\ResponseType::UNTAGGED !== $oResponse->ResponseType) {
|
$this->getResponse(null, function(Response $oResponse) use ($oImapClient, &$aReturn, $sCmd, &$sDelimiter, &$bInbox, $aMetadata) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
|
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
|
||||||
$sFullName = $this->toUTF8($oResponse->ResponseList[2]);
|
$sFullName = $oImapClient->toUTF8($oResponse->ResponseList[2]);
|
||||||
if (!isset($aReturn[$sFullName])) {
|
if (!isset($aReturn[$sFullName])) {
|
||||||
$aReturn[$sFullName] = new Folder($sFullName);
|
$aReturn[$sFullName] = new Folder($sFullName);
|
||||||
}
|
}
|
||||||
$aReturn[$sFullName]->setStatusFromResponse($oResponse);
|
$aReturn[$sFullName]->setStatusFromResponse($oResponse);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if ($sCmd === $oResponse->StatusOrIndex && 5 == \count($oResponse->ResponseList)) {
|
else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$sFullName = $this->toUTF8($oResponse->ResponseList[4]);
|
$sFullName = $oImapClient->toUTF8($oResponse->ResponseList[4]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $oResponse->ResponseList[0] = *
|
* $oResponse->ResponseList[0] = *
|
||||||
|
|
@ -612,18 +619,24 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
$sDelimiter = $oFolder->Delimiter();
|
$sDelimiter = $oFolder->Delimiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($aMetadata[$oResponse->ResponseList[4]])) {
|
||||||
|
$oFolder->SetAllMetadata($aMetadata[$oResponse->ResponseList[4]]);
|
||||||
|
}
|
||||||
|
|
||||||
$aReturn[$sFullName] = $oFolder;
|
$aReturn[$sFullName] = $oFolder;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
|
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
|
||||||
{
|
{
|
||||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
$oImapClient->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||||
}
|
}
|
||||||
catch (\Throwable $oException)
|
catch (\Throwable $oException)
|
||||||
{
|
{
|
||||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
$oImapClient->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
|
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
|
||||||
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
|
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
|
||||||
|
|
@ -631,24 +644,14 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC 5464
|
// RFC 5464
|
||||||
if (!$bIsSubscribeList && $this->IsSupported('METADATA')) {
|
if ($bMetadata && !$aMetadata) {
|
||||||
// Dovecot supports fetching all METADATA at once
|
foreach ($aReturn as $oFolder) {
|
||||||
$aMetadata = $this->getAllMetadata();
|
try {
|
||||||
if ($aMetadata) {
|
$oFolder->SetAllMetadata(
|
||||||
foreach ($aReturn as $oFolder) {
|
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
|
||||||
if (isset($aMetadata[$oFolder->FullName()])) {
|
);
|
||||||
$oFolder->SetAllMetadata($aMetadata[$oFolder->FullName()]);
|
} catch (\Throwable $e) {
|
||||||
}
|
// Ignore error
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foreach ($aReturn as $oFolder) {
|
|
||||||
try {
|
|
||||||
$oFolder->SetAllMetadata(
|
|
||||||
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
|
|
||||||
);
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
// Ignore error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -738,34 +741,36 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
*/
|
*/
|
||||||
$oResponseCollection = $this->SendRequestGetResponse($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
|
$oResponseCollection = $this->SendRequestGetResponse($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
|
||||||
$oResult = new FolderInformation($sFolderName, $bIsWritable);
|
$oResult = new FolderInformation($sFolderName, $bIsWritable);
|
||||||
foreach ($oResponseCollection as $oResponse) {
|
|
||||||
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType) {
|
|
||||||
if (!$oResult->setStatusFromResponse($oResponse)) {
|
|
||||||
// OK untagged responses
|
|
||||||
if (\is_array($oResponse->OptionalResponse)) {
|
|
||||||
$key = $oResponse->OptionalResponse[0];
|
|
||||||
if (\count($oResponse->OptionalResponse) > 1) {
|
|
||||||
if ('PERMANENTFLAGS' === $key && \is_array($oResponse->OptionalResponse[1])) {
|
|
||||||
$oResult->PermanentFlags = $oResponse->OptionalResponse[1];
|
|
||||||
}
|
|
||||||
} else if ('READ-ONLY' === $key) {
|
|
||||||
// $oResult->IsWritable = false;
|
|
||||||
} else if ('READ-WRITE' === $key) {
|
|
||||||
// $oResult->IsWritable = true;
|
|
||||||
} else if ('NOMODSEQ' === $key) {
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc4551#section-3.1.2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// untagged responses
|
$this->SendRequest($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
|
||||||
else if (\count($oResponse->ResponseList) > 2
|
$this->getResponse(null, function(Response $oResponse) use ($oResult) {
|
||||||
&& 'FLAGS' === $oResponse->ResponseList[1]
|
if (!$oResult->setStatusFromResponse($oResponse)) {
|
||||||
&& \is_array($oResponse->ResponseList[2])) {
|
// OK untagged responses
|
||||||
$oResult->Flags = $oResponse->ResponseList[2];
|
if (\is_array($oResponse->OptionalResponse)) {
|
||||||
|
$key = $oResponse->OptionalResponse[0];
|
||||||
|
if (\count($oResponse->OptionalResponse) > 1) {
|
||||||
|
if ('PERMANENTFLAGS' === $key && \is_array($oResponse->OptionalResponse[1])) {
|
||||||
|
$oResult->PermanentFlags = $oResponse->OptionalResponse[1];
|
||||||
|
}
|
||||||
|
} else if ('READ-ONLY' === $key) {
|
||||||
|
// $oResult->IsWritable = false;
|
||||||
|
} else if ('READ-WRITE' === $key) {
|
||||||
|
// $oResult->IsWritable = true;
|
||||||
|
} else if ('NOMODSEQ' === $key) {
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc4551#section-3.1.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// untagged responses
|
||||||
|
else if (\count($oResponse->ResponseList) > 2
|
||||||
|
&& 'FLAGS' === $oResponse->ResponseList[1]
|
||||||
|
&& \is_array($oResponse->ResponseList[2])) {
|
||||||
|
$oResult->Flags = $oResponse->ResponseList[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
$this->oCurrentFolderInfo = $oResult;
|
$this->oCurrentFolderInfo = $oResult;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -861,6 +866,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
\MailSo\Log\Enumerations\Type::ERROR, true);
|
\MailSo\Log\Enumerations\Type::ERROR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$aReturn = array();
|
||||||
$this->aFetchCallbacks = array();
|
$this->aFetchCallbacks = array();
|
||||||
try {
|
try {
|
||||||
$aFetchItems = Enumerations\FetchType::ChangeFetchItemsBefourRequest($aInputFetchItems);
|
$aFetchItems = Enumerations\FetchType::ChangeFetchItemsBefourRequest($aInputFetchItems);
|
||||||
|
|
@ -882,21 +888,22 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
* $aParams[1][] = MODSEQ
|
* $aParams[1][] = MODSEQ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$oResult = $this->SendRequestGetResponse($bIndexIsUid ? 'UID FETCH' : 'FETCH', $aParams);
|
$this->SendRequest($bIndexIsUid ? 'UID FETCH' : 'FETCH', $aParams);
|
||||||
|
$oImapClient = $this;
|
||||||
|
$this->getResponse(null, function(Response $oResponse) use ($oImapClient, &$aReturn) {
|
||||||
|
if (FetchResponse::IsValidFetchImapResponse($oResponse)) {
|
||||||
|
if (FetchResponse::IsNotEmptyFetchImapResponse($oResponse)) {
|
||||||
|
$aReturn[] = new FetchResponse($oResponse);
|
||||||
|
return true;
|
||||||
|
} else if ($oImapClient->oLogger) {
|
||||||
|
$oImapClient->oLogger->Write('Skipped Imap Response! ['.$oResponse->ToLine().']', \MailSo\Log\Enumerations\Type::NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
$this->aFetchCallbacks = array();
|
$this->aFetchCallbacks = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$aReturn = array();
|
|
||||||
foreach ($oResult as $oResponse) {
|
|
||||||
if (FetchResponse::IsValidFetchImapResponse($oResponse)) {
|
|
||||||
if (FetchResponse::IsNotEmptyFetchImapResponse($oResponse)) {
|
|
||||||
$aReturn[] = new FetchResponse($oResponse);
|
|
||||||
} else if ($this->oLogger) {
|
|
||||||
$this->oLogger->Write('Skipped Imap Response! ['.$oResponse->ToLine().']', \MailSo\Log\Enumerations\Type::NOTICE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $aReturn;
|
return $aReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1159,7 +1166,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getResponse(string $sEndTag = null) : ResponseCollection
|
protected function getResponse(string $sEndTag = null, callable $cbUntaggedResponse = null) : ResponseCollection
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$oResult = new ResponseCollection;
|
$oResult = new ResponseCollection;
|
||||||
|
|
@ -1169,7 +1176,9 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
$oResponse = $this->partialParseResponse();
|
$oResponse = $this->partialParseResponse();
|
||||||
$oResult->append($oResponse);
|
if (!$cbUntaggedResponse || Enumerations\ResponseType::UNTAGGED !== $oResponse->ResponseType || !$cbUntaggedResponse($oResponse)) {
|
||||||
|
$oResult->append($oResponse);
|
||||||
|
}
|
||||||
|
|
||||||
// RFC 5530
|
// RFC 5530
|
||||||
if ($sEndTag === $oResponse->Tag && \is_array($oResponse->OptionalResponse) && 'CLIENTBUG' === $oResponse->OptionalResponse[0]) {
|
if ($sEndTag === $oResponse->Tag && \is_array($oResponse->OptionalResponse) && 'CLIENTBUG' === $oResponse->OptionalResponse[0]) {
|
||||||
|
|
|
||||||
|
|
@ -1220,8 +1220,6 @@ class MailClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$bUseListStatus = $bUseListStatus && $this->oImapClient->IsSupported('LIST-STATUS');
|
|
||||||
|
|
||||||
$aFolders = $bUseListStatus
|
$aFolders = $bUseListStatus
|
||||||
? $this->oImapClient->FolderStatusList($sParent, $sListPattern)
|
? $this->oImapClient->FolderStatusList($sParent, $sListPattern)
|
||||||
: $this->oImapClient->FolderList($sParent, $sListPattern);
|
: $this->oImapClient->FolderList($sParent, $sListPattern);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue