From 135406ebfe1407ad7ee4b3fe2690e76561f809b0 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 29 May 2022 10:12:49 +0200 Subject: [PATCH 01/20] Some changes for #419 flags --- .../MailSo/Imap/FolderInformation.php | 22 +++++++++++++++++- .../app/libraries/MailSo/Mail/Folder.php | 1 + .../app/libraries/MailSo/Mail/MailClient.php | 23 ++++++++----------- .../MailSo/Mail/MessageCollection.php | 4 ++++ .../libraries/RainLoop/Actions/Folders.php | 3 +-- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php index dcedd1860..cee0a0c9d 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php @@ -15,7 +15,7 @@ namespace MailSo\Imap; * @category MailSo * @package Imap */ -class FolderInformation +class FolderInformation implements \JsonSerializable { use Traits\Status; @@ -36,6 +36,7 @@ class FolderInformation /** * @var array + * NOTE: Empty when FolderExamine is used */ public $PermanentFlags = array(); @@ -57,4 +58,23 @@ class FolderInformation \in_array($sFlag, $this->PermanentFlags) || \in_array($sFlag, $this->Flags); } + + public function jsonSerialize() + { + return array( + 'Name' => $this->FolderName, + 'Flags' => $this->Flags, + 'PermanentFlags' => $this->PermanentFlags, +/* + 'Messages' => $this->MESSAGES, + 'Unseen' => $this->UNSEEN, + 'Recent' => $this->RECENT, + 'UidNext' => $this->UIDNEXT, + 'UidValidity' => $this->UIDVALIDITY, + 'Highestmodseq' => $this->HIGHESTMODSEQ, + 'Appendlimit' => $this->APPENDLIMIT, + 'Mailboxid' => $this->MAILBOXID, +*/ + ); + } } 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 index 1dbde14e8..14f777b39 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Folder.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Folder.php @@ -228,6 +228,7 @@ class Folder implements \JsonSerializable 'Selectable' => $this->IsSelectable(), 'Flags' => $this->FlagsLowerCase(), // 'Extended' => $aExtended, +// 'PermanentFlags' => $this->oImapFolder->PermanentFlags, 'Metadata' => $this->oImapFolder->Metadata() ); } 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 3fbec55da..1e5e322ce 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 @@ -521,21 +521,19 @@ class MailClient */ public function FolderInformation(string $sFolderName, int $iPrevUidNext = 0, SequenceSet $oRange = null) : array { - $aFlags = array(); - list($iCount, $iUnseenCount, $iUidNext, $iHighestModSeq, $iAppendLimit, $sMailboxId) = $this->initFolderValues($sFolderName); - if ($oRange && \count($oRange)) - { - $this->oImapClient->FolderExamine($sFolderName); + $aFlags = array(); + if ($oRange && \count($oRange)) { + $oInfo = $this->oImapClient->FolderExamine($sFolderName); + // $oInfo->PermanentFlags $aFetchResponse = $this->oImapClient->Fetch(array( FetchType::UID, FetchType::FLAGS ), (string) $oRange, $oRange->UID); - foreach ($aFetchResponse as $oFetchResponse) - { + foreach ($aFetchResponse as $oFetchResponse) { $iUid = (int) $oFetchResponse->GetFetchValue(FetchType::UID); $aLowerFlags = \array_map('strtolower', $oFetchResponse->GetFetchValue(FetchType::FLAGS)); $aFlags[] = array( @@ -830,15 +828,19 @@ class MailClient list($iMessageRealCount, $iMessageUnseenCount, $iUidNext, $iHighestModSeq) = $this->initFolderValues($oParams->sFolderName); - $this->oImapClient->FolderExamine($oParams->sFolderName); + // Don't use FolderExamine, else PERMANENTFLAGS is empty + $oInfo = $this->oImapClient->FolderSelect($oParams->sFolderName); $oMessageCollection = new MessageCollection; $oMessageCollection->FolderName = $oParams->sFolderName; + $oMessageCollection->FolderInfo = $oInfo; $oMessageCollection->Offset = $oParams->iOffset; $oMessageCollection->Limit = $oParams->iLimit; $oMessageCollection->Search = $sSearch; $oMessageCollection->ThreadUid = $oParams->iThreadUid; $oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter; + $oMessageCollection->MessageCount = $iMessageRealCount; + $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $aUids = array(); $aAllThreads = []; @@ -934,8 +936,6 @@ class MailClient } } - $oMessageCollection->MessageCount = $iMessageRealCount; - $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = \count($aUids); if (\count($aUids)) @@ -954,9 +954,6 @@ class MailClient ', limit:'.\MailSo\Config::$MessageListCountLimitTrigger.')'); } - $oMessageCollection->MessageCount = $iMessageRealCount; - $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; - if (\strlen($sSearch)) { $aUids = $this->GetUids($oParams->oCacher, $sSearch, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php index 428e80baa..db607939a 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php @@ -67,6 +67,9 @@ class MessageCollection extends \MailSo\Base\Collection */ public $ThreadUid = 0; + // MailSo\Imap\FolderInformation + public $FolderInfo = null; + /** * @var array */ @@ -97,6 +100,7 @@ class MessageCollection extends \MailSo\Base\Collection 'MessageResultCount' => $this->MessageResultCount, 'Folder' => $this->FolderName, 'FolderHash' => $this->FolderHash, + 'FolderInfo' => $this->FolderInfo, 'UidNext' => $this->UidNext, 'ThreadUid' => $this->ThreadUid, 'NewMessages' => $this->NewMessages, 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 59889fdc3..be99c3c54 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 @@ -426,13 +426,12 @@ trait Folders ); $aInboxInformation['Flags'] = $aInboxInformation['MessagesFlags']; unset($aInboxInformation['MessagesFlags']); + return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); } catch (\Throwable $oException) { throw new ClientException(Notifications::MailServerError, $oException); } - - return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); } /** From 2ea3f10cb08824f5cd77f15e881bc15187ecefac Mon Sep 17 00:00:00 2001 From: Gerald Urbas <121263+geraldurbas@users.noreply.github.com> Date: Sun, 29 May 2022 20:19:06 +0200 Subject: [PATCH 02/20] Change Ordering of SASLMechanisms Want bw. Needed to change the ordering for SASL Mechanism... --- snappymail/v/0.0.0/app/libraries/MailSo/Smtp/SmtpClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Smtp/SmtpClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Smtp/SmtpClient.php index 22ec5ff61..9c745119f 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Smtp/SmtpClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Smtp/SmtpClient.php @@ -120,7 +120,7 @@ class SmtpClient extends \MailSo\Net\NetClient $sPassword = $aCredentials['Password']; $type = ''; - $aCredentials['SASLMechanisms'][] = 'LOGIN'; + array_unshift($aCredentials['SASLMechanisms'],'LOGIN'); foreach ($aCredentials['SASLMechanisms'] as $sasl_type) { if ($this->IsAuthSupported($sasl_type) && \SnappyMail\SASL::isSupported($sasl_type)) { $type = $sasl_type; From 30ece4b8c8526cefeffec1a7fc4faadd1d6c6210 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 30 May 2022 08:23:59 +0200 Subject: [PATCH 03/20] Resolve #420 --- dev/View/Popup/Compose.js | 3 ++- snappymail/v/0.0.0/app/templates/Views/User/PopupsCompose.html | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 8d67433e0..cc366ab4d 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -20,7 +20,7 @@ import { messagesDeleteHelper } from 'Common/Folders'; import { serverRequest } from 'Common/Links'; import { i18n, getNotification, getUploadErrorDescByCode, timestampToString } from 'Common/Translator'; import { MessageFlagsCache, setFolderHash } from 'Common/Cache'; -import { Settings, SettingsGet, elementById, addShortcut } from 'Common/Globals'; +import { Settings, SettingsCapa, SettingsGet, elementById, addShortcut } from 'Common/Globals'; //import { exitFullscreen, isFullscreen, toggleFullscreen } from 'Common/Fullscreen'; import { AppUserStore } from 'Stores/User/App'; @@ -236,6 +236,7 @@ export class ComposePopupView extends AbstractViewPopup { this.sLastFocusedField = 'to'; this.allowContacts = AppUserStore.allowContacts(); + this.allowIdentities = SettingsCapa('Identities'); this.bSkipNextHide = false; diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsCompose.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsCompose.html index 9f17dd1c5..c5ec43f3e 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/PopupsCompose.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsCompose.html @@ -66,7 +66,10 @@ + + + diff --git a/plugins/custom-settings-tab/templates/PluginCustomSettingsTab.html b/plugins/example/templates/ExampleUserSettingsTab.html similarity index 66% rename from plugins/custom-settings-tab/templates/PluginCustomSettingsTab.html rename to plugins/example/templates/ExampleUserSettingsTab.html index 1b688168b..3bbfad069 100644 --- a/plugins/custom-settings-tab/templates/PluginCustomSettingsTab.html +++ b/plugins/example/templates/ExampleUserSettingsTab.html @@ -1,13 +1,13 @@
- +    
@@ -15,7 +15,7 @@
@@ -23,10 +23,10 @@
-
diff --git a/snappymail/v/0.0.0/app/templates/Views/User/Login.html b/snappymail/v/0.0.0/app/templates/Views/User/Login.html index 53a04ce36..739f4e4ba 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/Login.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/Login.html @@ -24,12 +24,7 @@ data-i18n="[placeholder]GLOBAL/PASSWORD">
-
- -
-
+
+
From 1e61171f9c0e19914622256eb43ae4dfc83b240c Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 17:12:29 +0200 Subject: [PATCH 13/20] Fix RFC 9051 IMAP4rev2 keywords and $ReadReceipt should be $MDNSent --- dev/Model/Message.js | 10 +++- dev/View/User/MailBox/MessageView.js | 16 +++--- .../MailSo/Imap/Enumerations/MessageFlag.php | 19 ++++--- .../libraries/RainLoop/Actions/Messages.php | 54 +++++++++++-------- .../libraries/RainLoop/Actions/Response.php | 11 ++-- .../libraries/RainLoop/Config/Application.php | 2 - 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 822b49598..acb582304 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -307,11 +307,19 @@ export class MessageModel extends AbstractModel { hasFlaggedSubMessage: this.hasFlaggedSubMessage() }, (key, value) => value && classes.push(key)); this.flags().forEach(value => { - '\\' !== value[0] && classes.push('flag-'+value); + '\\' !== value[0] && '$forwarded' !== value && classes.push('flag-'+value); }); return classes.join(' '); } + /** + * @return array + * https://datatracker.ietf.org/doc/html/rfc5788 + */ + keywords() { + return this.flags().filter(value => '\\' !== value[0]); + } + /** * @returns {string} */ diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index d66b06254..e4a9b8cab 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -566,20 +566,20 @@ export class MailMessageView extends AbstractViewRight { readReceipt() { let oMessage = currentMessage() if (oMessage.readReceipt()) { - Remote.request('SendReadReceiptMessage', null, { + Remote.request('SendReadReceiptMessage', iError => { + if (!iError) { + oMessage.flags.push('$mdnsent'); +// oMessage.flags.valueHasMutated(); + MessageFlagsCache.store(oMessage); + MessagelistUserStore.reloadFlagsAndCachedMessage(); + } + }, { MessageFolder: oMessage.folder, MessageUid: oMessage.uid, ReadReceipt: oMessage.readReceipt(), Subject: i18n('READ_RECEIPT/SUBJECT', { SUBJECT: oMessage.subject() }), Text: i18n('READ_RECEIPT/BODY', { 'READ-RECEIPT': AccountUserStore.email() }) }); - - oMessage.flags.push('$mdnsent'); -// oMessage.flags.valueHasMutated(); - - MessageFlagsCache.store(oMessage); - - MessagelistUserStore.reloadFlagsAndCachedMessage(); } } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php index c2e2c2b69..467938643 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php @@ -18,10 +18,17 @@ namespace MailSo\Imap\Enumerations; */ abstract class MessageFlag { -// const RECENT = '\\Recent'; // IMAP4rev2 deprecated - const SEEN = '\\Seen'; - const DELETED = '\\Deleted'; - const FLAGGED = '\\Flagged'; - const ANSWERED = '\\Answered'; - const DRAFT = '\\Draft'; + const +// RECENT = '\\Recent', // IMAP4rev2 deprecated + SEEN = '\\Seen', + DELETED = '\\Deleted', + FLAGGED = '\\Flagged', + ANSWERED = '\\Answered', + DRAFT = '\\Draft', + // https://datatracker.ietf.org/doc/html/rfc9051#section-2.3.2 + FORWARDED = '$Forwarded', + MDNSENT = '$MDNSent', + JUNK = '$Junk', + NOTJUNK = '$NotJunk', + PHISHING = '$Phishing'; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php index 83989d264..97f69a264 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php @@ -187,16 +187,10 @@ trait Messages { case 'reply': case 'reply-all': - $this->MailClient()->MessageSetFlag($sDraftInfoFolder, new SequenceSet($iDraftInfoUid), - MessageFlag::ANSWERED); + $this->MailClient()->MessageSetFlag($sDraftInfoFolder, new SequenceSet($iDraftInfoUid), MessageFlag::ANSWERED); break; case 'forward': - $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', ''); - if (\strlen($sForwardedFlag)) - { - $this->MailClient()->MessageSetFlag($sDraftInfoFolder, new SequenceSet($iDraftInfoUid), - $sForwardedFlag); - } + $this->MailClient()->MessageSetFlag($sDraftInfoFolder, new SequenceSet($iDraftInfoUid), MessageFlag::FORWARDED); break; } } @@ -351,22 +345,18 @@ trait Messages $mResult = true; - $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', ''); - if (!empty($sReadReceiptFlag)) + $sFolderFullName = $this->GetActionParam('MessageFolder', ''); + $iUid = (int) $this->GetActionParam('MessageUid', 0); + + $this->Cacher($oAccount)->Set(\RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $iUid), '1'); + + if (\strlen($sFolderFullName) && 0 < $iUid) { - $sFolderFullName = $this->GetActionParam('MessageFolder', ''); - $iUid = (int) $this->GetActionParam('MessageUid', 0); - - $this->Cacher($oAccount)->Set(\RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $iUid), '1'); - - if (\strlen($sFolderFullName) && 0 < $iUid) + try { - try - { - $this->MailClient()->MessageSetFlag($sFolderFullName, new SequenceSet($iUid), $sReadReceiptFlag, true, true); - } - catch (\Throwable $oException) {} + $this->MailClient()->MessageSetFlag($sFolderFullName, new SequenceSet($iUid), MessageFlag::MDNSENT, true, true); } + catch (\Throwable $oException) {} } } } @@ -523,11 +513,10 @@ trait Messages $sFromFolder = $this->GetActionParam('FromFolder', ''); $sToFolder = $this->GetActionParam('ToFolder', ''); - $bMarkAsRead = !empty($this->GetActionParam('MarkAsRead', '0')); $oUids = new SequenceSet(\explode(',', (string) $this->GetActionParam('Uids', ''))); - if ($bMarkAsRead) + if (!empty($this->GetActionParam('MarkAsRead', '0'))) { try { @@ -539,6 +528,25 @@ trait Messages } } + $sLearning = $this->GetActionParam('Learning', ''); + if ($sLearning) + { + try + { + if ('SPAM' === $sLearning) { + $this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::JUNK); + $this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::NOTJUNK, false); + } else if ('HAM' === $sLearning) { + $this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::NOTJUNK); + $this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::JUNK, false); + } + } + catch (\Throwable $oException) + { + unset($oException); + } + } + try { $this->MailClient()->MessageMove($sFromFolder, $sToFolder, $oUids, 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 098664c4c..cbd71f682 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 @@ -194,10 +194,12 @@ trait Response 'FileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::ClearXss($sSubject) : 'message-'.$mResult['Uid']) . '.eml' )); - $sForwardedFlag = \strtolower($this->Config()->Get('labs', 'imap_forwarded_flag', '')); - $sReadReceiptFlag = \strtolower($this->Config()->Get('labs', 'imap_read_receipt_flag', '')); - \strlen($sForwardedFlag) && \in_array($sForwardedFlag, $mResult['Flags']) && \array_push($mResult['Flags'], '$forwarded'); - \strlen($sReadReceiptFlag) && \in_array($sReadReceiptFlag, $mResult['Flags']) && \array_push($mResult['Flags'], '$mdnsent'); + // https://datatracker.ietf.org/doc/html/rfc5788#section-3.4.1 + $key = \array_search('$readreceipt', $mResult['Flags']); + if (false !== $key) { + $mResult['Flags'][$key] = '$mdnsent'; + } + $mResult['Flags'] = \array_unique($mResult['Flags']); if ('Message' === $sParent) @@ -220,6 +222,7 @@ trait Response if (\strlen($mResult['ReadReceipt']) && !\in_array('$forwarded', $mResult['Flags'])) { + // \in_array('$mdnsent', $mResult['Flags']) if (\strlen($mResult['ReadReceipt'])) { try diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php index 0209bd3fc..94b0a71ce 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -355,8 +355,6 @@ Enables caching in the system'), 'use_imap_thread' => array(true), 'use_imap_move' => array(false), 'use_imap_expunge_all_on_delete' => array(false), - 'imap_forwarded_flag' => array('$Forwarded'), - 'imap_read_receipt_flag' => array('$ReadReceipt'), 'imap_body_text_limit' => array(555000), 'imap_message_list_fast_simple_search' => array(true), 'imap_message_list_count_limit_trigger' => array(0), From 0ebfa6af238675393c096f4a3d30935ef0c2e4b1 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 17:13:25 +0200 Subject: [PATCH 14/20] Reduce MessageView "Checked messages count" HTML & CSS --- dev/Styles/User/MessageView.less | 11 ++++------- .../app/templates/Views/User/MailMessageView.html | 5 +---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/dev/Styles/User/MessageView.less b/dev/Styles/User/MessageView.less index c23deddeb..07cb1082f 100644 --- a/dev/Styles/User/MessageView.less +++ b/dev/Styles/User/MessageView.less @@ -42,13 +42,10 @@ html.rl-no-preview-pane { line-height: 70px; padding-top: 100px; color: #999; - - .icon-mail { - font-size: 100px; - font-size: 50px; - line-height: 90px; - padding-left: 10px; - } + } + .b-message-view-checked-helper::after { + content: ' ✉'; + font-family: snappymail; } .b-message-view-desc { diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 76c68a2e2..f3f3cd4e6 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -25,10 +25,7 @@
-
- - -
+
From 899648d8e4d20c91cd6c30399f52578b20f91b94 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 20:38:35 +0200 Subject: [PATCH 15/20] Improved handling of imap message flags/keywords --- dev/Model/Message.js | 28 ++----------------- dev/Stores/User/Messagelist.js | 6 +--- dev/Styles/User/MessageList.less | 23 +++++++++++---- dev/View/User/MailBox/MessageList.js | 21 ++++---------- .../MailSo/Imap/Enumerations/MessageFlag.php | 2 ++ .../templates/Views/User/MailMessageList.html | 6 +--- 6 files changed, 29 insertions(+), 57 deletions(-) diff --git a/dev/Model/Message.js b/dev/Model/Message.js index acb582304..ab46130ac 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -97,11 +97,8 @@ export class MessageModel extends AbstractModel { isImportant: () => MessagePriority.High === this.priority(), hasAttachments: () => this.attachments().hasVisible(), - isDeleted: () => this.flags().includes('\\deleted'), - isUnseen: () => !this.flags().includes('\\seen') /* || this.flags().includes('\\unseen')*/, + isUnseen: () => !this.flags().includes('\\seen'), isFlagged: () => this.flags().includes('\\flagged'), - isAnswered: () => this.flags().includes('\\answered'), - isForwarded: () => this.flags().includes('$forwarded'), isReadReceipt: () => this.flags().includes('$mdnsent') // isJunk: () => this.flags().includes('$junk') && !this.flags().includes('$nonjunk'), // isPhishing: () => this.flags().includes('$phishing') @@ -291,13 +288,9 @@ export class MessageModel extends AbstractModel { let classes = []; forEachObjectEntry({ deleted: this.deleted(), - 'deleted-mark': this.isDeleted(), selected: this.selected(), checked: this.checked(), - flagged: this.isFlagged(), unseen: this.isUnseen(), - answered: this.isAnswered(), - forwarded: this.isForwarded(), focused: this.focused(), important: this.isImportant(), withAttachments: !!this.attachments().length, @@ -306,9 +299,7 @@ export class MessageModel extends AbstractModel { hasUnseenSubMessage: this.hasUnseenSubMessage(), hasFlaggedSubMessage: this.hasFlaggedSubMessage() }, (key, value) => value && classes.push(key)); - this.flags().forEach(value => { - '\\' !== value[0] && '$forwarded' !== value && classes.push('flag-'+value); - }); + this.flags().forEach(value => classes.push('flag-'+value)); return classes.join(' '); } @@ -578,19 +569,4 @@ export class MessageModel extends AbstractModel { return result.html || plainToHtml(this.plain()); } - /** - * @returns {string} - */ - flagHash() { - return [ - this.deleted(), - this.isDeleted(), - this.isUnseen(), - this.isFlagged(), - this.isAnswered(), - this.isForwarded(), - this.isReadReceipt() - ].join(','); - } - } diff --git a/dev/Stores/User/Messagelist.js b/dev/Stores/User/Messagelist.js index d24848ade..1b3750664 100644 --- a/dev/Stores/User/Messagelist.js +++ b/dev/Stores/User/Messagelist.js @@ -332,11 +332,7 @@ MessagelistUserStore.removeMessagesFromList = ( ? messageList.filter(item => item && uidForRemove.includes(pInt(item.uid))) : []; - messages.forEach(item => { - if (item && item.isUnseen()) { - ++unseenCount; - } - }); + messages.forEach(item => item && item.isUnseen() && ++unseenCount); if (fromFolder && !copy) { fromFolder.messageCountAll( diff --git a/dev/Styles/User/MessageList.less b/dev/Styles/User/MessageList.less index 2e9283a7e..55778d506 100644 --- a/dev/Styles/User/MessageList.less +++ b/dev/Styles/User/MessageList.less @@ -216,7 +216,7 @@ html:not(rl-mobile) { margin-right:5px } - &.deleted-mark { + &.flag-\\deleted { opacity: .7; .subjectParent { text-decoration: line-through; @@ -242,8 +242,6 @@ html:not(rl-mobile) { .attachmentParent { position: relative; margin: 2px 10px 0 5px; - color: #666; - text-shadow: 0 1px 0 #eee; } .senderParent, .subjectParent { @@ -340,15 +338,15 @@ html:not(rl-mobile) { .flagParent { padding: 0 10px 0 5px; } - &.flagged .flagParent::after, + &.flag-\\flagged .flagParent::after, &.hasFlaggedSubMessage .flagParent::after { color: orange; content: '★'; /*⚑*/ } - &:not(.flagged):not(.hasFlaggedSubMessage) .flagParent::after { + &:not(.flag-\\flagged):not(.hasFlaggedSubMessage) .flagParent::after { content: '☆'; /*⚐*/ } - &:not(.flagged):not(.hasFlaggedSubMessage) .flagParent:not(:hover) { + &:not(.flag-\\flagged):not(.hasFlaggedSubMessage) .flagParent:not(:hover) { opacity: 0.5; } } @@ -445,6 +443,19 @@ html:not(.rl-mobile):not(.rl-side-preview-pane) { } } +.senderParent::before { + font-family: snappymail; +} +.flag-\\answered .senderParent::before { + content: '← '; +} +.flag-\$forwarded .senderParent::before { + content: '→ '; +} +.flag-\\answered.flag-\$forwarded .senderParent::before { + content: '←→ '; +} + /* Thunderbird labels */ .flag-\$label5 .checkboxMessage { background-color: #808; } .flag-\$label4 .checkboxMessage { background-color: #00F; } diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 4b5f6595a..b49fd1dc9 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -571,21 +571,12 @@ export class MailMessageList extends AbstractViewRight { seenMessagesFast(seen) { const checked = MessagelistUserStore.listCheckedOrSelected(); - if (checked.length) { - if (undefined === seen) { - const unseen = checked.filter(message => message.isUnseen()); - listAction( - checked[0].folder, - unseen.length ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen, - checked - ); - } else { - listAction( - checked[0].folder, - seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen, - checked - ); - } + if (checked.length && null != seen) { + listAction( + checked[0].folder, + seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen, + checked + ); } } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php index 467938643..c42865ed8 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php @@ -7,6 +7,8 @@ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. + * + * https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml */ namespace MailSo\Imap\Enumerations; diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html index 7d35eb900..dce497560 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html @@ -133,11 +133,7 @@
-
- - - -
+
From 5ea5f54097982cf7d8e87179af58c07ab2e9a25d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 20:39:08 +0200 Subject: [PATCH 16/20] Fix message view menu order --- .../v/0.0.0/app/templates/Views/User/MailMessageView.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index f3f3cd4e6..5721b96e3 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -60,10 +60,10 @@
  • - +
  • - +
  • From d46537a24fb7e58fbbe2c240afecbe5442315d47 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 20:39:50 +0200 Subject: [PATCH 17/20] Different Thunderbird labels idea for #419 --- dev/Styles/User/MessageList.less | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dev/Styles/User/MessageList.less b/dev/Styles/User/MessageList.less index 55778d506..791f1904d 100644 --- a/dev/Styles/User/MessageList.less +++ b/dev/Styles/User/MessageList.less @@ -457,8 +457,20 @@ html:not(.rl-mobile):not(.rl-side-preview-pane) { } /* Thunderbird labels */ +/* .flag-\$label5 .checkboxMessage { background-color: #808; } .flag-\$label4 .checkboxMessage { background-color: #00F; } .flag-\$label3 .checkboxMessage { background-color: #080; } .flag-\$label2 .checkboxMessage { background-color: #FA0; } .flag-\$label1 .checkboxMessage { background-color: #F00; } +*/ +.messageListItem.flag-\$label5.focused { background-color: rgba(255, 0, 255, 0.30); } +.messageListItem.flag-\$label4.focused { background-color: rgba( 64, 64, 255, 0.30); } +.messageListItem.flag-\$label3.focused { background-color: rgba( 0, 255, 0, 0.30); } +.messageListItem.flag-\$label2.focused { background-color: rgba(255, 170, 0, 0.30); } +.messageListItem.flag-\$label1.focused { background-color: rgba(255, 0, 0, 0.30); } +.messageListItem.flag-\$label5:not(.focused) { color: #939; } +.messageListItem.flag-\$label4:not(.focused) { color: #33F; } +.messageListItem.flag-\$label3:not(.focused) { color: #090; } +.messageListItem.flag-\$label2:not(.focused) { color: #F90; } +.messageListItem.flag-\$label1:not(.focused) { color: #F00; } From baff1308e7fb0fbf85d0038250838e83f0a4d06a Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 20:55:55 +0200 Subject: [PATCH 18/20] Remove ugly attachmentItem box-shafow --- dev/Styles/User/Attachments.less | 4 ---- dev/Styles/User/MessageView.less | 8 -------- 2 files changed, 12 deletions(-) diff --git a/dev/Styles/User/Attachments.less b/dev/Styles/User/Attachments.less index 4ef482afd..93f73c80d 100644 --- a/dev/Styles/User/Attachments.less +++ b/dev/Styles/User/Attachments.less @@ -19,10 +19,6 @@ opacity: 0.6; } - &.checked { - box-shadow: 0 0 0 1px rgba(0, 0, 255, 0.1), 0 1px 5px rgba(0, 0, 255, 0.2); - } - .checkboxAttachment { bottom: 6px; cursor: pointer; diff --git a/dev/Styles/User/MessageView.less b/dev/Styles/User/MessageView.less index 07cb1082f..b39b406ff 100644 --- a/dev/Styles/User/MessageView.less +++ b/dev/Styles/User/MessageView.less @@ -300,14 +300,6 @@ html.rl-no-preview-pane { } } - &.unselectedAttachmentsError { - .attachmentItem { - box-shadow: 0 1px 4px red; - box-shadow: 0 1px 5px rgba(255, 0, 0, 0.4); - box-shadow: 0 0 0 1px rgba(255, 0, 0, 0.2), 0 1px 5px rgba(255, 0, 0, 0.3); - } - } - .controls-handle { position: absolute; bottom: 5px; From 5c99a14559632fd9da1684e816a656f4ba905df0 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 21:17:09 +0200 Subject: [PATCH 19/20] Simplify message view attachment controls --- dev/View/User/MailBox/MessageView.js | 10 ++++------ .../app/templates/Views/User/MailMessageView.html | 7 ++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index e4a9b8cab..75768be08 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -123,9 +123,6 @@ export class MailMessageView extends AbstractViewRight { this.fullScreenMode = isFullscreen; this.toggleFullScreen = toggleFullscreen; - this.messageListOfThreadsLoading = ko.observable(false).extend({ rateLimit: 1 }); - this.highlightUnselectedAttachments = ko.observable(false).extend({ falseTimeout: 2000 }); - this.downloadAsZipError = ko.observable(false).extend({ falseTimeout: 7000 }); this.messageDomFocused = ko.observable(false).extend({ rateLimit: 0 }); @@ -136,7 +133,10 @@ export class MailMessageView extends AbstractViewRight { this.addComputables({ allowAttachmentControls: () => arrayLength(attachmentsActions) && SettingsCapa('AttachmentsActions'), - downloadAsZipAllowed: () => this.attachmentsActions.includes('zip') && this.allowAttachmentControls(), + downloadAsZipAllowed: () => this.attachmentsActions.includes('zip') + && (currentMessage() ? currentMessage().attachments : []) + .filter(item => item && !item.isLinked() && item.checked() && item.download) + .length, lastReplyAction: { read: this.lastReplyAction_, @@ -538,8 +538,6 @@ export class MailMessageView extends AbstractViewRight { } }) .catch(() => this.downloadAsZipError(true)); - } else { - this.highlightUnselectedAttachments(true); } } diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 5721b96e3..4e2548800 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -213,8 +213,7 @@ data-icon="🖼" data-i18n="MESSAGE/BUTTON_SHOW_IMAGES">
    -
    +
    • @@ -241,7 +240,7 @@ click: function () { checked(!checked()); return false }">
    - +
    - - ×
    From 3fc781c1c1ed50b11ed9be1253d4a097747e76ef Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 31 May 2022 21:24:39 +0200 Subject: [PATCH 20/20] Drop application.ini imap_forwarded_flag and imap_read_receipt_flag --- .docker/release/files/usr/local/include/application.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/.docker/release/files/usr/local/include/application.ini b/.docker/release/files/usr/local/include/application.ini index ea6374ee5..9f0a6b09e 100644 --- a/.docker/release/files/usr/local/include/application.ini +++ b/.docker/release/files/usr/local/include/application.ini @@ -259,8 +259,6 @@ use_imap_force_selection = Off use_imap_thread = On use_imap_move = Off use_imap_expunge_all_on_delete = Off -imap_forwarded_flag = "$Forwarded" -imap_read_receipt_flag = "$ReadReceipt" imap_body_text_limit = 555000 imap_message_list_fast_simple_search = On imap_message_list_count_limit_trigger = 0