Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2020-05-04 18:28:12 +0300
committerChristoph Wurst <christoph@winzerhof-wurst.at>2020-05-12 15:54:39 +0300
commit7d035b022c741a292dd1220154f0f74af5cd3548 (patch)
tree756ccf738e0a90c849e0f82dba7c63f3d0a3f0e7
parent6f757189f3f345af082fc530095c058a68fa413a (diff)
Fix mailvelope integration by switching to the API version
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
-rwxr-xr-xcss/mail.scss4
-rw-r--r--src/components/AppSettingsMenu.vue6
-rw-r--r--src/components/Composer.vue110
-rw-r--r--src/components/MailvelopeEditor.vue82
-rw-r--r--src/components/Message.vue11
-rw-r--r--src/components/MessageEncryptedBody.vue42
-rw-r--r--src/components/NewMessageDetail.vue3
-rw-r--r--src/crypto/mailvelope.js48
-rw-r--r--src/crypto/pgp.js29
-rw-r--r--src/tests/unit/crypto/mailvelope.spec.js49
-rw-r--r--src/tests/unit/crypto/pgp.spec.js49
11 files changed, 411 insertions, 22 deletions
diff --git a/css/mail.scss b/css/mail.scss
index 918f1d03a..54d6668ee 100755
--- a/css/mail.scss
+++ b/css/mail.scss
@@ -316,10 +316,6 @@
.mailaccount-list .actions {
opacity: .5;
}
-.app-settings-hint {
- margin-top: 15px;
- color: #555;
-}
/* icons */
.icon-inbox {
diff --git a/src/components/AppSettingsMenu.vue b/src/components/AppSettingsMenu.vue
index 5a3c8dfdf..39490f143 100644
--- a/src/components/AppSettingsMenu.vue
+++ b/src/components/AppSettingsMenu.vue
@@ -48,12 +48,6 @@
{{ t('mail', 'Keyboard shortcuts') }}
</router-link>
</p>
-
- <p class="app-settings-hint app-settings-link">
- <a href="https://www.mailvelope.com/" target="_blank">{{
- t('mail', 'Looking for a way to encrypt your emails? Install the Mailvelope browser extension!')
- }}</a>
- </p>
</div>
</template>
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index 490f62bed..d9bf0b372 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -103,13 +103,20 @@
@keyup="onInputChanged"
/>
</div>
- <div v-if="noReply" class="warning noreply-box">
+ <div v-if="noReply" class="warning noreply-warning">
{{ t('mail', 'This message came from a noreply address so your reply will probably not be read.') }}
</div>
+ <div v-if="mailvelope.keysMissing.length" class="warning noreply-warning">
+ {{
+ t('mail', 'The following recipients do not have a PGP key: {recipients}.', {
+ recipients: mailvelope.keysMissing.join(', '),
+ })
+ }}
+ </div>
<div class="composer-fields">
<!--@keypress="onBodyKeyPress"-->
<TextEditor
- v-if="editorPlainText"
+ v-if="!encrypt && editorPlainText"
key="editor-plain"
v-model="bodyVal"
name="body"
@@ -120,7 +127,7 @@
@input="onInputChanged"
></TextEditor>
<TextEditor
- v-else
+ v-else-if="!encrypt && !editorPlainText"
key="editor-rich"
v-model="bodyVal"
:html="true"
@@ -131,6 +138,14 @@
:bus="bus"
@input="onInputChanged"
></TextEditor>
+ <MailvelopeEditor
+ v-else
+ ref="mailvelopeEditor"
+ v-model="bodyVal"
+ :recipients="allRecipients"
+ :quoted-text="body"
+ :is-reply-or-forward="isReply || isForward"
+ />
</div>
<div class="composer-actions">
<ComposerAttachments v-model="attachments" :bus="bus" @upload="onAttachmentsUploading" />
@@ -146,16 +161,26 @@
<ActionButton icon="icon-folder" @click="onAddCloudAttachment">{{
t('mail', 'Add attachment from Files')
}}</ActionButton>
- <ActionButton icon="icon-folder" @click="onAddCloudAttachmentLink">{{
+ <ActionButton :disabled="encrypt" icon="icon-folder" @click="onAddCloudAttachmentLink">{{
t('mail', 'Add attachment link from Files')
}}</ActionButton>
<ActionCheckbox
- :checked="!editorPlainText"
- :text="t('mail', 'Enable formatting')"
+ :checked="!encrypt && !editorPlainText"
+ :disabled="encrypt"
@check="editorPlainText = false"
@uncheck="editorPlainText = true"
>{{ t('mail', 'Enable formatting') }}</ActionCheckbox
>
+ <ActionCheckbox
+ v-if="mailvelope.available"
+ :checked="encrypt"
+ @check="encrypt = true"
+ @uncheck="encrypt = false"
+ >{{ t('mail', 'Encrypt message with Mailvelope') }}</ActionCheckbox
+ >
+ <ActionLink v-else href="https://www.mailvelope.com/" target="_blank" icon="icon-password">{{
+ t('mail', 'Looking for a way to encrypt your emails? Install the Mailvelope browser extension!')
+ }}</ActionLink>
</Actions>
<div>
<input
@@ -193,17 +218,21 @@ import debouncePromise from 'debounce-promise'
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
+import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import {translate as t} from '@nextcloud/l10n'
import Vue from 'vue'
import ComposerAttachments from './ComposerAttachments'
import {findRecipient} from '../service/AutocompleteService'
-import {detect, html, toHtml, toPlain} from '../util/text'
+import {detect, html, plain, toHtml, toPlain} from '../util/text'
import Loading from './Loading'
import logger from '../logger'
import TextEditor from './TextEditor'
import {buildReplyBody} from '../ReplyBuilder'
+import MailvelopeEditor from './MailvelopeEditor'
+import {getMailvelope} from '../crypto/mailvelope'
+import {isPgpgMessage} from '../crypto/pgp'
const debouncedSearch = debouncePromise(findRecipient, 500)
@@ -220,9 +249,11 @@ const STATES = Object.seal({
export default {
name: 'Composer',
components: {
+ MailvelopeEditor,
Actions,
ActionButton,
ActionCheckbox,
+ ActionLink,
ComposerAttachments,
Loading,
Multiselect,
@@ -282,7 +313,6 @@ export default {
bodyVal: toHtml(this.body).value,
attachments: [],
noReply: this.to.some((to) => to.email.startsWith('noreply@') || to.email.startsWith('no-reply@')),
- submitButtonTitle: t('mail', 'Send'),
draftsPromise: Promise.resolve(),
attachmentsPromise: Promise.resolve(),
savingDraft: undefined,
@@ -294,21 +324,37 @@ export default {
selectCc: this.cc,
selectBcc: this.bcc,
bus: new Vue(),
+ encrypt: false,
+ mailvelope: {
+ available: false,
+ keyRing: undefined,
+ keysMissing: [],
+ },
}
},
computed: {
aliases() {
return this.$store.getters.accounts.filter((a) => !a.isUnified)
},
+ allRecipients() {
+ return this.selectTo.concat(this.selectCc).concat(this.selectBcc)
+ },
selectableRecipients() {
return this.newRecipients
.concat(this.autocompleteRecipients)
.map((recipient) => ({...recipient, label: recipient.label || recipient.email}))
},
+ isForward() {
+ return this.forwardFrom !== undefined
+ },
isReply() {
return this.replyTo !== undefined
},
canSend() {
+ if (this.encrypt && this.mailvelope.keysMissing.length) {
+ return false
+ }
+
return this.selectTo.length > 0 || this.selectCc.length > 0 || this.selectBcc.length > 0
},
editorPlainText() {
@@ -317,15 +363,27 @@ export default {
}
return false
},
+ submitButtonTitle() {
+ if (!this.mailvelope.available) {
+ return t('mail', 'Send')
+ }
+
+ return this.encrypt ? t('mail', 'Encrypt and send') : t('mail', 'Send unencrypted')
+ },
},
watch: {
'$route.params.messageUid'(newID) {
this.reset()
},
+ allRecipients() {
+ this.checkRecipientsKeys()
+ },
},
- beforeMount() {
+ async beforeMount() {
this.setAlias()
this.initBody()
+
+ await this.onMailvelopeLoaded(await getMailvelope())
},
mounted() {
this.$refs.toLabel.$el.focus()
@@ -343,6 +401,8 @@ export default {
},
beforeDestroy() {
this.$root.$off('newMessage')
+
+ window.removeEventListener('mailvelope', this.onMailvelopeLoaded)
},
methods: {
setAlias() {
@@ -352,6 +412,16 @@ export default {
this.selectedAlias = this.aliases[0]
}
},
+ async checkRecipientsKeys() {
+ if (!this.encrypt || !this.mailvelope.available) {
+ return
+ }
+
+ const recipients = this.allRecipients.map((r) => r.email)
+ const keysValid = await this.mailvelope.keyRing.validKeyForAddress(recipients)
+ logger.debug('recipients keys validated', {recipients, keysValid})
+ this.mailvelope.keysMissing = recipients.filter((r) => keysValid[r] === false)
+ },
initBody() {
if (this.replyTo) {
this.bodyVal = this.bodyWithSignature(
@@ -398,7 +468,7 @@ export default {
bcc: this.selectBcc.map(this.recipientToRfc822).join(', '),
draftUID: uid,
subject: this.subjectVal,
- body: html(this.bodyVal),
+ body: this.encrypt ? plain(this.bodyVal) : html(this.bodyVal),
attachments: this.attachments,
folderId: this.replyTo ? this.replyTo.folderId : undefined,
messageId: this.replyTo ? this.replyTo.id : undefined,
@@ -460,6 +530,17 @@ export default {
.catch((error) => logger.error('could not upload attachments', {error}))
.then(() => logger.debug('attachments uploaded'))
},
+ async onMailvelopeLoaded(mailvelope) {
+ this.encrypt = isPgpgMessage(this.body)
+ this.mailvelope.available = true
+ logger.info('Mailvelope loaded', {
+ encrypt: this.encrypt,
+ isPgpgMessage: isPgpgMessage(this.body),
+ keyRing: this.mailvelope.keyRing,
+ })
+ this.mailvelope.keyRing = await mailvelope.getKeyring()
+ await this.checkRecipientsKeys()
+ },
onNewToAddr(addr) {
this.onNewAddr(addr, this.selectTo)
},
@@ -477,7 +558,12 @@ export default {
this.newRecipients.push(res)
list.push(res)
},
- onSend() {
+ async onSend() {
+ if (this.encrypt) {
+ logger.debug('get encrypted message from mailvelope')
+ await this.$refs.mailvelopeEditor.pull()
+ }
+
this.state = STATES.UPLOADING
return this.attachmentsPromise
@@ -598,7 +684,7 @@ export default {
padding: 24px 12px;
}
-.noreply-box {
+.warning-box {
padding: 5px 12px;
border-radius: 0;
}
diff --git a/src/components/MailvelopeEditor.vue b/src/components/MailvelopeEditor.vue
new file mode 100644
index 000000000..13e8bcf29
--- /dev/null
+++ b/src/components/MailvelopeEditor.vue
@@ -0,0 +1,82 @@
+<!--
+ - @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ -
+ - @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<template>
+ <div id="mailvelope-composer"></div>
+</template>
+
+<script>
+import logger from '../logger'
+import {isPgpgMessage} from '../crypto/pgp'
+
+export default {
+ name: 'MailvelopeEditor',
+ props: {
+ value: {
+ type: String,
+ required: true,
+ },
+ recipients: {
+ type: Array,
+ required: true,
+ },
+ quotedText: {
+ type: Object,
+ required: false,
+ default: () => undefined,
+ },
+ isReplyOrForward: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ editor: undefined,
+ }
+ },
+ async mounted() {
+ const isEncrypted = this.quotedText ? isPgpgMessage(this.quotedText) : false
+ const quotedMail = this.isReplyOrForward ? this.quotedText?.value : undefined
+
+ this.editor = await window.mailvelope.createEditorContainer('#mailvelope-composer', undefined, {
+ quotedMail: isEncrypted ? quotedMail : undefined,
+ })
+ },
+ methods: {
+ async pull() {
+ const recipients = this.recipients.map((r) => r.email)
+ logger.info('encrypting message', {recipients})
+ const armored = await this.editor.encrypt(recipients)
+ logger.info('message encryted', {armored})
+
+ this.$emit('input', armored)
+ },
+ },
+}
+</script>
+
+<style scoped>
+#mailvelope-composer {
+ width: 100%;
+ height: 450px;
+}
+</style>
diff --git a/src/components/Message.vue b/src/components/Message.vue
index 614a9daff..e6305de75 100644
--- a/src/components/Message.vue
+++ b/src/components/Message.vue
@@ -66,6 +66,7 @@
<Itinerary :entries="message.itineraries" :message-id="message.messageId" />
</div>
<MessageHTMLBody v-if="message.hasHtmlBody" :url="htmlUrl" />
+ <MessageEncryptedBody v-else-if="isEncrypted" :body="message.body" :from="from" />
<MessagePlainTextBody v-else :body="message.body" :signature="message.signature" />
<Popover v-if="message.attachments[0]" class="attachment-popover">
<Actions slot="trigger">
@@ -92,7 +93,10 @@ import AddressList from './AddressList'
import {buildRecipients as buildReplyRecipients, buildReplySubject} from '../ReplyBuilder'
import Error from './Error'
import {getRandomMessageErrorMessage} from '../util/ErrorMessageFactory'
+import {html, plain} from '../util/text'
+import {isPgpgMessage} from '../crypto/pgp'
import Itinerary from './Itinerary'
+import MessageEncryptedBody from './MessageEncryptedBody'
import MessageHTMLBody from './MessageHTMLBody'
import MessagePlainTextBody from './MessagePlainTextBody'
import Loading from './Loading'
@@ -110,6 +114,7 @@ export default {
Itinerary,
Loading,
MessageAttachments,
+ MessageEncryptedBody,
MessageHTMLBody,
MessagePlainTextBody,
Modal,
@@ -130,6 +135,12 @@ export default {
}
},
computed: {
+ from() {
+ return this.message.from[0]?.email
+ },
+ isEncrypted() {
+ return isPgpgMessage(this.message.hasHtmlBody ? html(this.message.body) : plain(this.message.body))
+ },
htmlUrl() {
return generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{id}/html', {
accountId: this.message.accountId,
diff --git a/src/components/MessageEncryptedBody.vue b/src/components/MessageEncryptedBody.vue
new file mode 100644
index 000000000..5d0718fc0
--- /dev/null
+++ b/src/components/MessageEncryptedBody.vue
@@ -0,0 +1,42 @@
+<template>
+ <div>
+ <div v-if="mailvelope" id="mail-content"></div>
+ <span v-else>{{ t('mail', 'This message is encrypted with PGP. Install Mailvelope to decrypt it.') }}</span>
+ </div>
+</template>
+
+<script>
+import {getMailvelope} from '../crypto/mailvelope'
+
+export default {
+ name: 'MessageEncryptedBody',
+ props: {
+ body: {
+ type: String,
+ required: true,
+ },
+ from: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ },
+ data() {
+ return {
+ mailvelope: false,
+ }
+ },
+ async mounted() {
+ this.mailvelope = await getMailvelope()
+ this.mailvelope.createDisplayContainer('#mail-content', this.body, undefined, {
+ senderAddress: this.from,
+ })
+ },
+}
+</script>
+
+<style scoped>
+#mail-content {
+ height: 450px;
+}
+</style>
diff --git a/src/components/NewMessageDetail.vue b/src/components/NewMessageDetail.vue
index ddb6a211a..ae199c331 100644
--- a/src/components/NewMessageDetail.vue
+++ b/src/components/NewMessageDetail.vue
@@ -81,6 +81,7 @@ export default {
cc: [],
subject: buildReplySubject(message.subject),
body: this.originalBody,
+ originalBody: this.originalBody,
replyTo: message,
}
} else if (this.$route.params.messageUid === 'replyAll') {
@@ -97,6 +98,7 @@ export default {
cc: recipients.cc,
subject: buildReplySubject(message.subject),
body: this.originalBody,
+ originalBody: this.originalBody,
replyTo: message,
}
} else {
@@ -107,6 +109,7 @@ export default {
cc: [],
subject: buildForwardSubject(message.subject),
body: this.originalBody,
+ originalBody: this.originalBody,
forwardFrom: message,
}
}
diff --git a/src/crypto/mailvelope.js b/src/crypto/mailvelope.js
new file mode 100644
index 000000000..943c73a6b
--- /dev/null
+++ b/src/crypto/mailvelope.js
@@ -0,0 +1,48 @@
+/*
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import logger from '../logger'
+
+let mailvelope
+
+const loadMailvelopeStatically = () => window.mailvelope
+
+const loadMailvelopeDynamically = () =>
+ new Promise((res) => {
+ window.addEventListener('mailvelope', () => res(window.mailvelope), false)
+ })
+
+export const getMailvelope = async () => {
+ if (mailvelope) {
+ return mailvelope
+ }
+
+ mailvelope = loadMailvelopeStatically()
+ if (mailvelope) {
+ logger.debug('mailvelope found statically')
+ return mailvelope
+ }
+
+ logger.debug('loading mailvelope dynamically')
+ mailvelope = await loadMailvelopeDynamically()
+ logger.debug('mailvelope found dynamically')
+ return mailvelope
+}
diff --git a/src/crypto/pgp.js b/src/crypto/pgp.js
new file mode 100644
index 000000000..95d8b4fb5
--- /dev/null
+++ b/src/crypto/pgp.js
@@ -0,0 +1,29 @@
+/*
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import startsWith from 'lodash/fp/startsWith'
+
+/**
+ * @param {Text} message
+ * @return {boolean|*}
+ */
+export const isPgpgMessage = (message) =>
+ message.format === 'plain' && message.value.startsWith('-----BEGIN PGP MESSAGE-----')
diff --git a/src/tests/unit/crypto/mailvelope.spec.js b/src/tests/unit/crypto/mailvelope.spec.js
new file mode 100644
index 000000000..a1e1c372f
--- /dev/null
+++ b/src/tests/unit/crypto/mailvelope.spec.js
@@ -0,0 +1,49 @@
+/*
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import {getMailvelope} from '../../../crypto/mailvelope'
+
+describe('mailvelope', () => {
+ afterEach(() => {
+ delete window.mailvelope
+ })
+
+ it('loads statically', async () => {
+ window.mailvelope = {
+ mock: 3,
+ }
+
+ const mailvelope = await getMailvelope()
+
+ expect(mailvelope).to.deep.equal(window.mailvelope)
+ })
+
+ it('loads dynamically', async () => {
+ const p = getMailvelope()
+ window.mailvelope = {
+ mock: 3,
+ }
+ window.dispatchEvent(new Event('mailvelope'))
+
+ const mailvelope = await p
+ expect(mailvelope).to.deep.equal(window.mailvelope)
+ })
+})
diff --git a/src/tests/unit/crypto/pgp.spec.js b/src/tests/unit/crypto/pgp.spec.js
new file mode 100644
index 000000000..c62f72c76
--- /dev/null
+++ b/src/tests/unit/crypto/pgp.spec.js
@@ -0,0 +1,49 @@
+/*
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import {isPgpgMessage} from '../../../crypto/pgp'
+import {html, plain} from '../../../util/text'
+
+describe('pgp', () => {
+ it('detects non-pgp messages', () => {
+ const messages = plain('Hi Alice')
+
+ const isPgp = isPgpgMessage(messages)
+
+ expect(isPgp).to.equal(false)
+ })
+
+ it('detects non-pgp HTML messages', () => {
+ const messages = html('Hi Alice')
+
+ const isPgp = isPgpgMessage(messages)
+
+ expect(isPgp).to.equal(false)
+ })
+
+ it('detects a pgp message', () => {
+ const message = plain('-----BEGIN PGP MESSAGE-----\nVersion: Mailvelope v4.3.1')
+
+ const isPgp = isPgpgMessage(message)
+
+ expect(isPgp).to.equal(true)
+ })
+})