diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 8988c58b9..1f4a08d18 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -75,10 +75,11 @@ export class MessageModel extends AbstractModel { hasExternals: false, pgpSigned: null, - pgpEncrypted: null, - isPgpEncrypted: false, pgpVerified: null, + pgpEncrypted: null, + pgpDecrypted: false, + readReceipt: '', hasUnseenSubMessage: false, @@ -153,10 +154,11 @@ export class MessageModel extends AbstractModel { this.attachments(new AttachmentCollectionModel); this.pgpSigned(null); - this.pgpEncrypted(null); - this.isPgpEncrypted(false); this.pgpVerified(null); + this.pgpEncrypted(null); + this.pgpDecrypted(false); + this.priority(MessagePriority.Normal); this.readReceipt(''); @@ -472,6 +474,7 @@ export class MessageModel extends AbstractModel { initView() { // init BlockquoteSwitcher this.body.querySelectorAll('blockquote:not(.rl-bq-switcher)').forEach(node => { + node.removeAttribute('style') if (node.textContent.trim() && !node.parentNode.closest('blockquote')) { let h = node.clientHeight || getRealHeight(node); if (0 === h || 100 < h) { diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index 7a05f7542..5209cac08 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -372,7 +372,7 @@ export const MessageUserStore = new class { } else { body = Element.fromHTML('
'); message.body = body; diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index a0807894b..79ed2fbc5 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -176,7 +176,7 @@ export const } } else { body.classList.add('mailvelope'); - return; + return true; } } } diff --git a/dev/Styles/User/MessageView.less b/dev/Styles/User/MessageView.less index 6a356ba2f..f85c12ca5 100644 --- a/dev/Styles/User/MessageView.less +++ b/dev/Styles/User/MessageView.less @@ -174,264 +174,6 @@ html.rl-no-preview-pane { } } - #messageItem { - - color: #000; - height: 100%; - overflow: auto; - scroll-behavior: smooth; - - .buttonFull { - display: inline-block; - position: fixed; - right: 25px; - bottom: 25px; - height: 30px; - width: 30px; - text-align: center; - vertical-align: middle; - line-height: 30px; - background-color: transparent; - background-color: #fff; - border: 1px solid #333; - color: #333; - z-index: 2; - cursor: pointer; - border-radius: 5px; - opacity: 0.5; - - &:hover { - opacity: 0.8; - border-color: #666; - background-color: #888; - color: #fff; - } - } - - .loading { - text-align: center; - font-size: 24px; - color: grey; - padding: 50px 0; - } - - .showImages, .readReceipt, .pgpSigned, .pgpEncrypted { - cursor: pointer; - padding: 10px 15px; - border-bottom: 1px solid #ddd; - background-color: #eee; - } - - .pgpInfo { - padding: 5px 15px; - border-bottom: 1px solid #ddd; - background-color: #fcf8e3; - - &.success { - background-color: #e9f4ff; - } - } - - .readReceipt { - background-color: #ffffd9; - } - - .attachmentsPlace { - - padding: 10px 10px 6px 10px; - background: #eee; - border-bottom: 1px solid #ddd; - position: relative; - - .attachmentList { - margin: 0; - } - - &:not(.selection-mode) { - .checkboxAttachment { - display: none; - } - } - - &.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; - right: 8px; - color: #999; - cursor: pointer; - } - } - - .attachmentsControls { - padding: 7px 5px 7px 14px; - background: #e8e8e8; - border-bottom: 1px solid #ddd; - } - - .rlBlockquoteSwitcher { - border: 1px solid #999; - display: block; - width: 3em; - line-height: 1em; - text-align: center; - cursor: pointer; - margin: 2em 0 10px; - - opacity: 0.5; - &:hover { - opacity: 1; - } - } - - .b-text-part { - - height: 100%; - - div[data-x-div-type=html] { - height: 100%; - div[data-x-div-type=body] { - height: 100%; - } - } - - a { - color: blue; - text-decoration: underline; - - &:visited { - color: #609; - } - &:active { - color: red; - } - } - - blockquote { - border-left: 2px solid #000; - padding: 0 10px; - margin: 0; - } - - .rl-bq-switcher.hidden-bq { - display: none; - } - - &.html { - - div[data-x-div-type=body] { - /*padding: 15px;*/ - margin: 15px; - } - - img { - max-width: 90vw; - } - img[data-x-src]:not([src]) { - border: 1px solid #999; - position: relative; - } - img[data-x-src]:not([src])::after { - content: "🖼"; - font-family: snappymail; - position: absolute; - top: 0; - left: 0; - color: #000; - background-color: #fff; - } - img[data-x-src]:not([src]):hover::after { - content: attr(data-x-src); - font-family: var(--fontSans); - font-size: 11px; - height: auto; - transform: translate(-25%,0); - width: auto; - width: -moz-fit-content; - width: -webkit-fit-content; - width: fit-content; - z-index: 1000; - } - - pre, code { - margin: 0; - border: none; - word-break: normal; - word-wrap: break-word; - } - - code { - border-radius: 0; - display: inline; - padding: 2px 5px; - } - - pre { - border-radius: 5px; - display: block; - padding: 5px 10px; - } - - pre > code { - padding: 0; - } - } - - &.plain { - - padding: 15px; - white-space: pre-wrap; - font-family: var(--fontMono); - - pre { - margin: 0; - padding: 0; - border: none; - display: block; - word-break: normal; - } - - blockquote { - border-left: 2px solid blue; - color: blue; - } - - blockquote blockquote { - border-left: 2px solid green; - color: green; - } - - blockquote blockquote blockquote { - border-left: 2px solid red; - color: red; - } - } - -/* - &.openpgp-signed, - &.openpgp-encrypted { - border: 1px dashed #FA0; - - &.success { - border-color: green; - background-color: rgba(0, 255, 0, 0.03); - } - &.error { - border-color: red; - background-color: rgba(255, 0, 0, 0.03); - } - } -*/ - } - } - .openpgp-control { margin: 0.5em; padding: 0.5em; @@ -482,6 +224,249 @@ html.rl-no-preview-pane { } } +#messageItem { + + color: #000; + height: 100%; + overflow: auto; + scroll-behavior: smooth; + + .buttonFull { + display: inline-block; + position: fixed; + right: 25px; + bottom: 25px; + height: 30px; + width: 30px; + text-align: center; + vertical-align: middle; + line-height: 30px; + background-color: transparent; + background-color: #fff; + border: 1px solid #333; + color: #333; + z-index: 2; + cursor: pointer; + border-radius: 5px; + opacity: 0.5; + + &:hover { + opacity: 0.8; + border-color: #666; + background-color: #888; + color: #fff; + } + } + + .loading { + text-align: center; + font-size: 24px; + color: grey; + padding: 50px 0; + } + + .showImages, .readReceipt, .pgpSigned, .pgpEncrypted { + cursor: pointer; + padding: 10px 15px; + border-bottom: 1px solid #ddd; + background-color: #eee; + } + + .pgpInfo { + padding: 5px 15px; + border-bottom: 1px solid #ddd; + background-color: #fcf8e3; + + &.success { + background-color: #e9f4ff; + } + } + + .readReceipt { + background-color: #ffffd9; + } + + .attachmentsPlace { + + padding: 10px 10px 6px 10px; + background: #eee; + border-bottom: 1px solid #ddd; + position: relative; + + .attachmentList { + margin: 0; + } + + &:not(.selection-mode) { + .checkboxAttachment { + display: none; + } + } + + &.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; + right: 8px; + color: #999; + cursor: pointer; + } + } + + .attachmentsControls { + padding: 7px 5px 7px 14px; + background: #e8e8e8; + border-bottom: 1px solid #ddd; + } + + .rlBlockquoteSwitcher { + border: 1px solid #999; + display: block; + width: 3em; + line-height: 1em; + text-align: center; + cursor: pointer; + margin: 2em 0 10px; + opacity: 0.5; + &:hover { + opacity: 1; + } + } + + .b-text-part { + + height: 100%; + padding: 10px; + + div[data-x-div-type=html] { + height: 100%; + div[data-x-div-type=body] { + height: 100%; + } + } + + a { + color: blue; + text-decoration: underline; + + &:visited { + color: #609; + } + &:active { + color: red; + } + } + + blockquote { + border-left: 2px solid #000; + opacity: 0.8; + padding: 0 10px; + margin: 0; + } + + .rl-bq-switcher.hidden-bq { + display: none; + } + + &.html { + + div[data-x-div-type=body] { + /*padding: 15px;*/ + margin: 15px; + } + + img { + max-width: 90vw; + } + img[data-x-src]:not([src]) { + border: 1px solid #999; + position: relative; + } + img[data-x-src]:not([src])::after { + content: "🖼"; + font-family: snappymail; + position: absolute; + top: 0; + left: 0; + color: #000; + background-color: #fff; + } + img[data-x-src]:not([src]):hover::after { + content: attr(data-x-src); + font-family: var(--fontSans); + font-size: 11px; + height: auto; + transform: translate(-25%,0); + width: auto; + width: -moz-fit-content; + width: -webkit-fit-content; + width: fit-content; + z-index: 1000; + } + + pre, code { + margin: 0; + border: none; + word-break: normal; + word-wrap: break-word; + } + + code { + border-radius: 0; + display: inline; + padding: 2px 5px; + } + + pre { + border-radius: 5px; + display: block; + padding: 5px 10px; + } + + pre > code { + padding: 0; + } + } + + &.plain { + + white-space: pre-wrap; + font-family: var(--fontMono); + + pre { + margin: 0; + padding: 0; + border: none; + display: block; + word-break: normal; + } + } + +/* + &.openpgp-signed, + &.openpgp-encrypted { + border: 1px dashed #FA0; + + &.success { + border-color: green; + background-color: rgba(0, 255, 0, 0.03); + } + &.error { + border-color: red; + background-color: rgba(255, 0, 0, 0.03); + } + } +*/ + } +} + html.rl-no-preview-pane .messageView { .toolbar { diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 147743ce6..c63d1f8c6 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -583,15 +583,18 @@ export class MailMessageView extends AbstractViewRight { pgpDecrypt() { const oMessage = currentMessage(); PgpUserStore.decrypt(oMessage).then(result => { - if (result && result.data) { - MimeToMessage(result.data, oMessage); - oMessage.html() ? oMessage.viewHtml() : oMessage.viewPlain(); - if (result.signatures && result.signatures.length) { - oMessage.pgpSigned(true); - oMessage.pgpVerified({ - signatures: result.signatures, - success: !!result.signatures.length - }); + if (result) { + oMessage.pgpDecrypted(true); + if (result.data) { + MimeToMessage(result.data, oMessage); + oMessage.html() ? oMessage.viewHtml() : oMessage.viewPlain(); + if (result.signatures && result.signatures.length) { + oMessage.pgpSigned(true); + oMessage.pgpVerified({ + signatures: result.signatures, + success: !!result.signatures.length + }); + } } } }); diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php index e40a36a03..964350572 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -78,8 +78,7 @@ class Message implements \JsonSerializable $aThreads = array(), $aPgpSigned = null, - $aPgpEncrypted = null, - $bPgpEncrypted = false; + $aPgpEncrypted = null; function __construct() { @@ -106,11 +105,6 @@ class Message implements \JsonSerializable return $this->aPgpEncrypted; } - public function isPgpEncrypted() : bool - { - return $this->bPgpEncrypted || $this->aPgpEncrypted; - } - public function Folder() : string { return $this->sFolder; @@ -491,10 +485,6 @@ class Message implements \JsonSerializable $oMessage->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, ''); } - // Content-Type: multipart/encrypted; protocol="application/pgp-encrypted" - $oMessage->bPgpEncrypted = ('multipart/encrypted' === \strtolower($oMessage->sContentType) - && 'application/pgp-encrypted' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL))); - if ($oBodyStructure) { $gEncryptedParts = $oBodyStructure->SearchByContentType('multipart/encrypted'); @@ -573,25 +563,25 @@ class Message implements \JsonSerializable ]; } + if (\str_contains($sText, '-----BEGIN PGP MESSAGE-----')) + { + $keyIds = []; + if (\SnappyMail\PGP\GPG::isSupported()) { + $GPG = new \SnappyMail\PGP\GPG(''); + $keyIds = $GPG->getEncryptedMessageKeys($sText); + } + $oMessage->aPgpEncrypted = [ + 'PartId' => $oPart->PartID(), + 'KeyIds' => $keyIds + ]; + } + if ('text/html' === $oPart->ContentType()) { $aHtmlParts[] = $sText; } else { - if (\str_contains($sText, '-----BEGIN PGP MESSAGE-----')) - { - $keyIds = []; - if (\SnappyMail\PGP\GPG::isSupported()) { - $GPG = new \SnappyMail\PGP\GPG(''); - $keyIds = $GPG->getEncryptedMessageKeys($sText); - } - $oMessage->aPgpEncrypted = [ - 'PartId' => $oPart->PartID(), - 'KeyIds' => $keyIds - ]; - } - if ($oPart->IsFlowedFormat()) { $sText = Utils::DecodeFlowedFormat($sText); @@ -605,9 +595,7 @@ class Message implements \JsonSerializable $oMessage->sHtml = \implode('