diff --git a/dev/Model/FolderCollection.js b/dev/Model/FolderCollection.js index 66c14cefe..fee11b3bd 100644 --- a/dev/Model/FolderCollection.js +++ b/dev/Model/FolderCollection.js @@ -105,7 +105,6 @@ export class FolderCollectionModel extends AbstractCollectionModel constructor() { super(); this.CountRec - this.IsThreadsSupported this.Namespace; this.Optimized this.SystemFolders @@ -200,7 +199,10 @@ export class FolderCollectionModel extends AbstractCollectionModel FolderUserStore.namespace = this.Namespace; - AppUserStore.threadsAllowed(!!(Settings.app('useImapThread') && this.IsThreadsSupported)); + // 'THREAD=REFS', 'THREAD=REFERENCES', 'THREAD=ORDEREDSUBJECT' + AppUserStore.threadsAllowed(!!( + Settings.app('useImapThread') && this.Capabilities.some(capa => capa.startsWith('THREAD=')) + )); FolderUserStore.folderListOptimized(!!this.Optimized); FolderUserStore.quotaUsage(this.quotaUsage); diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php index f1866b2a0..8b75f2212 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php @@ -29,12 +29,13 @@ trait Folders * @throws \MailSo\Net\Exceptions\* * @throws \MailSo\Imap\Exceptions\* */ - public function FolderCreate(string $sFolderName) : self + public function FolderCreate(string $sFolderName, bool $bSubscribe = false) : self { $this->SendRequestGetResponse('CREATE', array( $this->EscapeFolderName($sFolderName) // , ['(USE (\Drafts \Sent))'] RFC 6154 )); + $bSubscribe && $this->FolderSubscribe($sFolderName); return $this; } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php index 30cc4aabc..e59571956 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php @@ -11,11 +11,14 @@ namespace MailSo\Imap; +use MailSo\Imap\Enumerations\FolderType; +use MailSo\Imap\Enumerations\MetadataKeys; + /** * @category MailSo * @package Imap */ -class Folder +class Folder implements \JsonSerializable { // RFC5258 Response data STATUS items when using LIST-EXTENDED use Traits\Status; @@ -54,6 +57,11 @@ class Folder $this->aFlagsLowerCase = \array_map('mb_strtolower', $aFlags); } + public function setSubscribed() : void + { + $this->aFlagsLowerCase = \array_unique(\array_merge($this->aFlagsLowerCase, ['\\subscribed'])); + } + public function setDelimiter(?string $sDelimiter) : void { $this->sDelimiter = $sDelimiter; @@ -84,9 +92,19 @@ class Folder return $this->aFlagsLowerCase; } - public function IsSelectable() : bool + public function Exists() : bool { - return !\in_array('\\noselect', $this->aFlagsLowerCase) && !\in_array('\\nonexistent', $this->aFlagsLowerCase); + return !\in_array('\\nonexistent', $this->aFlagsLowerCase); + } + + public function Selectable() : bool + { + return !\in_array('\\noselect', $this->aFlagsLowerCase) && $this->Exists(); + } + + public function IsSubscribed() : bool + { + return \in_array('\\subscribed', $this->aFlagsLowerCase); } public function IsInbox() : bool @@ -113,4 +131,195 @@ class Folder { return $this->aMetadata; } + + // JMAP RFC 8621 + public function Role() : ?string + { + $aFlags = $this->aFlagsLowerCase; + $aFlags[] = \strtolower($this->GetMetadata(MetadataKeys::SPECIALUSE)); + + $match = \array_intersect([ + '\\inbox', + '\\all', // '\\allmail' + '\\archive', + '\\drafts', + '\\flagged', // '\\starred' + '\\important', + '\\junk', // '\\spam' + '\\sent', // '\\sentmail' + '\\trash', // '\\bin' + ], $aFlags); + if ($match) { + return \substr(\array_shift($match), 1); + } + + if ('INBOX' === \strtoupper($this->FolderName)) { + return 'inbox'; + } +/* + // Kolab + $type = $this->GetMetadata(MetadataKeys::KOLAB_CTYPE) ?: $this->GetMetadata(MetadataKeys::KOLAB_CTYPE_SHARED); + switch ($type) { + case 'mail.inbox': + return 'inbox'; +// case 'mail.outbox': + case 'mail.sentitems': + return 'sent'; + case 'mail.drafts': + return 'drafts'; + case 'mail.junkemail': + return 'junk'; + case 'mail.wastebasket': + return 'trash'; + } +*/ + return null; + } + + public function Hash(string $sClientHash) : ?string + { + return $this->getHash($sClientHash); + } + + public function GetType() : int + { + $aFlags = $this->aFlagsLowerCase; + // RFC 6154 +// $aFlags[] = \strtolower($this->GetMetadata(MetadataKeys::SPECIALUSE)); + + switch (true) + { + case $this->IsInbox(): + return FolderType::INBOX; + + case \in_array('\\sent', $this->aFlagsLowerCase): + case \in_array('\\sentmail', $this->aFlagsLowerCase): + return FolderType::SENT; + + case \in_array('\\drafts', $this->aFlagsLowerCase): + return FolderType::DRAFTS; + + case \in_array('\\junk', $this->aFlagsLowerCase): + case \in_array('\\spam', $this->aFlagsLowerCase): + return FolderType::JUNK; + + case \in_array('\\trash', $this->aFlagsLowerCase): + case \in_array('\\bin', $this->aFlagsLowerCase): + return FolderType::TRASH; + + case \in_array('\\important', $this->aFlagsLowerCase): + return FolderType::IMPORTANT; + + case \in_array('\\flagged', $this->aFlagsLowerCase): + case \in_array('\\starred', $this->aFlagsLowerCase): + return FolderType::FLAGGED; + + case \in_array('\\archive', $this->aFlagsLowerCase): + return FolderType::ARCHIVE; + + case \in_array('\\all', $this->aFlagsLowerCase): + case \in_array('\\allmail', $this->aFlagsLowerCase): + return FolderType::ALL; + + // TODO +// case 'Templates' === $this->FullName(): +// return FolderType::TEMPLATES; + } + + // Kolab + $type = $this->GetMetadata(MetadataKeys::KOLAB_CTYPE) ?: $this->GetMetadata(MetadataKeys::KOLAB_CTYPE_SHARED); + switch ($type) + { +/* + // TODO: Kolab + case 'event': + case 'event.default': + return FolderType::CALENDAR; + case 'contact': + case 'contact.default': + return FolderType::CONTACTS; + case 'task': + case 'task.default': + return FolderType::TASKS; + case 'note': + case 'note.default': + return FolderType::NOTES; + case 'file': + case 'file.default': + return FolderType::FILES; + case 'configuration': + return FolderType::CONFIGURATION; + case 'journal': + case 'journal.default': + return FolderType::JOURNAL; +*/ + case 'mail.inbox': + return FolderType::INBOX; +// case 'mail.outbox': + case 'mail.sentitems': + return FolderType::SENT; + case 'mail.drafts': + return FolderType::DRAFTS; + case 'mail.junkemail': + return FolderType::JUNK; + case 'mail.wastebasket': + return FolderType::TRASH; + } + + return FolderType::USER; + } + + #[\ReturnTypeWillChange] + public function jsonSerialize() + { +/* + $aExtended = null; + if (isset($this->MESSAGES, $this->UNSEEN, $this->UIDNEXT)) { + $aExtended = array( + 'totalEmails' => (int) $this->MESSAGES, + 'unreadEmails' => (int) $this->UNSEEN, + 'UidNext' => (int) $this->UIDNEXT, +// 'Hash' => $this->Hash($this->MailClient()->GenerateImapClientHash()) + ); + } +*/ +/* + if ($this->ImapClient->IsSupported('ACL') || $this->ImapClient->CapabilityValue('RIGHTS')) { + // MailSo\Imap\Responses\ACL + $rights = $this->ImapClient->FolderMyRights($this->FolderName); + } +*/ + return array( + '@Object' => 'Object/Folder', + 'name' => $this->Name(), + 'FullName' => $this->FolderName, + 'Delimiter' => (string) $this->sDelimiter, + 'isSubscribed' => $this->IsSubscribed(), + 'Exists' => $this->Exists(), + 'Selectable' => $this->Selectable(), + 'Flags' => $this->aFlagsLowerCase, +// 'Extended' => $aExtended, +// 'PermanentFlags' => $this->PermanentFlags, + 'Metadata' => $this->aMetadata, + 'UidNext' => $this->UIDNEXT, + // https://datatracker.ietf.org/doc/html/rfc8621#section-2 + 'totalEmails' => $this->MESSAGES, + 'unreadEmails' => $this->UNSEEN, + 'id' => $this->MAILBOXID, + 'role' => $this->Role() +/* + 'myRights' => [ + 'mayReadItems' => !$rights || ($rights->hasRight('l') && $rights->hasRight('r')), + 'mayAddItems' => !$rights || $rights->hasRight('i'), + 'mayRemoveItems' => !$rights || ($rights->hasRight('t') && $rights->hasRight('e')), + 'maySetSeen' => !$rights || $rights->hasRight('s'), + 'maySetKeywords' => !$rights || $rights->hasRight('w'), + 'mayCreateChild' => !$rights || $rights->hasRight('k'), + 'mayRename' => !$rights || $rights->hasRight('x'), + 'mayDelete' => !$rights || $rights->hasRight('x'), + 'maySubmit' => !$rights || $rights->hasRight('p') + ] +*/ + ); + } } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Folder.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Folder.php deleted file mode 100644 index a29af3361..000000000 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Folder.php +++ /dev/null @@ -1,260 +0,0 @@ -oImapFolder = $oImapFolder; - $this->bSubscribed = $bSubscribed || \in_array('\\subscribed', $oImapFolder->FlagsLowerCase()); - $this->bExists = $bExists; - } - - /** - * @throws \InvalidArgumentException - * @throws \InvalidArgumentException - */ - public static function NewNonExistentInstance(string $sFullName, string $sDelimiter) : self - { - return new self( - new \MailSo\Imap\Folder($sFullName, $sDelimiter, array('\\Noselect')), false, false); - } - - public function Name() : string - { - return $this->oImapFolder->Name(); - } - - public function FullName() : string - { - return $this->oImapFolder->FullName(); - } - - public function NameRaw() : string - { - return $this->oImapFolder->NameRaw(); - } - - public function Delimiter() : ?string - { - return $this->oImapFolder->Delimiter(); - } - - public function FlagsLowerCase() : array - { - return $this->oImapFolder->FlagsLowerCase(); - } - - public function IsSubscribed() : bool - { - return $this->bSubscribed; - } - - public function IsExists() : bool - { - return $this->bExists; - } - - public function IsSelectable() : bool - { - return $this->bExists && $this->oImapFolder->IsSelectable(); - } - - public function Hash(string $sClientHash) : ?string - { - return $this->oImapFolder->getHash($sClientHash); - } - - public function IsInbox() : bool - { - return $this->oImapFolder->IsInbox(); - } - - public function GetType() : int - { - $aFlags = $this->oImapFolder->FlagsLowerCase(); - // RFC 6154 -// $aFlags[] = \strtolower($this->oImapFolder->GetMetadata(MetadataKeys::SPECIALUSE)); - - switch (true) - { - case \in_array('\\inbox', $aFlags) || 'INBOX' === \strtoupper($this->FullName()): - return FolderType::INBOX; - - case \in_array('\\sent', $aFlags): - case \in_array('\\sentmail', $aFlags): - return FolderType::SENT; - - case \in_array('\\drafts', $aFlags): - return FolderType::DRAFTS; - - case \in_array('\\junk', $aFlags): - case \in_array('\\spam', $aFlags): - return FolderType::JUNK; - - case \in_array('\\trash', $aFlags): - case \in_array('\\bin', $aFlags): - return FolderType::TRASH; - - case \in_array('\\important', $aFlags): - return FolderType::IMPORTANT; - - case \in_array('\\flagged', $aFlags): - case \in_array('\\starred', $aFlags): - return FolderType::FLAGGED; - - case \in_array('\\archive', $aFlags): - return FolderType::ARCHIVE; - - case \in_array('\\all', $aFlags): - case \in_array('\\allmail', $aFlags): - return FolderType::ALL; - - // TODO -// case 'Templates' === $this->FullName(): -// return FolderType::TEMPLATES; - } - - // Kolab - $type = $this->GetMetadata(MetadataKeys::KOLAB_CTYPE) ?: $this->GetMetadata(MetadataKeys::KOLAB_CTYPE_SHARED); - switch ($type) - { -/* - // TODO: Kolab - case 'event': - case 'event.default': - return FolderType::CALENDAR; - case 'contact': - case 'contact.default': - return FolderType::CONTACTS; - case 'task': - case 'task.default': - return FolderType::TASKS; - case 'note': - case 'note.default': - return FolderType::NOTES; - case 'file': - case 'file.default': - return FolderType::FILES; - case 'configuration': - return FolderType::CONFIGURATION; - case 'journal': - case 'journal.default': - return FolderType::JOURNAL; -*/ - case 'mail.inbox': - return FolderType::INBOX; -// case 'mail.outbox': - case 'mail.sentitems': - return FolderType::SENT; - case 'mail.drafts': - return FolderType::DRAFTS; - case 'mail.junkemail': - return FolderType::JUNK; - case 'mail.wastebasket': - return FolderType::TRASH; - } - - return FolderType::USER; - } - - /** - * @return mixed - */ - public function GetMetadata(string $sName) : ?string - { - return $this->oImapFolder->GetMetadata($sName); - } - - #[\ReturnTypeWillChange] - public function jsonSerialize() - { -/* - $aExtended = null; - if (isset($this->oImapFolder->MESSAGES, $this->oImapFolder->UNSEEN, $this->oImapFolder->UIDNEXT)) { - $aExtended = array( - 'totalEmails' => (int) $this->oImapFolder->MESSAGES, - 'unreadEmails' => (int) $this->oImapFolder->UNSEEN, - 'UidNext' => (int) $this->oImapFolder->UIDNEXT, -// 'Hash' => $this->Hash($this->MailClient()->GenerateImapClientHash()) - ); - } -*/ -/* - $types = [ - FolderType::INBOX => 'inbox', - FolderType::ALL => 'all', - FolderType::ARCHIVE => 'archive', - FolderType::DRAFTS => 'drafts', - FolderType::FLAGGED => 'flagged', - FolderType::IMPORTANT => 'important', - FolderType::JUNK => 'junk', - FolderType::SENT => 'sent', - FolderType::TRASH => 'trash', - ]; - $type = $this->GetType(); -*/ - return array( - '@Object' => 'Object/Folder', - 'name' => $this->Name(), - 'FullName' => $this->FullName(), - 'Delimiter' => (string) $this->Delimiter(), - 'isSubscribed' => $this->bSubscribed, - 'Exists' => $this->bExists, - 'Selectable' => $this->IsSelectable(), - 'Flags' => $this->FlagsLowerCase(), -// 'Extended' => $aExtended, -// 'PermanentFlags' => $this->oImapFolder->PermanentFlags, - 'Metadata' => $this->oImapFolder->Metadata(), - 'UidNext' => $this->oImapFolder->UIDNEXT, - // https://datatracker.ietf.org/doc/html/rfc8621#section-2 - 'totalEmails' => $this->oImapFolder->MESSAGES, - 'unreadEmails' => $this->oImapFolder->UNSEEN, - 'id' => $this->oImapFolder->MAILBOXID, -/* - 'role' => isset($types[$type]) ? $types[$type] : null, - - if ($this->IsSupported('ACL') || $this->CapabilityValue('RIGHTS')) { - $rights = $this->FolderMyRights($this->FullName()); - } - 'myRights' => [ - 'mayReadItems' => !$rights || ($rights->hasRight('l') && $rights->hasRight('r')), - 'mayAddItems' => !$rights || $rights->hasRight('i'), - 'mayRemoveItems' => !$rights || ($rights->hasRight('t') && $rights->hasRight('e')), - 'maySetSeen' => !$rights || $rights->hasRight('s'), - 'maySetKeywords' => !$rights || $rights->hasRight('w'), - 'mayCreateChild' => !$rights || $rights->hasRight('k'), - 'mayRename' => !$rights || $rights->hasRight('x'), - 'mayDelete' => !$rights || $rights->hasRight('x'), - 'maySubmit' => !$rights || $rights->hasRight('p') - ] -*/ - ); - } -} diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php index 4e82c6af3..c36039593 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php @@ -17,16 +17,11 @@ namespace MailSo\Mail; */ class FolderCollection extends \MailSo\Base\Collection { - /** - * @var bool - */ - public $Optimized = false; - - public $TotalCount = 0; + public bool $Optimized = false; public function append($oFolder, bool $bToTop = false) : void { - assert($oFolder instanceof Folder); + assert($oFolder instanceof \MailSo\Imap\Folder); parent::append($oFolder, $bToTop); } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 250ceb614..19b530f70 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -619,17 +619,6 @@ class MailClient } } - /** - * @throws \MailSo\RuntimeException - * @throws \MailSo\Net\Exceptions\* - */ - public function IsThreadsSupported() : bool - { - return $this->oImapClient->IsSupported('THREAD=REFS') || - $this->oImapClient->IsSupported('THREAD=REFERENCES') || - $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT'); - } - /** * @throws \InvalidArgumentException * @throws \MailSo\RuntimeException @@ -939,9 +928,7 @@ class MailClient } // $this->oImapClient->Settings->disable_list_status - $aFolders = $this->oImapClient->IsSupported('LIST-STATUS') - ? $this->oImapClient->FolderStatusList($sParent, $sListPattern) - : $this->oImapClient->FolderList($sParent, $sListPattern); + $aFolders = $this->oImapClient->FolderStatusList($sParent, $sListPattern); if (!$aFolders) { return null; } @@ -950,19 +937,14 @@ class MailClient $oFolderCollection = new FolderCollection; $oFolderCollection->Optimized = 10 < $iOptimizationLimit && \count($aFolders) > $iOptimizationLimit; - $sINBOX = 'INBOX'; foreach ($aFolders as $sFullName => /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) { - $oMailFolder = new Folder($oImapFolder, - ($bUseListSubscribeStatus && (null === $aImapSubscribedFoldersHelper || \in_array($sFullName, $aImapSubscribedFoldersHelper))) - || $oImapFolder->IsInbox() - ); - if ($oImapFolder->IsInbox()) { - $sINBOX = $sFullName; + if (($bUseListSubscribeStatus && (null === $aImapSubscribedFoldersHelper || \in_array($sFullName, $aImapSubscribedFoldersHelper))) || $oImapFolder->IsInbox()) { + $oImapFolder->setSubscribed(); } - $aFolders[$sFullName] = $oMailFolder; + $aFolders[$sFullName] = $oImapFolder; // Add NonExistent folders - $sDelimiter = $oMailFolder->Delimiter(); + $sDelimiter = $oImapFolder->Delimiter(); $aFolderExplode = \explode($sDelimiter, $sFullName); \array_pop($aFolderExplode); while ($aFolderExplode) { @@ -971,7 +953,7 @@ class MailClient try { $aFolders[$sNonExistentFolderFullName] = - Folder::NewNonExistentInstance($sNonExistentFolderFullName, $sDelimiter); + new \MailSo\Imap\Folder($sNonExistentFolderFullName, $sDelimiter, ['\\Noselect', '\\NonExistent']); } catch (\Throwable $oExc) { @@ -984,29 +966,24 @@ class MailClient $oFolderCollection->exchangeArray(\array_values($aFolders)); - $oFolderCollection->TotalCount = \count($aFolders); - return $oFolderCollection; } /** * @throws \InvalidArgumentException */ - public function FolderCreate(string $sFolderNameInUtf8, string $sFolderParentFullName = '', bool $bSubscribeOnCreation = true, string $sDelimiter = '') : ?Folder + public function FolderCreate(string $sFolderNameInUtf8, string $sFolderParentFullName = '', bool $bSubscribeOnCreation = true, string $sDelimiter = '') : ?\MailSo\Imap\Folder { $sFolderNameInUtf8 = \trim($sFolderNameInUtf8); $sFolderParentFullName = \trim($sFolderParentFullName); - if (!\strlen($sFolderNameInUtf8)) - { + if (!\strlen($sFolderNameInUtf8)) { throw new \InvalidArgumentException; } - if (!\strlen($sDelimiter) || \strlen($sFolderParentFullName)) - { + if (!\strlen($sDelimiter) || \strlen($sFolderParentFullName)) { $sDelimiter = $this->oImapClient->FolderHierarchyDelimiter($sFolderParentFullName); - if (null === $sDelimiter) - { + if (null === $sDelimiter) { // TODO: Translate throw new \MailSo\RuntimeException( \strlen($sFolderParentFullName) @@ -1014,14 +991,12 @@ class MailClient : 'Cannot get folder delimiter.'); } - if (\strlen($sDelimiter) && \strlen($sFolderParentFullName)) - { + if (\strlen($sDelimiter) && \strlen($sFolderParentFullName)) { $sFolderParentFullName .= $sDelimiter; } } - if (\strlen($sDelimiter) && false !== \strpos($sFolderNameInUtf8, $sDelimiter)) - { + if (\strlen($sDelimiter) && false !== \strpos($sFolderNameInUtf8, $sDelimiter)) { // TODO: Translate throw new \MailSo\RuntimeException( 'New folder name contains delimiter.'); @@ -1029,18 +1004,16 @@ class MailClient $sFullNameToCreate = $sFolderParentFullName.$sFolderNameInUtf8; - $this->oImapClient->FolderCreate($sFullNameToCreate); + $this->oImapClient->FolderCreate($sFullNameToCreate, $bSubscribeOnCreation); - if ($bSubscribeOnCreation) - { - $this->oImapClient->FolderSubscribe($sFullNameToCreate); + $aFolders = $this->oImapClient->FolderStatusList($sFullNameToCreate, ''); + if (isset($aFolders[$sFullNameToCreate])) { + $oImapFolder = $aFolders[$sFullNameToCreate]; + $bSubscribeOnCreation && $oImapFolder->setSubscribed(); + return $oImapFolder; } - $aFolders = $this->oImapClient->IsSupported('LIST-STATUS') - ? $this->oImapClient->FolderStatusList($sFullNameToCreate, '') - : $this->oImapClient->FolderList($sFullNameToCreate, ''); - $oImapFolder = $aFolders[$sFullNameToCreate]; - return $oImapFolder ? new Folder($oImapFolder, $bSubscribeOnCreation) : null; + return null; } /** diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php index 2235175ea..d59836205 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php @@ -58,8 +58,7 @@ trait Folders $oFolderCollection = $this->getFolderCollection($HideUnsubscribed); - if ($oFolderCollection) - { + if ($oFolderCollection) { $sNamespace = $this->MailClient()->GetPersonalNamespace(); $this->Plugins()->RunHook('filter.folders-post', array($oAccount, $oFolderCollection)); @@ -67,8 +66,7 @@ trait Folders $aSystemFolders = array(); $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders); - if ($this->Config()->Get('labs', 'autocreate_system_folders', false)) - { + if ($this->Config()->Get('labs', 'autocreate_system_folders', false)) { $bDoItAgain = false; $sParent = \substr($sNamespace, 0, -1); @@ -78,64 +76,51 @@ trait Folders $aList = array(); $aMap = $this->systemFoldersNames($oAccount); - if ('' === $oSettingsLocal->GetConf('SentFolder', '')) - { + if ('' === $oSettingsLocal->GetConf('SentFolder', '')) { $aList[] = FolderType::SENT; } - if ('' === $oSettingsLocal->GetConf('DraftFolder', '')) - { + if ('' === $oSettingsLocal->GetConf('DraftFolder', '')) { $aList[] = FolderType::DRAFTS; } - if ('' === $oSettingsLocal->GetConf('SpamFolder', '')) - { + if ('' === $oSettingsLocal->GetConf('SpamFolder', '')) { $aList[] = FolderType::JUNK; } - if ('' === $oSettingsLocal->GetConf('TrashFolder', '')) - { + if ('' === $oSettingsLocal->GetConf('TrashFolder', '')) { $aList[] = FolderType::TRASH; } - if ('' === $oSettingsLocal->GetConf('ArchiveFolder', '')) - { + if ('' === $oSettingsLocal->GetConf('ArchiveFolder', '')) { $aList[] = FolderType::ARCHIVE; } $this->Plugins()->RunHook('filter.folders-system-types', array($oAccount, &$aList)); - foreach ($aList as $iType) - { - if (!isset($aSystemFolders[$iType])) - { + foreach ($aList as $iType) { + if (!isset($aSystemFolders[$iType])) { $mFolderNameToCreate = \array_search($iType, $aMap); - if (!empty($mFolderNameToCreate)) - { + if (!empty($mFolderNameToCreate)) { $iPos = \strrpos($mFolderNameToCreate, $sDelimiter); - if (false !== $iPos) - { + if (false !== $iPos) { $mNewParent = \substr($mFolderNameToCreate, 0, $iPos); $mNewFolderNameToCreate = \substr($mFolderNameToCreate, $iPos + 1); - if (\strlen($mNewFolderNameToCreate)) - { + if (\strlen($mNewFolderNameToCreate)) { $mFolderNameToCreate = $mNewFolderNameToCreate; } - if (\strlen($mNewParent)) - { + if (\strlen($mNewParent)) { $sParent = \strlen($sParent) ? $sParent.$sDelimiter.$mNewParent : $mNewParent; } } $sFullNameToCheck = $mFolderNameToCreate; - if (\strlen($sParent)) - { + if (\strlen($sParent)) { $sFullNameToCheck = $sParent.$sDelimiter.$sFullNameToCheck; } - if (!isset($oFolderCollection[$sFullNameToCheck])) - { + if (!isset($oFolderCollection[$sFullNameToCheck])) { try { $this->MailClient()->FolderCreate($mFolderNameToCreate, $sParent, true, $sDelimiter); @@ -150,20 +135,17 @@ trait Folders } } - if ($bDoItAgain) - { + if ($bDoItAgain) { $oFolderCollection = $this->getFolderCollection($HideUnsubscribed); - if ($oFolderCollection) - { + if ($oFolderCollection) { $aSystemFolders = array(); $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders); } } } - if ($oFolderCollection) - { + if ($oFolderCollection) { $this->Plugins()->RunHook('filter.folders-complete', array($oAccount, $oFolderCollection)); $aQuota = null; @@ -186,9 +168,8 @@ trait Folders 'quotaUsage' => $aQuota ? $aQuota[0] * 1024 : null, 'quotaLimit' => $aQuota ? $aQuota[1] * 1024 : null, 'Namespace' => $sNamespace, - 'IsThreadsSupported' => $this->MailClient()->IsThreadsSupported(), 'Optimized' => $oFolderCollection->Optimized, - 'CountRec' => $oFolderCollection->TotalCount, + 'CountRec' => $oFolderCollection->count(), 'SystemFolders' => empty($aSystemFolders) ? null : $aSystemFolders, 'Capabilities' => \array_values($aCapabilities) ) @@ -246,14 +227,10 @@ trait Folders } catch (\Throwable $oException) { - if ($bSubscribe) - { - throw new ClientException(Notifications::CantSubscribeFolder, $oException); - } - else - { - throw new ClientException(Notifications::CantUnsubscribeFolder, $oException); - } + throw new ClientException( + $bSubscribe ? Notifications::CantSubscribeFolder : Notifications::CantUnsubscribeFolder, + $oException + ); } return $this->TrueResponse(__FUNCTION__); @@ -271,22 +248,16 @@ trait Folders $sCheckableFolder = $oSettingsLocal->GetConf('CheckableFolder', '[]'); $aCheckableFolder = \json_decode($sCheckableFolder); - if (!\is_array($aCheckableFolder)) - { + if (!\is_array($aCheckableFolder)) { $aCheckableFolder = array(); } - if ($bCheckable) - { + if ($bCheckable) { $aCheckableFolder[] = $sFolderFullName; - } - else - { + } else { $aCheckableFolderNew = array(); - foreach ($aCheckableFolder as $sFolder) - { - if ($sFolder !== $sFolderFullName) - { + foreach ($aCheckableFolder as $sFolder) { + if ($sFolder !== $sFolderFullName) { $aCheckableFolderNew[] = $sFolder; } } @@ -424,20 +395,16 @@ trait Folders $aResult = array(); $aFolders = $this->GetActionParam('Folders', null); - if (\is_array($aFolders)) - { + if (\is_array($aFolders)) { $this->initMailClientConnection(); $aFolders = \array_unique($aFolders); - foreach ($aFolders as $sFolder) - { - if (\strlen($sFolder) && 'INBOX' !== \strtoupper($sFolder)) - { + foreach ($aFolders as $sFolder) { + if (\strlen($sFolder) && 'INBOX' !== \strtoupper($sFolder)) { try { $aInboxInformation = $this->MailClient()->FolderInformation($sFolder); - if (isset($aInboxInformation['Folder'])) - { + if (isset($aInboxInformation['Folder'])) { $aResult[] = [ 'Folder' => $aInboxInformation['Folder'], 'Hash' => $aInboxInformation['Hash'], @@ -475,45 +442,31 @@ trait Folders private function recFoldersTypes(\RainLoop\Model\Account $oAccount, \MailSo\Mail\FolderCollection $oFolders, array &$aResult, bool $bListFolderTypes = true) : void { - if ($oFolders->Count()) - { - if ($bListFolderTypes) - { - foreach ($oFolders as $oFolder) - { + if ($oFolders->count()) { + if ($bListFolderTypes) { + $types = array( + FolderType::INBOX, + FolderType::SENT, + FolderType::DRAFTS, + FolderType::JUNK, + FolderType::TRASH, + FolderType::ARCHIVE + ); + foreach ($oFolders as $oFolder) { $iFolderType = $oFolder->GetType(); - if (!isset($aResult[$iFolderType]) && \in_array($iFolderType, array( - FolderType::INBOX, - FolderType::SENT, - FolderType::DRAFTS, - FolderType::JUNK, - FolderType::TRASH, - FolderType::ARCHIVE - ))) - { + if (!isset($aResult[$iFolderType]) && \in_array($iFolderType, $types)) { $aResult[$iFolderType] = $oFolder->FullName(); } } } $aMap = $this->systemFoldersNames($oAccount); - foreach ($oFolders as $oFolder) - { + foreach ($oFolders as $oFolder) { $sName = $oFolder->Name(); $sFullName = $oFolder->FullName(); - - if (isset($aMap[$sName]) || isset($aMap[$sFullName])) - { + if (isset($aMap[$sName]) || isset($aMap[$sFullName])) { $iFolderType = isset($aMap[$sName]) ? $aMap[$sName] : $aMap[$sFullName]; - if ((!isset($aResult[$iFolderType]) || $sName === $sFullName || "INBOX{$oFolder->Delimiter()}{$sName}" === $sFullName) && \in_array($iFolderType, array( - FolderType::INBOX, - FolderType::SENT, - FolderType::DRAFTS, - FolderType::JUNK, - FolderType::TRASH, - FolderType::ARCHIVE - ))) - { + if ((!isset($aResult[$iFolderType]) || $sName === $sFullName || "INBOX{$oFolder->Delimiter()}{$sName}" === $sFullName) && \in_array($iFolderType, $types)) { $aResult[$iFolderType] = $oFolder->FullName(); } } @@ -527,8 +480,7 @@ trait Folders private function systemFoldersNames(\RainLoop\Model\Account $oAccount) : array { static $aCache = null; - if (null === $aCache) - { + if (null === $aCache) { $aCache = array( 'Sent' => FolderType::SENT, @@ -578,8 +530,7 @@ trait Folders ); $aNewCache = array(); - foreach ($aCache as $sKey => $iType) - { + foreach ($aCache as $sKey => $iType) { $aNewCache[$sKey] = $iType; $aNewCache[\str_replace(' ', '', $sKey)] = $iType; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php index 59f10472e..71e4b8f20 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php @@ -246,7 +246,7 @@ trait Response return $mResult; } - if ($mResponse instanceof \MailSo\Mail\Folder) + if ($mResponse instanceof \MailSo\Imap\Folder) { $aResult = $mResponse->jsonSerialize(); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php b/snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php index bbf53894b..b458a1039 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php @@ -68,7 +68,7 @@ class Sync 'folder' => $sSourceFolderName ]); } - if ($oImapFolder->IsSelectable()) { + if ($oImapFolder->Selectable()) { if ($oImapFolder->IsInbox()) { $sSourceINBOX = $sSourceFolderName; } @@ -83,11 +83,11 @@ class Sync } // Create mailbox if not exists if (!isset($aTargetFolders[$sTargetFolderName])) { - $this->oImapTarget->FolderCreate($sTargetFolderName); - if (!$bUseListStatus || \in_array('\\subscribed', $oImapFolder->FlagsLowerCase())) { - $this->oImapTarget->FolderSubscribe($sTargetFolderName); - } - } else if (!$aTargetFolders[$sTargetFolderName]->IsSelectable()) { + $this->oImapTarget->FolderCreate( + $sTargetFolderName, + !$bUseListStatus || $oImapFolder->IsSubscribed() + ); + } else if (!$aTargetFolders[$sTargetFolderName]->Selectable()) { // Can't copy messages continue; }