mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-02-25 07:16:21 +08:00
RFC 5464 Metadata improvements as for #152
This commit is contained in:
parent
73eb89b4ee
commit
474c2b9f95
7 changed files with 164 additions and 47 deletions
|
@ -28,4 +28,13 @@ abstract class FolderType
|
|||
const FLAGGED = 11;
|
||||
const ARCHIVE = 12;
|
||||
const ALL = 13;
|
||||
|
||||
// Kolab
|
||||
const CONFIGURATION = 20;
|
||||
const CALENDAR = 21;
|
||||
const CONTACTS = 22;
|
||||
const TASKS = 23;
|
||||
const NOTES = 24;
|
||||
const FILES = 25;
|
||||
const JOURNAL = 26;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2021 DJMaze
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Imap\Enumerations;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Imap
|
||||
* @subpackage Enumerations
|
||||
*/
|
||||
abstract class MetadataKeys
|
||||
{
|
||||
const
|
||||
// RFC 5464
|
||||
ADMIN_SHARED = '/shared/admin', // Server
|
||||
COMMENT = '/private/comment', // Mailbox
|
||||
COMMENT_SHARED = '/shared/comment', // Server & Mailbox
|
||||
|
||||
// RFC 6154
|
||||
SPECIALUSE = '/private/specialuse',
|
||||
|
||||
// Kolab
|
||||
KOLAB_CTYPE = '/private/vendor/kolab/folder-type',
|
||||
KOLAB_CTYPE_SHARED = '/shared/vendor/kolab/folder-type',
|
||||
KOLAB_COLOR = '/private/vendor/kolab/color',
|
||||
KOLAB_COLOR_SHARED = '/shared/vendor/kolab/color',
|
||||
KOLAB_NAME = '/private/vendor/kolab/displayname',
|
||||
KOLAB_NAME_SHARED = '/shared/vendor/kolab/displayname',
|
||||
KOLAB_UID_SHARED = '/shared/vendor/kolab/uniqueid',
|
||||
CYRUS_UID_SHARED = '/shared/vendor/cmu/cyrus-imapd/uniqueid';
|
||||
}
|
|
@ -160,4 +160,12 @@ class Folder
|
|||
{
|
||||
return isset($this->aMetadata[$sName]) ? $this->aMetadata[$sName] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function Metadata() : array
|
||||
{
|
||||
return $this->aMetadata;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
$sCmd = 'LIST';
|
||||
}
|
||||
|
||||
$sListPattern = 0 === strlen(trim($sListPattern)) ? '*' : $sListPattern;
|
||||
$sListPattern = \strlen(\trim($sListPattern)) ? $sListPattern : '*';
|
||||
|
||||
$aParameters = array(
|
||||
$this->EscapeString($sParentFolderName),
|
||||
|
@ -470,7 +470,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
// RFC 5464
|
||||
if ($this->IsSupported('METADATA')) {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
foreach ($this->FolderGetMetadata($oFolder->FullNameRaw(), ['/shared', '/private'], ['DEPTH'=>'infinity']) as $key => $value) {
|
||||
foreach ($this->getMetadata($oFolder->FullNameRaw(), ['/shared', '/private'], ['DEPTH'=>'infinity']) as $key => $value) {
|
||||
$oFolder->SetMetadata($key, $value);
|
||||
}
|
||||
}
|
||||
|
@ -1754,28 +1754,8 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
* RFC 5464
|
||||
*/
|
||||
|
||||
const
|
||||
ADMIN_SHARED = '/shared/admin', // Server
|
||||
COMMENT_SHARED = '/shared/comment', // Server & Mailbox
|
||||
COMMENT_PRIVATE = '/private/comment', // Mailbox
|
||||
// RFC 6154
|
||||
SPECIALUSE_PRIVATE = '/private/specialuse',
|
||||
// Kolab
|
||||
KOLAB_CTYPE_KEY_SHARED = '/shared/vendor/kolab/folder-type',
|
||||
KOLAB_CTYPE_KEY_PRIVATE = '/private/vendor/kolab/folder-type',
|
||||
KOLAB_COLOR_KEY_SHARED = '/shared/vendor/kolab/color',
|
||||
KOLAB_COLOR_KEY_PRIVATE = '/private/vendor/kolab/color',
|
||||
KOLAB_NAME_KEY_SHARED = '/shared/vendor/kolab/displayname',
|
||||
KOLAB_NAME_KEY_PRIVATE = '/private/vendor/kolab/displayname',
|
||||
KOLAB_UID_KEY_SHARED = '/shared/vendor/kolab/uniqueid',
|
||||
CYRUS_UID_KEY_SHARED = '/shared/vendor/cmu/cyrus-imapd/uniqueid';
|
||||
|
||||
public function FolderGetMetadata(string $sFolderName, array $aEntries, array $aOptions = []) : array
|
||||
private function getMetadata(string $sFolderName, array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
if (!$this->IsSupported('METADATA') && !(!\strlen($sFolderName) && $this->IsSupported('METADATA-SERVER'))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$arguments = [];
|
||||
|
||||
if ($aOptions) {
|
||||
|
@ -1801,8 +1781,23 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
return $this->SendRequestGetResponse('GETMETADATA', $arguments)->getFolderMetadataResult();
|
||||
}
|
||||
|
||||
public function FolderSetMetadata(string $sFolderName, array $aEntries)
|
||||
public function ServerGetMetadata(array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
return $this->IsSupported('METADATA-SERVER')
|
||||
? $this->getMetadata('', $aEntries, $aOptions)
|
||||
: [];
|
||||
}
|
||||
|
||||
public function FolderGetMetadata(string $sFolderName, array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
return $this->IsSupported('METADATA')
|
||||
? $this->getMetadata($sFolderName, $aEntries, $aOptions)
|
||||
: [];
|
||||
}
|
||||
|
||||
public function FolderSetMetadata(string $sFolderName, array $aEntries) : void
|
||||
{
|
||||
if ($this->IsSupported('METADATA')) {
|
||||
if (!$aEntries) {
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException("Wrong argument for SETMETADATA command");
|
||||
}
|
||||
|
@ -1814,12 +1809,8 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
});
|
||||
$arguments[] = '(' . \implode(' ', $aEntries) . ')';
|
||||
|
||||
$result = $this->SendRequestGetResponse('SETMETADATA', $arguments);
|
||||
$this->SendRequestGetResponse('SETMETADATA', $arguments);
|
||||
}
|
||||
|
||||
public function FolderDeleteMetadata($sFolderName, array $aEntries)
|
||||
{
|
||||
$this->SetMetadata($sFolderName, \array_fill_keys(\array_keys($aEntries), null));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -131,7 +131,9 @@ class ResponseCollection extends \MailSo\Base\Collection
|
|||
$c = \count($oResponse->ResponseList[3]);
|
||||
for ($i = 0; $i < $c; $i += 2) {
|
||||
$value = $oResponse->ResponseList[3][$i+1];
|
||||
$aReturn[$oResponse->ResponseList[3][$i]] = ('NIL' === $value) ? null : $value;
|
||||
if ('NIL' !== $value) {
|
||||
$aReturn[$oResponse->ResponseList[3][$i]] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace MailSo\Mail;
|
||||
|
||||
use MailSo\Imap\Enumerations\MetadataKeys;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Mail
|
||||
|
@ -188,6 +190,7 @@ class Folder implements \JsonSerializable
|
|||
public function GetFolderListType() : int
|
||||
{
|
||||
$aFlags = $this->oImapFolder->FlagsLowerCase();
|
||||
// $aFlags[] = \strtolower($this->oImapFolder->GetMetadata(MetadataKeys::SPECIALUSE));
|
||||
|
||||
switch (true)
|
||||
{
|
||||
|
@ -224,9 +227,49 @@ class Folder implements \JsonSerializable
|
|||
return \MailSo\Imap\Enumerations\FolderType::ALL;
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Kolab
|
||||
switch ($this->oImapFolder->GetMetadata(MetadataKeys::KOLAB_CTYPE) ?: $this->oImapFolder->GetMetadata(MetadataKeys::KOLAB_CTYPE_SHARED)) {
|
||||
{
|
||||
case 'event':
|
||||
return \MailSo\Imap\Enumerations\FolderType::CALENDAR;
|
||||
case 'contact':
|
||||
return \MailSo\Imap\Enumerations\FolderType::CONTACTS;
|
||||
case 'task':
|
||||
return \MailSo\Imap\Enumerations\FolderType::TASKS;
|
||||
case 'note':
|
||||
return \MailSo\Imap\Enumerations\FolderType::NOTES;
|
||||
case 'file':
|
||||
return \MailSo\Imap\Enumerations\FolderType::FILES;
|
||||
case 'configuration':
|
||||
return \MailSo\Imap\Enumerations\FolderType::CONFIGURATION;
|
||||
case 'journal':
|
||||
return \MailSo\Imap\Enumerations\FolderType::JOURNAL;
|
||||
case 'mail.inbox':
|
||||
return \MailSo\Imap\Enumerations\FolderType::INBOX;
|
||||
case 'mail.drafts':
|
||||
return \MailSo\Imap\Enumerations\FolderType::DRAFTS;
|
||||
case 'mail.sentitems':
|
||||
return \MailSo\Imap\Enumerations\FolderType::SENT;
|
||||
case 'mail.wastebasket':
|
||||
return \MailSo\Imap\Enumerations\FolderType::TRASH;
|
||||
// case 'mail.outbox':
|
||||
case 'mail.junkemail':
|
||||
return \MailSo\Imap\Enumerations\FolderType::JUNK;
|
||||
}
|
||||
*/
|
||||
|
||||
return \MailSo\Imap\Enumerations\FolderType::USER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetMetadata(string $sName) : ?string
|
||||
{
|
||||
return $this->oImapFolder->GetMetadata($sName);
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return array(
|
||||
|
@ -239,7 +282,8 @@ class Folder implements \JsonSerializable
|
|||
'Subscribed' => $this->bSubscribed,
|
||||
'Exists' => $this->bExists,
|
||||
'Selectable' => $this->IsSelectable(),
|
||||
'Flags' => $this->FlagsLowerCase()
|
||||
'Flags' => $this->FlagsLowerCase(),
|
||||
'Metadata' => $this->oImapFolder->Metadata()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ class MailClient
|
|||
{
|
||||
if (!$bSkipUnsupportedFlag)
|
||||
{
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException('Message flag "'.$sMessageFlag.'" is not supported.');
|
||||
throw new Exceptions\RuntimeException('Message flag "'.$sMessageFlag.'" is not supported.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,7 @@ class MailClient
|
|||
{
|
||||
if (!$bSkipUnsupportedFlag)
|
||||
{
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException('Message flag "'.$sMessageFlag.'" is not supported.');
|
||||
throw new Exceptions\RuntimeException('Message flag "'.$sMessageFlag.'" is not supported.');
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2095,7 +2095,7 @@ class MailClient
|
|||
if (!$aFolders)
|
||||
{
|
||||
// TODO: Translate
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException(
|
||||
throw new Exceptions\RuntimeException(
|
||||
\strlen($sFolderParentFullNameRaw)
|
||||
? 'Cannot create folder in non-existent parent folder.'
|
||||
: 'Cannot get folder delimiter.');
|
||||
|
@ -2115,7 +2115,7 @@ class MailClient
|
|||
if (\strlen($sDelimiter) && false !== \strpos($sFullNameRawToCreate, $sDelimiter))
|
||||
{
|
||||
// TODO: Translate
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException(
|
||||
throw new Exceptions\RuntimeException(
|
||||
'New folder name contains delimiter.');
|
||||
}
|
||||
|
||||
|
@ -2161,7 +2161,7 @@ class MailClient
|
|||
if (!$aFolders)
|
||||
{
|
||||
// TODO: Translate
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException('Cannot '.($bRename?'rename':'move').' non-existent folder.');
|
||||
throw new Exceptions\RuntimeException('Cannot '.($bRename?'rename':'move').' non-existent folder.');
|
||||
}
|
||||
|
||||
$sDelimiter = $aFolders[0]->Delimiter();
|
||||
|
@ -2186,7 +2186,7 @@ class MailClient
|
|||
if (\strlen($sDelimiter) && false !== \strpos($sNewFolderFullNameRaw, $sDelimiter))
|
||||
{
|
||||
// TODO: Translate
|
||||
throw new \MailSo\Mail\Exceptions\RuntimeException('New folder name contains delimiter.');
|
||||
throw new Exceptions\RuntimeException('New folder name contains delimiter.');
|
||||
}
|
||||
|
||||
$sFolderParentFullNameRaw = false === $iLast ? '' : \substr($sPrevFolderFullNameRaw, 0, $iLast + 1);
|
||||
|
@ -2226,7 +2226,7 @@ class MailClient
|
|||
$aIndexOrUids = $this->oImapClient->MessageSimpleSearch('ALL');
|
||||
if (\count($aIndexOrUids))
|
||||
{
|
||||
throw new \MailSo\Mail\Exceptions\NonEmptyFolder;
|
||||
throw new Exceptions\NonEmptyFolder;
|
||||
}
|
||||
|
||||
$this->oImapClient->FolderExamine('INBOX');
|
||||
|
@ -2292,4 +2292,28 @@ class MailClient
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC 5464
|
||||
*/
|
||||
|
||||
public function ServerGetMetadata(array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
return $this->oImapClient->ServerGetMetadata($aEntries, $aOptions);
|
||||
}
|
||||
|
||||
public function FolderGetMetadata(string $sFolderName, array $aEntries, array $aOptions = []) : array
|
||||
{
|
||||
return $this->oImapClient->FolderGetMetadata($sFolderName, $aEntries, $aOptions);
|
||||
}
|
||||
|
||||
public function FolderSetMetadata(string $sFolderName, array $aEntries) : void
|
||||
{
|
||||
$this->oImapClient->FolderSetMetadata($sFolderName, $aEntries);
|
||||
}
|
||||
|
||||
public function FolderDeleteMetadata($sFolderName, array $aEntries) : void
|
||||
{
|
||||
$this->oImapClient->FolderSetMetadata($sFolderName, \array_fill_keys(\array_keys($aEntries), null));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue