mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-10 15:08:28 +03:00
Dovecot supports
This commit is contained in:
parent
4fdfd54f87
commit
796b10dc14
4 changed files with 99 additions and 41 deletions
|
|
@ -20,6 +20,40 @@ namespace MailSo\Imap\Commands;
|
|||
trait Metadata
|
||||
{
|
||||
|
||||
/**
|
||||
* Dovecot 2.2+ supports fetching all METADATA at once (wildcard).
|
||||
* RFC 5464 doesn't specify this, but its earlier draft did, and Kolab uses it.
|
||||
*/
|
||||
public function getAllMetadata() : array
|
||||
{
|
||||
$aReturn = array();
|
||||
try {
|
||||
$arguments = [
|
||||
'(DEPTH infinity)',
|
||||
$this->EscapeString('*')
|
||||
];
|
||||
$arguments[] = '(' . \implode(' ', \array_map([$this, 'EscapeString'], ['/shared', '/private'])) . ')';
|
||||
$oResult = $this->SendRequestGetResponse('GETMETADATA', $arguments);
|
||||
foreach ($oResult as $oResponse) {
|
||||
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
||||
&& 4 === \count($oResponse->ResponseList)
|
||||
&& 'METADATA' === $oResponse->ResponseList[1]
|
||||
&& \is_array($oResponse->ResponseList[3]))
|
||||
{
|
||||
$aMetadata = array();
|
||||
$c = \count($oResponse->ResponseList[3]);
|
||||
for ($i = 0; $i < $c; $i += 2) {
|
||||
$aMetadata[$oResponse->ResponseList[3][$i]] = $oResponse->ResponseList[3][$i+1];
|
||||
}
|
||||
$aReturn[$oResponse->ResponseList[2]] = $aMetadata;
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
//\error_log($e->getMessage());
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
public function getMetadata(string $sFolderName, array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
$arguments = [];
|
||||
|
|
@ -44,7 +78,23 @@ trait Metadata
|
|||
$arguments[] = $this->EscapeString($sFolderName);
|
||||
|
||||
$arguments[] = '(' . \implode(' ', \array_map([$this, 'EscapeString'], $aEntries)) . ')';
|
||||
return $this->SendRequestGetResponse('GETMETADATA', $arguments)->getFolderMetadataResult();
|
||||
|
||||
$oResult = $this->SendRequestGetResponse('GETMETADATA', $arguments);
|
||||
|
||||
$aReturn = array();
|
||||
foreach ($oResult as $oResponse) {
|
||||
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
||||
&& 4 === \count($oResponse->ResponseList)
|
||||
&& 'METADATA' === $oResponse->ResponseList[1]
|
||||
&& \is_array($oResponse->ResponseList[3]))
|
||||
{
|
||||
$c = \count($oResponse->ResponseList[3]);
|
||||
for ($i = 0; $i < $c; $i += 2) {
|
||||
$aReturn[$oResponse->ResponseList[3][$i]] = $oResponse->ResponseList[3][$i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
public function ServerGetMetadata(array $aEntries, array $aOptions = []) : array
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ class Folder
|
|||
$this->aMetadata[$sName] = $sData;
|
||||
}
|
||||
|
||||
public function SetAllMetadata(array $aMetadata) : void
|
||||
{
|
||||
$this->aMetadata = $aMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -534,35 +534,30 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
$this->SendRequest($sCmd, $aParameters);
|
||||
$bPassthru = false;
|
||||
if ($bPassthru) {
|
||||
// TODO: passthru to parse response in JavaScript
|
||||
// This will reduce CPU time on server and moves it to the client
|
||||
// And can be used with the new JavaScript AbstractFetchRemote.streamPerLine(fCallback, sGetAdd)
|
||||
if (\is_resource($this->ConnectionResource())) {
|
||||
\SnappyMail\HTTP\Stream::start();
|
||||
$sEndTag = $this->getCurrentTag();
|
||||
$sLine = \fgets($this->ConnectionResource());
|
||||
do {
|
||||
echo $sLine;
|
||||
if (0 === \strpos($sLine, $sEndTag)) {
|
||||
break;
|
||||
}
|
||||
$sLine = \fgets($this->ConnectionResource());
|
||||
} while (\strlen($sLine));
|
||||
exit;
|
||||
}
|
||||
$this->streamResponse();
|
||||
} else {
|
||||
$aReturn = $this->getResponse()->getFoldersResult($sCmd);
|
||||
}
|
||||
|
||||
// RFC 5464
|
||||
if (!$bIsSubscribeList && $this->IsSupported('METADATA')) {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
try {
|
||||
foreach ($this->getMetadata($oFolder->FullNameRaw(), ['/shared', '/private'], ['DEPTH'=>'infinity']) as $key => $value) {
|
||||
$oFolder->SetMetadata($key, $value);
|
||||
// Dovecot supports fetching all METADATA at once
|
||||
$aMetadata = $this->getAllMetadata();
|
||||
if ($aMetadata) {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
if (isset($aMetadata[$oFolder->FullNameRaw()])) {
|
||||
$oFolder->SetAllMetadata($aMetadata[$oFolder->FullNameRaw()]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
try {
|
||||
$oFolder->SetAllMetadata(
|
||||
$this->getMetadata($oFolder->FullNameRaw(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore error
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1099,10 +1094,36 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
}
|
||||
|
||||
/**
|
||||
* TODO: passthru to parse response in JavaScript
|
||||
* This will reduce CPU time on server and moves it to the client
|
||||
* And can be used with the new JavaScript AbstractFetchRemote.streamPerLine(fCallback, sGetAdd)
|
||||
*
|
||||
* @throws \MailSo\Imap\Exceptions\ResponseNotFoundException
|
||||
* @throws \MailSo\Imap\Exceptions\InvalidResponseException
|
||||
* @throws \MailSo\Imap\Exceptions\NegativeResponseException
|
||||
*/
|
||||
private function streamResponse(string $sEndTag = null) : void
|
||||
{
|
||||
try {
|
||||
if (\is_resource($this->ConnectionResource())) {
|
||||
\SnappyMail\HTTP\Stream::start();
|
||||
$sEndTag = $sEndTag ?: $this->getCurrentTag();
|
||||
$sLine = \fgets($this->ConnectionResource());
|
||||
do {
|
||||
echo $sLine;
|
||||
if (0 === \strpos($sLine, $sEndTag)) {
|
||||
break;
|
||||
}
|
||||
$sLine = \fgets($this->ConnectionResource());
|
||||
} while (\strlen($sLine));
|
||||
exit;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->writeLogException($e, \MailSo\Log\Enumerations\Type::WARNING);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function getResponse(string $sEndTag = null) : ResponseCollection
|
||||
{
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -88,24 +88,6 @@ class ResponseCollection extends \MailSo\Base\Collection
|
|||
return $aReturn;
|
||||
}
|
||||
|
||||
public function getFolderMetadataResult() : array
|
||||
{
|
||||
$aReturn = array();
|
||||
foreach ($this as $oResponse) {
|
||||
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
||||
&& 4 === \count($oResponse->ResponseList)
|
||||
&& 'METADATA' === $oResponse->ResponseList[1]
|
||||
&& \is_array($oResponse->ResponseList[3]))
|
||||
{
|
||||
$c = \count($oResponse->ResponseList[3]);
|
||||
for ($i = 0; $i < $c; $i += 2) {
|
||||
$aReturn[$oResponse->ResponseList[3][$i]] = $oResponse->ResponseList[3][$i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
public function getFoldersResult(string $sStatus) : array
|
||||
{
|
||||
$aReturn = array();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue