Compare commits

...

5 commits

Author SHA1 Message Date
the-djmaze b2477f2ce3 v2.32.0 2023-12-26 17:42:56 +01:00
the-djmaze 167c27c1ee Default IMAP message_list_limit to 10000 2023-12-26 17:20:27 +01:00
the-djmaze b88794b54b Bugfix: Folders array_filter(): Argument #1 ($array) must be of type array, null given 2023-12-26 16:54:29 +01:00
the-djmaze 1a75a624cb Run full UID fetch in background when message_list_limit is set 2023-12-26 16:45:48 +01:00
the-djmaze ef850e37f7 Cleanup SequenceSet 2023-12-26 16:26:12 +01:00
19 changed files with 191 additions and 115 deletions

View file

@ -1,3 +1,39 @@
## 2.32.0 2023-12-26
### Added
- Run full GetUids() in background when message_list_limit is set
- MessageListThreadsMap as background task when message_list_limit is set
- Properly set CACHEDIR.TAG
- Sending group email to all contact addresses by @rezaei92
[#1286](https://github.com/the-djmaze/snappymail/pull/1286)
### Changed
- Default IMAP message_list_limit to 10000
- DoMessageCopy() return toFolder hash/etag
- Improved Squire WYSIWYG
- Sort real attachments and inline attachments for
[#1360](https://github.com/the-djmaze/snappymail/issues/1360)
- Nextcloud Theme fixes and improvements by @hampoelz
[#1363](https://github.com/the-djmaze/snappymail/pull/1363)
- Improve display of attachments
[#1361](https://github.com/the-djmaze/snappymail/issues/1361)
- Rename messageVisibility to messageVisible
- All CSS font-size to % instead of px
- Flip source code view of .eml attachments
[#1332](https://github.com/the-djmaze/snappymail/issues/1332)
### Fixed
- Folders array_filter(): Argument 1 must be of type array, null given
- At upgrade set `static` and `themes` folder to 0755
- Preview tooltip shows "null" when PREVIEW capability is disabled
### Nextcloud
- Improved language handling by @avinash-0007
[#1362](https://github.com/the-djmaze/snappymail/pull/1362)
- FilterLanguage had wrong parameter order
- Use NextcloudV25+ theme by default
## 2.31.0 2023-12-08
### Added

View file

@ -30,7 +30,7 @@ For more information about the product, check [snappymail.eu](https://snappymail
Information about installing the product, check the [wiki page](https://github.com/the-djmaze/snappymail/wiki/Installation-instructions).
And don't forget to read the [RainLoop documentation](https://www.rainloop.net/docs/).
And don't forget to read the whole [Wiki](https://github.com/the-djmaze/snappymail/wiki).
## License
@ -140,26 +140,26 @@ RainLoop 1.17 vs SnappyMail
|js/* |RainLoop |Snappy |
|--------------- |--------: |--------: |
|admin.js |2.170.153 | 80.366 |
|app.js |4.207.787 | 407.909 |
|admin.js |2.170.153 | 80.370 |
|app.js |4.207.787 | 408.429 |
|boot.js | 868.735 | 4.142 |
|libs.js | 658.812 | 192.289 |
|libs.js | 658.812 | 193.230 |
|sieve.js | 0 | 85.085 |
|polyfills.js | 334.608 | 0 |
|serviceworker.js | 0 | 285 |
|TOTAL |8.240.095 | 770.076 |
|TOTAL |8.240.095 | 771.541 |
|js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli |
|--------------- |--------: |--------: |------: |------: |--------: |--------: |
|admin.min.js | 256.831 | 39.283 | 73.606 | 13.181 | 60.877 | 11.803 |
|app.min.js | 515.367 | 186.036 |139.456 | 63.062 |110.485 | 54.135 |
|admin.min.js | 256.831 | 39.285 | 73.606 | 13.183 | 60.877 | 11.806 |
|app.min.js | 515.367 | 186.270 |139.456 | 63.111 |110.485 | 54.218 |
|boot.min.js | 84.659 | 2.084 | 26.998 | 1.202 | 23.643 | 1.003 |
|libs.min.js | 584.772 | 93.758 |180.901 | 34.878 |155.182 | 31.291 |
|libs.min.js | 584.772 | 93.401 |180.901 | 34.765 |155.182 | 31.194 |
|sieve.min.js | 0 | 41.316 | 0 | 10.364 | 0 | 9.352 |
|polyfills.min.js | 32.837 | 0 | 11.406 | 0 | 10.175 | 0 |
|TOTAL user |1.217.635 | 281.878 |358.761 | 99.142 |299.485 | 86.429 |
|TOTAL user+sieve |1.217.635 | 323.194 |358.761 |109.506 |299.485 | 95.781 |
|TOTAL admin | 959.099 | 135.125 |292.911 | 49.261 |249.877 | 44.097 |
|TOTAL user |1.217.635 | 281.755 |358.761 | 99.078 |299.485 | 86.415 |
|TOTAL user+sieve |1.217.635 | 323.071 |358.761 |109.442 |299.485 | 95.767 |
|TOTAL admin | 959.099 | 134.770 |292.911 | 49.150 |249.877 | 44.003 |
For a user it is around 69% smaller and faster than traditional RainLoop.
@ -188,8 +188,8 @@ For a user it is around 69% smaller and faster than traditional RainLoop.
|css/* |RainLoop |Snappy |RL gzip |SM gzip |SM brotli |
|------------ |-------: |------: |------: |------: |--------: |
|app.css | 340.331 | 84.607 | 46.946 | 17.662 | 15.138 |
|app.min.css | 274.947 | 67.961 | 39.647 | 15.550 | 13.570 |
|app.css | 340.331 | 84.484 | 46.946 | 17.627 | 15.110 |
|app.min.css | 274.947 | 67.910 | 39.647 | 15.541 | 13.547 |
|boot.css | | 1.326 | | 664 | 545 |
|boot.min.css | | 1.071 | | 590 | 474 |
|admin.css | | 30.641 | | 7.028 | 6.111 |

View file

@ -36,7 +36,7 @@ const
imapForce_select: false,
imapFolder_list_limit: 200,
imapMessage_all_headers: false,
imapMessage_list_limit: 0,
imapMessage_list_limit: 10000,
imapSearch_filter: '',
sieveEnabled: false,

View file

@ -162,13 +162,11 @@ export class MailMessageView extends AbstractViewRight {
listAttachments: () => currentMessage()?.attachments()
.filter(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
// hasAttachments: () => this.listAttachments()?.length,
// hasAttachments: () => currentMessage()?.attachments()?.length,
hasAttachments: () => currentMessage()?.attachments()
.some(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
// listInlines: () => currentMessage()?.attachments()
// .filter(item => item.isLinked()),
// hasInlines: () => currentMessage()?.attachments()
// .some(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
// listInline: () => currentMessage()?.attachments().filter(item => item.isLinked()),
// hasInline: () => currentMessage()?.attachments().some(item => item.isLinked()),
canBeRepliedOrForwarded: () => !MessagelistUserStore.isDraftFolder() && this.messageVisible(),

View file

@ -1,4 +1,4 @@
This app packages SnappyMail <upstream>2.31.0</upstream>.
This app packages SnappyMail <upstream>2.32.0</upstream>.
SnappyMail is a simple, modern, lightweight & fast web-based email client.

View file

@ -4,7 +4,7 @@ RUN mkdir -p /app/code
WORKDIR /app/code
# If you change the extraction below, be sure to test on scaleway
VERSION=2.31.0
VERSION=2.32.0
RUN wget https://github.com/the-djmaze/snappymail/releases/download/v${VERSION}/snappymail-${VERSION}.zip -O /tmp/snappymail.zip && \
unzip /tmp/snappymail.zip -d /app/code && \
rm /tmp/snappymail.zip && \

View file

@ -3,7 +3,7 @@
<id>snappymail</id>
<name>SnappyMail</name>
<summary>SnappyMail Webmail</summary>
<version>2.31.0</version>
<version>2.32.0</version>
<licence>agpl</licence>
<author>SnappyMail, RainLoop Team, Nextgen-Networks, Tab Fitts, Nathan Kinkade, Pierre-Alain Bandinelli</author>
<description><![CDATA[**Simple, modern, lightweight & fast web-based email client.**

View file

@ -20,7 +20,7 @@ return "SnappyMail Webmail is a browser-based multilingual IMAP client with an a
# script_snappymail_versions()
sub script_snappymail_versions
{
return ( "2.31.0" );
return ( "2.32.0" );
}
sub script_snappymail_version_desc

View file

@ -3,7 +3,7 @@
"title": "SnappyMail",
"description": "Simple, modern & fast web-based email client",
"private": true,
"version": "2.31.0",
"version": "2.32.0",
"homepage": "https://snappymail.eu",
"author": {
"name": "DJ Maze",

View file

@ -30,7 +30,7 @@
"fast_simple_search": true,
"force_select": false,
"message_all_headers": false,
"message_list_limit": 0,
"message_list_limit": 10000,
"search_filter": ""
},
"SMTP": {

View file

@ -289,7 +289,7 @@ trait Messages
$this->FolderSelect($sFolderName);
$iNewUid = $this->MessageAppendStream($sFolderName, $rMessageStream, $iStreamSize, $aFlagsList, $iDateTime);
if ($iUid) {
$oRange = new SequenceSet([$iUid]);
$oRange = new SequenceSet($iUid);
$this->MessageStoreFlag($oRange,
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT

View file

@ -28,6 +28,9 @@ class SequenceSet /*extends \SplFixedArray*/ implements \Countable
private array $data = [];
/**
* @param mixed $mItems Can be array, string or int
*/
public function __construct($mItems, bool $uid = true)
{
if (\is_array($mItems)) {

View file

@ -22,7 +22,7 @@ class Settings extends \MailSo\Net\ConnectSettings
$timeout = 300,
$body_text_limit = 0,
// $folder_list_limit = 200,
$message_list_limit = 0,
$message_list_limit = 10000,
$thread_limit = 50;
public bool

View file

@ -435,6 +435,7 @@ class MailClient
return $aSerializedUids['ThreadsUids'];
}
}
/*
// Idea to fetch all UID's in background
else if (!$bBackground) {
$this->logWrite('Set MessageListThreadsMap() as background task ("'.$sFolderName.'" / '.$sSearch.')');
@ -444,6 +445,7 @@ class MailClient
}, [$this, $oMessageCollection, $oCacher]);
return [];
}
*/
}
$this->oImapClient->FolderExamine($sFolderName);
@ -529,59 +531,75 @@ class MailClient
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
private function GetUids(MessageListParams $oParams, string $sSearch,
FolderInformation $oInfo, bool $bUseSort = false) : array
private function GetUids(MessageListParams $oParams, FolderInformation $oInfo, bool $onlyCache = false) : array
{
$oCacher = $oParams->oCacher;
$sFolderName = $oParams->sFolderName;
$bUseSort = $bUseSort && $this->oImapClient->hasCapability('SORT');
$sSort = $bUseSort ? $oParams->sSort : '';
/* TODO: Validate $sSort
ARRIVAL
Internal date and time of the message. This differs from the
ON criteria in SEARCH, which uses just the internal date.
$bUseSort = $oParams->bUseSort && $this->oImapClient->hasCapability('SORT');
$aSortTypes = [];
if ($bUseSort) {
if ($oParams->sSort) {
/* TODO: Validate $oParams->sSort
* /(REVERSE\s+)?(ARRIVAL|CC|DATE|FROM|SIZE|SUBJECT|TO|DISPLAYFROM|DISPLAYTO)/
ARRIVAL
Internal date and time of the message. This differs from the
ON criteria in SEARCH, which uses just the internal date.
CC
[IMAP] addr-mailbox of the first "cc" address.
CC
[IMAP] addr-mailbox of the first "cc" address.
DATE
Sent date and time, as described in section 2.2.
DATE
Sent date and time, as described in section 2.2.
FROM
[IMAP] addr-mailbox of the first "From" address.
FROM
[IMAP] addr-mailbox of the first "From" address.
REVERSE
Followed by another sort criterion, has the effect of that
criterion but in reverse (descending) order.
Note: REVERSE only reverses a single criterion, and does not
affect the implicit "sequence number" sort criterion if all
other criteria are identical. Consequently, a sort of
REVERSE SUBJECT is not the same as a reverse ordering of a
SUBJECT sort. This can be avoided by use of additional
criteria, e.g., SUBJECT DATE vs. REVERSE SUBJECT REVERSE
DATE. In general, however, it's better (and faster, if the
client has a "reverse current ordering" command) to reverse
the results in the client instead of issuing a new SORT.
REVERSE
Followed by another sort criterion, has the effect of that
criterion but in reverse (descending) order.
Note: REVERSE only reverses a single criterion, and does not
affect the implicit "sequence number" sort criterion if all
other criteria are identical. Consequently, a sort of
REVERSE SUBJECT is not the same as a reverse ordering of a
SUBJECT sort. This can be avoided by use of additional
criteria, e.g., SUBJECT DATE vs. REVERSE SUBJECT REVERSE
DATE. In general, however, it's better (and faster, if the
client has a "reverse current ordering" command) to reverse
the results in the client instead of issuing a new SORT.
SIZE
Size of the message in octets.
SIZE
Size of the message in octets.
SUBJECT
Base subject text.
SUBJECT
Base subject text.
TO
[IMAP] addr-mailbox of the first "To" address.
TO
[IMAP] addr-mailbox of the first "To" address.
RFC 5957:
$this->oImapClient->hasCapability('SORT=DISPLAY')
DISPLAYFROM, DISPLAYTO
*/
RFC 5957:
$this->oImapClient->hasCapability('SORT=DISPLAY')
DISPLAYFROM, DISPLAYTO
*/
$aSortTypes[] = $oParams->sSort;
}
if (!\str_contains($oParams->sSort, 'DATE')) {
// Always also sort DATE descending when DATE is not defined
$aSortTypes[] = 'REVERSE DATE';
}
}
$oParams->sSort = \implode(' ', $aSortTypes);
$bUseCacheAfterSearch = $oCacher && $oCacher->IsInited();
$sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch);
$bUseCache = $oCacher && $oCacher->IsInited();
$sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString(
$this->oImapClient,
$sFolderName,
$oParams->sSearch,
$oParams->bHideDeleted,
$bUseCache
);
// Disable? as there are many cases that change the result
// $bUseCacheAfterSearch = false;
// $bUseCache = false;
$bReturnUid = true;
if ($oParams->oSequenceSet) {
@ -591,12 +609,11 @@ class MailClient
$sSerializedHash = '';
$sSerializedLog = '';
if ($bUseCacheAfterSearch) {
if ($bUseCache) {
$sSerializedHash = 'Get'
. ($bReturnUid ? 'UIDS/' : 'IDS/')
. ($bUseSort ? 'S' . $sSort : 'N')
. "/{$this->oImapClient->Hash()}/{$sFolderName}/{$sSearchCriterias}";
$sSerializedLog = "\"{$sFolderName}\" / {$sSort} / {$sSearchCriterias}";
. "{$oParams->sSort}/{$this->oImapClient->Hash()}/{$sFolderName}/{$sSearchCriterias}";
$sSerializedLog = "\"{$sFolderName}\" / {$oParams->sSort} / {$sSearchCriterias}";
$sSerialized = $oCacher->Get($sSerializedHash);
if (!empty($sSerialized)) {
@ -610,19 +627,14 @@ class MailClient
}
}
}
if ($onlyCache) {
return [];
}
$this->oImapClient->FolderExamine($sFolderName);
$aResultUids = [];
if ($bUseSort) {
$aSortTypes = [];
if ($sSort) {
$aSortTypes[] = $sSort;
}
if (false === \strpos($sSort, 'DATE')) {
// Always also sort DATE descending when DATE is not defined
$aSortTypes[] = 'REVERSE DATE';
}
// $this->oImapClient->hasCapability('ESORT')
// $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL'];
$aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias, $bReturnUid);
@ -632,7 +644,7 @@ class MailClient
$aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bReturnUid);
}
if ($bUseCacheAfterSearch) {
if ($bUseCache) {
$oCacher->Set($sSerializedHash, \json_encode(array(
'FolderHash' => $oInfo->etag,
'Uids' => $aResultUids
@ -641,6 +653,10 @@ class MailClient
$this->logWrite('Save Serialized '.($bReturnUid?'UIDS':'IDS').' to cache ('.$sSerializedLog.') [count:'.\count($aResultUids).']');
}
// $oSequenceSet = new SequenceSet($aResultUids, false);
// $oSequenceSet->UID = $bReturnUid;
// return $oSequenceSet;
return $aResultUids;
}
@ -648,7 +664,7 @@ class MailClient
{
$oUnseenParams = new MessageListParams;
$oUnseenParams->sFolderName = $oParams->sFolderName;
// $oUnseenParams->sSearch = $oParams->sSearch;
$oUnseenParams->sSearch = 'unseen';
// $oUnseenParams->sSort = $oParams->sSort;
$oUnseenParams->oCacher = $oParams->oCacher;
$oUnseenParams->bUseSort = false; // $oParams->bUseSort
@ -658,7 +674,7 @@ class MailClient
// $oUnseenParams->iLimit = $oParams->iLimit;
// $oUnseenParams->iPrevUidNext = $oParams->iPrevUidNext;
// $oUnseenParams->iThreadUid = $oParams->iThreadUid;
return $this->GetUids($oUnseenParams, 'unseen', $oInfo);
return $this->GetUids($oUnseenParams, $oInfo);
}
/**
@ -688,14 +704,13 @@ class MailClient
$oMessageCollection->FolderInfo = $oInfo;
$oMessageCollection->totalEmails = $oInfo->MESSAGES;
$bUseThreads = $oParams->bUseThreads && $this->oImapClient->CapabilityValue('THREAD');
$oParams->bUseThreads = $oParams->bUseThreads && $this->oImapClient->CapabilityValue('THREAD');
// && ($this->oImapClient->hasCapability('THREAD=REFS') || $this->oImapClient->hasCapability('THREAD=REFERENCES') || $this->oImapClient->hasCapability('THREAD=ORDEREDSUBJECT'));
if ($oParams->iThreadUid && !$bUseThreads) {
if ($oParams->iThreadUid && !$oParams->bUseThreads) {
throw new \InvalidArgumentException('THREAD not supported');
}
if (!$oInfo->MESSAGES) {
$this->logWrite('No messages in '.$oMessageCollection->FolderName);
if (!$oInfo->MESSAGES || $oParams->iOffset > $oInfo->MESSAGES) {
return $oMessageCollection;
}
@ -705,23 +720,41 @@ class MailClient
);
}
$bUseSort = $oParams->bUseSort || $oParams->sSort;
$bUseSort = ($oParams->bUseSort || $oParams->sSort) && $this->oImapClient->hasCapability('SORT');
$oParams->bUseSort = $bUseSort;
$oParams->sSearch = $sSearch;
$aAllThreads = [];
$aUnseenUIDs = [];
$aUids = [];
$message_list_limit = $oParams->bIgnoreLimit ? 0 : $this->oImapClient->Settings->message_list_limit;
if (0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES) {
/*
// TODO: Idea to fetch all UID's in background
// Must know what is cached so needs more thought
if ($oParams->oCacher && !$oParams->iOffset && !$oParams->iThreadUid && !\strlen($sSearch)) {
\SnappyMail\Shutdown::add(function($oMailClient, $oParams) {
$oParams->bIgnoreLimit = true;
$oMailClient->MessageList($oParams);
}, [$this, $oParams]);
$message_list_limit = $this->oImapClient->Settings->message_list_limit;
if (100 > $message_list_limit || $message_list_limit > $oInfo->MESSAGES) {
$message_list_limit = 0;
}
// Idea to fetch all UID's in background
$oAllParams = clone $oParams;
$oAllParams->sSearch = '';
$oAllParams->oSequenceSet = null;
if ($message_list_limit && $message_list_limit < $oInfo->MESSAGES && !$oParams->iThreadUid
&& $oParams->oCacher && $oParams->oCacher->IsInited()
) {
$aUids = $this->GetUids($oAllParams, $oInfo, true);
if ($aUids) {
$message_list_limit = 0;
$oMessageCollection->Sort = $oAllParams->sSort;
} else {
\SnappyMail\Shutdown::add(function($oMailClient, $oAllParams, $oInfo, $oMessageCollection) {
$oMailClient->GetUids($oAllParams, $oInfo);
if ($oAllParams->bUseThreads) {
$oMessageCollection->FolderInfo->MESSAGES = 0;
$oMailClient->MessageListThreadsMap($oMessageCollection, $oAllParams->oCacher, true);
}
}, [$this, $oAllParams, $oInfo, $oMessageCollection]);
}
*/
}
if ($message_list_limit && $message_list_limit < $oInfo->MESSAGES && !$aUids) {
// if ((0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES)
// || (!$this->oImapClient->hasCapability('SORT') && !$this->oImapClient->CapabilityValue('THREAD'))) {
// Don't use THREAD for speed
@ -729,17 +762,15 @@ class MailClient
$this->logWrite('List optimization (count: '.$oInfo->MESSAGES.', limit:'.$message_list_limit.')');
if (\strlen($sSearch)) {
// Don't use SORT for speed
$aUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/);
$oParams->bUseSort = false;
$aUids = $this->GetUids($oParams, $oInfo);
} else {
$bUseSort = $this->oImapClient->hasCapability('SORT');
if (2 > $oInfo->MESSAGES) {
$aRequestIndexes = \array_slice([1], $oParams->iOffset, 1);
} else if ($bUseSort) {
if ($bUseSort) {
// Attempt to sort REVERSE DATE with a bigger range then $oParams->iLimit
$end = \min($oInfo->MESSAGES, \max(1, $oInfo->MESSAGES - $oParams->iOffset + $oParams->iLimit));
$start = \max(1, $end - ($oParams->iLimit * 3) + 1);
$oParams->oSequenceSet = new SequenceSet(\range($end, $start), false);
$aRequestIndexes = $this->GetUids($oParams, '', $oInfo, $bUseSort);
$aRequestIndexes = $this->GetUids($oParams, $oInfo);
// Attempt to get the correct $oParams->iLimit slice
$aRequestIndexes = \array_slice($aRequestIndexes, $oParams->iOffset ? $oParams->iLimit : 0, $oParams->iLimit);
} else {
@ -750,12 +781,16 @@ class MailClient
}
$this->MessageListByRequestIndexOrUids($oMessageCollection, new SequenceSet($aRequestIndexes, false));
}
$oMessageCollection->Sort = $oParams->sSort;
} else {
$aUids = ($bUseThreads && $oParams->iThreadUid)
? [$oParams->iThreadUid]
: $this->GetUids($oParams, '', $oInfo, $bUseSort);
if ($oParams->bUseThreads && $oParams->iThreadUid) {
$aUids = [$oParams->iThreadUid];
} else if (!$aUids) {
$aUids = $this->GetUids($oAllParams, $oInfo);
$oMessageCollection->Sort = $oAllParams->sSort;
}
if ($bUseThreads) {
if ($oParams->bUseThreads) {
$aAllThreads = $this->MessageListThreadsMap($oMessageCollection, $oParams->oCacher);
$oMessageCollection->totalThreads = \count($aAllThreads);
// $iThreadLimit = $this->oImapClient->Settings->thread_limit;
@ -784,8 +819,9 @@ class MailClient
}
if ($aUids && \strlen($sSearch)) {
$aSearchedUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/);
if ($bUseThreads && !$oParams->iThreadUid) {
$oParams->bUseSort = false;
$aSearchedUids = $this->GetUids($oParams, $oInfo);
if ($oParams->bUseThreads && !$oParams->iThreadUid) {
$matchingThreadUids = [];
foreach ($aAllThreads as $aMap) {
if (\array_intersect($aSearchedUids, $aMap)) {

View file

@ -32,6 +32,8 @@ class MessageCollection extends \MailSo\Base\Collection
public string $Search = '';
public string $Sort = '';
public int $ThreadUid = 0;
// MailSo\Imap\FolderInformation
@ -57,7 +59,7 @@ class MessageCollection extends \MailSo\Base\Collection
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return array_merge(parent::jsonSerialize(), array(
return \array_merge(parent::jsonSerialize(), array(
'totalEmails' => $this->totalEmails,
'totalThreads' => $this->totalThreads,
'threadUid' => $this->ThreadUid,
@ -66,6 +68,7 @@ class MessageCollection extends \MailSo\Base\Collection
'offset' => $this->Offset,
'limit' => $this->Limit,
'search' => $this->Search,
'sort' => $this->Sort,
'limited' => $this->Limited,
'folder' => $this->FolderInfo
));

View file

@ -24,8 +24,7 @@ class MessageListParams
public bool
$bUseSort = true,
$bUseThreads = false,
$bHideDeleted = true,
$bIgnoreLimit = false;
$bHideDeleted = true;
protected int
$iOffset = 0,
@ -61,7 +60,7 @@ class MessageListParams
$this->iLimit,
$this->bHideDeleted ? '1' : '0',
$this->sSearch,
$this->bUseSort ? $this->sSort : '',
$this->bUseSort ? $this->sSort : '0',
$this->bUseThreads ? $this->iThreadUid : '',
$this->iPrevUidNext
]));

View file

@ -68,7 +68,7 @@ trait Folders
}
}
$aCapabilities = \array_values(\array_filter($this->ImapClient()->Capability(), function ($item) {
$aCapabilities = \array_values(\array_filter($this->ImapClient()->Capability() ?: [], function ($item) {
return !\preg_match('/^(IMAP|AUTH|LOGIN|SASL)/', $item);
}));

View file

@ -77,6 +77,7 @@ trait Messages
$oParams->oCacher = $this->Cacher($oAccount);
}
// $oParams->bUseSort = $this->ImapClient->hasCapability('SORT');
$oParams->bUseSort = true;
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);

View file

@ -198,7 +198,7 @@ class Sync
);
if ($iAppendUid && $aFlags) {
$this->MessageStoreFlag(
new SequenceSet([$iAppendUid]),
new SequenceSet($iAppendUid),
$aFlags,
\MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT
);