mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
Compare commits
5 commits
501b0daa09
...
b2477f2ce3
Author | SHA1 | Date | |
---|---|---|---|
b2477f2ce3 | |||
167c27c1ee | |||
b88794b54b | |||
1a75a624cb | |||
ef850e37f7 |
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -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
|
||||
|
|
26
README.md
26
README.md
|
@ -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 |
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 && \
|
||||
|
|
|
@ -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.**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
));
|
||||
|
|
|
@ -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
|
||||
]));
|
||||
|
|
|
@ -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);
|
||||
}));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue