Bug 1673241 - Improve handling of mixed MIME and inline OpenPGP. r=PatrickBrunschwig,mkmelin
authorKai Engert <kaie@kuix.de>
Thu, 01 Apr 2021 19:10:23 +0200
changeset 32280 34b4c229c416a707188eb2ddf0698c7d1cd8fe11
parent 32279 344d6a52a2de8f7e9e2bcd29677c34fdb9a69a7c
child 32281 32ecec9855f60a5106141d4e343881a9cce64190
push id18694
push userkaie@kuix.de
push dateTue, 20 Apr 2021 22:06:02 +0000
treeherdercomm-central@34b4c229c416 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersPatrickBrunschwig, mkmelin
bugs1673241
Bug 1673241 - Improve handling of mixed MIME and inline OpenPGP. r=PatrickBrunschwig,mkmelin Differential Revision: https://phabricator.services.mozilla.com/D110588
mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
mail/test/browser/openpgp/browser_viewMessage.js
mail/test/browser/openpgp/data/eml/alice-partially-encrypted.eml
mail/test/browser/openpgp/data/eml/bob-enc-html-nbsp.eml
mail/test/browser/openpgp/data/eml/partial-encrypt-for-alice-html.eml
mail/test/browser/openpgp/data/eml/partial-encrypt-for-alice-plaintext.eml
mail/test/browser/openpgp/data/eml/partial-encrypt-for-carol-html.eml
mail/test/browser/openpgp/data/eml/partial-encrypt-for-carol-plaintext.eml
mail/test/browser/openpgp/data/eml/partial-signed-from-bob-html.eml
mail/test/browser/openpgp/data/eml/partial-signed-from-bob-plaintext.eml
mail/test/browser/openpgp/data/eml/partial-signed-from-carol-html.eml
mail/test/browser/openpgp/data/eml/partial-signed-from-carol-plaintext.eml
--- a/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
@@ -1003,34 +1003,41 @@ Enigmail.msg = {
       "",
       "",
       uri,
       "",
       "1"
     );
   },
 
-  trimIfEncrypted(msgText) {
-    // If it's an encrypted message, we want to trim (at least) the
-    // separator line between the header and the content.
-    // However, trimming all lines should be safe.
-    let trimEncrypted = false;
-
+  getFirstPGPMessageType(msgText) {
     let indexEncrypted = msgText.indexOf("-----BEGIN PGP MESSAGE-----");
     let indexSigned = msgText.indexOf("-----BEGIN PGP SIGNED MESSAGE-----");
     if (indexEncrypted >= 0) {
       if (
         indexSigned == -1 ||
         (indexSigned >= 0 && indexEncrypted < indexSigned)
       ) {
-        trimEncrypted = true;
+        return "encrypted";
       }
     }
 
-    if (trimEncrypted) {
+    if (indexSigned >= 0) {
+      return "signed";
+    }
+
+    return "";
+  },
+
+  trimIfEncrypted(msgText) {
+    // If it's an encrypted message, we want to trim (at least) the
+    // separator line between the header and the content.
+    // However, trimming all lines should be safe.
+
+    if (Enigmail.msg.getFirstPGPMessageType(msgText) == "encrypted") {
       // \xA0 is non-breaking-space
       msgText = msgText.replace(/^[ \t\xA0]+/gm, "");
     }
     return msgText;
   },
 
   async messageParse(
     interactive,
@@ -1053,81 +1060,101 @@ Enigmail.msg = {
       return;
     }
 
     let topElement = bodyElement;
     var findStr = /* interactive ? null : */ "-----BEGIN PGP";
     var msgText = null;
     var foundIndex = -1;
 
+    let bodyElementFound = false;
+    let hasHeadOrTailNode = false;
+
     if (bodyElement.firstChild) {
       let node = bodyElement.firstChild;
       while (node) {
         if (
           node.firstChild &&
-          node.firstChild.nodeName == "LEGEND" &&
-          node.firstChild.className == "mimeAttachmentHeaderName"
-        ) {
-          // we reached the area where inline attachments are displayed
-          // --> don't try to decrypt displayed inline attachments
-          break;
-        }
-        if (
-          node.firstChild &&
           node.firstChild.nodeName.toUpperCase() == "LEGEND" &&
           node.firstChild.className == "mimeAttachmentHeaderName"
         ) {
           // we reached the area where inline attachments are displayed
           // --> don't try to decrypt displayed inline attachments
           break;
         }
         if (node.nodeName === "DIV") {
+          if (bodyElementFound) {
+            hasHeadOrTailNode = true;
+            break;
+          }
+
           foundIndex = node.textContent.indexOf(findStr);
 
+          if (foundIndex < 0) {
+            hasHeadOrTailNode = true;
+            node = node.nextSibling;
+            continue;
+          }
+
           if (foundIndex >= 0) {
             if (
               node.textContent.indexOf(findStr + " LICENSE AUTHORIZATION") ==
               foundIndex
             ) {
               foundIndex = -1;
+              node = node.nextSibling;
+              continue;
             }
           }
 
           if (foundIndex === 0) {
             bodyElement = node;
-            break;
-          }
-          if (
+            bodyElementFound = true;
+          } else if (
             foundIndex > 0 &&
             node.textContent.substr(foundIndex - 1, 1).search(/[\r\n]/) === 0
           ) {
             bodyElement = node;
-            break;
+            bodyElementFound = true;
           }
         }
         node = node.nextSibling;
       }
     }
 
     if (foundIndex >= 0 && !this.hasInlineQuote(topElement)) {
+      let beginIndex = {};
+      let endIndex = {};
+      let indentStr = {};
+
       if (
         Enigmail.msg.savedHeaders["content-type"].search(/^text\/html/i) === 0
       ) {
         let p = Cc["@mozilla.org/parserutils;1"].createInstance(
           Ci.nsIParserUtils
         );
         const de = Ci.nsIDocumentEncoder;
         msgText = p.convertToPlainText(
           topElement.innerHTML,
           de.OutputRaw | de.OutputBodyOnly,
           0
         );
       } else {
         msgText = bodyElement.textContent;
       }
+
+      if (!isAuto) {
+        let blockType = EnigmailArmor.locateArmoredBlock(msgText, 0, "", beginIndex, endIndex, indentStr);
+        if (!blockType) {
+          msgText = "";
+        } else {
+          msgText = msgText.substring(beginIndex.value, endIndex.value+1);
+        }
+      }
+
       msgText = this.trimIfEncrypted(msgText);
     }
 
     if (!msgText) {
       // No PGP content
 
       // but this might be caused by the HACK for MS-EXCHANGE-Server Problem
       // - so return only if:
@@ -1194,17 +1221,17 @@ Enigmail.msg = {
 
     var charset = msgWindow ? msgWindow.mailCharacterSet : "";
     if (charset != "UTF-8") {
       // Encode ciphertext to charset from unicode
       msgText = EnigmailData.convertFromUnicode(msgText, charset);
     }
 
     if (isAuto) {
-      let ht = this.hasHeadOrTailBesidesInlinePGP(msgText);
+      let ht = hasHeadOrTailNode || this.hasHeadOrTailBesidesInlinePGP(msgText);
       if (ht) {
         let infoId;
         let buttonId;
         if (ht & EnigmailConstants.UNCERTAIN_SIGNATURE) {
           infoId = "openpgp-partially-signed";
           buttonId = "openpgp-partial-verify-button";
         } else {
           infoId = "openpgp-partially-encrypted";
@@ -1458,16 +1485,29 @@ Enigmail.msg = {
       if (interactive && errorMsg) {
         EnigmailDialog.alert(window, errorMsg);
       }
       return;
     }
 
     var displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
     if (!msgUriSpec || displayedUriSpec == msgUriSpec) {
+      if (exitCode && !statusFlags) {
+        // Failure, but we don't know why it failed.
+        // Peek inside msgText, and check what kind of content it is,
+        // so we can show a minimal error.
+
+        let msgType = Enigmail.msg.getFirstPGPMessageType(msgText);
+        if (msgType == "encrypted") {
+          statusFlags = EnigmailConstants.DECRYPTION_FAILED;
+        } else if (msgType == "signed") {
+          statusFlags = EnigmailConstants.BAD_SIGNATURE;
+        }
+      }
+
       Enigmail.hdrView.updateHdrIcons(
         exitCode,
         statusFlags,
         extStatusFlags,
         keyIdObj.value,
         userIdObj.value,
         sigDetailsObj.value,
         errorMsg,
@@ -1547,24 +1587,18 @@ Enigmail.msg = {
           isAuto,
           pbMessageIndex
         );
         return;
       }
     }
 
     if (!plainText) {
-      if (
-        interactive &&
-        Enigmail.msg.securityInfo &&
-        Enigmail.msg.securityInfo.statusInfo
-      ) {
-        EnigmailDialog.info(window, Enigmail.msg.securityInfo.statusInfo);
-      }
-      return;
+      // Show the subset that we cannot process, together with status.
+      plainText = msgText;
     }
 
     if (retry >= 2) {
       plainText = EnigmailData.convertFromUnicode(
         EnigmailData.convertToUnicode(plainText, "UTF-8"),
         charset
       );
     }
@@ -1662,42 +1696,62 @@ Enigmail.msg = {
     );
 
     var node;
     var bodyElement = Enigmail.msg.getBodyElement(pbMessageIndex);
 
     if (bodyElement.firstChild) {
       node = bodyElement.firstChild;
 
+      let divFound = false;
+
       while (node) {
         if (node.nodeName == "DIV") {
-          // for safety reasons, we replace the complete visible message with
-          // the decrypted or signed part (bug 983)
-          node.innerHTML = EnigmailFuncs.formatPlaintextMsg(
-            EnigmailData.convertToUnicode(messageContent, charset)
-          );
-          Enigmail.msg.movePEPsubject();
-          return;
+          if (divFound) {
+            node.innerHTML = "";
+          } else {
+            // for safety reasons, we replace the complete visible message with
+            // the decrypted or signed part (bug 983)
+            divFound = true;
+            node.innerHTML = EnigmailFuncs.formatPlaintextMsg(
+              EnigmailData.convertToUnicode(messageContent, charset)
+            );
+            Enigmail.msg.movePEPsubject();
+          }
         }
         node = node.nextSibling;
       }
 
+      if (divFound) {
+        return;
+      }
+
+      let preFound = false;
+
       // if no <DIV> node is found, try with <PRE> (bug 24762)
       node = bodyElement.firstChild;
       while (node) {
         if (node.nodeName == "PRE") {
-          node.innerHTML = EnigmailFuncs.formatPlaintextMsg(
-            EnigmailData.convertToUnicode(messageContent, charset)
-          );
-          Enigmail.msg.movePEPsubject();
-          return;
+          if (preFound) {
+            node.innerHTML = "";
+          } else {
+            preFound = true;
+            node.innerHTML = EnigmailFuncs.formatPlaintextMsg(
+              EnigmailData.convertToUnicode(messageContent, charset)
+            );
+            Enigmail.msg.movePEPsubject();
+          }
         }
         node = node.nextSibling;
       }
 
+      if (preFound) {
+        return;
+      }
+
       // HACK for MS-EXCHANGE-Server Problem:
       // - remove empty text/plain part
       //   and set message content as inner text
       // - missing:
       //   - signal in statusFlags so that we warn in Enigmail.hdrView.updateHdrIcons()
       if (this.buggyExchangeEmailContent) {
         if (this.displayBuggyExchangeMail()) {
           return;
--- a/mail/test/browser/openpgp/browser_viewMessage.js
+++ b/mail/test/browser/openpgp/browser_viewMessage.js
@@ -264,16 +264,163 @@ add_task(async function testOpenSignedBy
   );
   Assert.ok(
     OpenPGPTestUtils.hasEncryptedIconState(mc.window.document, "ok"),
     "encrypted icon is displayed"
   );
   close_window(mc);
 });
 
+let partialInlineTests = [
+  {
+    filename: "partial-encrypt-for-carol-plaintext.eml",
+    expectDecryption: true,
+    expectVerification: false,
+    expectSuccess: false,
+  },
+  {
+    filename: "partial-encrypt-for-carol-html.eml",
+    expectDecryption: true,
+    expectVerification: false,
+    expectSuccess: false,
+  },
+  {
+    filename: "partial-encrypt-for-alice-plaintext.eml",
+    expectDecryption: true,
+    expectVerification: false,
+    expectSuccess: true,
+  },
+  {
+    filename: "partial-encrypt-for-alice-html.eml",
+    expectDecryption: true,
+    expectVerification: false,
+    expectSuccess: true,
+  },
+  {
+    filename: "partial-signed-from-carol-plaintext.eml",
+    expectDecryption: false,
+    expectVerification: true,
+    expectSuccess: false,
+  },
+  {
+    filename: "partial-signed-from-carol-html.eml",
+    expectDecryption: false,
+    expectVerification: true,
+    expectSuccess: false,
+  },
+  {
+    filename: "partial-signed-from-bob-plaintext.eml",
+    expectDecryption: false,
+    expectVerification: true,
+    expectSuccess: true,
+  },
+  {
+    filename: "partial-signed-from-bob-html.eml",
+    expectDecryption: false,
+    expectVerification: true,
+    expectSuccess: true,
+  },
+];
+
+/**
+ * Test the notification/decryption/verification behavior for partially
+ * encrypted/signed inline PGP messages.
+ */
+add_task(async function testPartialInlinePGPDecrypt() {
+  for (let test of partialInlineTests) {
+    if (!test.filename) {
+      continue;
+    }
+
+    info(`Testing partial inline; filename=${test.filename}`);
+
+    // Setup the message.
+    let mc = await open_message_from_file(
+      new FileUtils.File(getTestFilePath("data/eml/" + test.filename))
+    );
+
+    let notificationBox = "mail-notification-top";
+    let notificationValue = "decryptInlinePG";
+
+    // Ensure the "partially encrypted notification" is visible.
+    wait_for_notification_to_show(mc, notificationBox, notificationValue);
+
+    let body = getMsgBodyTxt(mc);
+
+    Assert.ok(
+      body.includes("BEGIN PGP"),
+      "unprocessed PGP message should still be shown"
+    );
+
+    Assert.ok(body.includes("prefix"), "prefix should still be shown");
+    Assert.ok(body.includes("suffix"), "suffix should still be shown");
+
+    // Click on the button to process the message subset.
+    let processButton = get_notification_button(
+      mc,
+      notificationBox,
+      notificationValue,
+      {
+        popup: null,
+      }
+    );
+    EventUtils.synthesizeMouseAtCenter(processButton, {}, mc.window);
+
+    // Assert that the message was processed and the partial content reminder
+    // notification is visible.
+    wait_for_notification_to_show(
+      mc,
+      notificationBox,
+      "decryptInlinePGReminder"
+    );
+
+    // Get updated body text after processing the PGP subset.
+    body = getMsgBodyTxt(mc);
+
+    Assert.ok(!body.includes("prefix"), "prefix should not be shown");
+    Assert.ok(!body.includes("suffix"), "suffix should not be shown");
+
+    if (test.expectDecryption) {
+      let containsSecret = body.includes(
+        "Insert a coin to play your personal lucky melody."
+      );
+      if (test.expectSuccess) {
+        Assert.ok(containsSecret, "secret decrypted content should be shown");
+        Assert.ok(
+          OpenPGPTestUtils.hasEncryptedIconState(mc.window.document, "ok"),
+          "decryption success icon is shown"
+        );
+      } else {
+        Assert.ok(
+          !containsSecret,
+          "secret decrypted content should not be shown"
+        );
+        Assert.ok(
+          OpenPGPTestUtils.hasEncryptedIconState(mc.window.document, "notok"),
+          "decryption failure icon is shown"
+        );
+      }
+    } else if (test.expectVerification) {
+      if (test.expectSuccess) {
+        Assert.ok(
+          OpenPGPTestUtils.hasSignedIconState(mc.window.document, "verified"),
+          "ok verification icon is shown"
+        );
+      } else {
+        Assert.ok(
+          OpenPGPTestUtils.hasSignedIconState(mc.window.document, "unknown"),
+          "unknown verification icon is shown"
+        );
+      }
+    }
+
+    close_window(mc);
+  }
+});
+
 /**
  * Test that the message is properly reloaded and the message security icon is
  * updated if the user changes the signature acceptance level.
  */
 add_task(async function testUpdateMessageSignature() {
   // Setup the message.
   let mc = await open_message_from_file(
     new FileUtils.File(
@@ -348,56 +495,18 @@ add_task(async function testUpdateMessag
   // Verify the new acceptance level is correct.
   Assert.ok(
     OpenPGPTestUtils.hasSignedIconState(mc.window.document, "unverified"),
     "signed unverified icon should be displayed"
   );
   close_window(mc);
 });
 
-/**
- * Test the notification and decryption behavior for partially encrypted inline
- * PGP messages.
- */
-add_task(async function testPartialInlinePGPDecrypt() {
-  // Setup the message.
-  let mc = await open_message_from_file(
-    new FileUtils.File(
-      getTestFilePath("data/eml/alice-partially-encrypted.eml")
-    )
-  );
-
-  let notificationBox = "mail-notification-top";
-  let notificationValue = "decryptInlinePG";
-
-  // Ensure the "partially encrypted notification" is visible.
-  wait_for_notification_to_show(mc, notificationBox, notificationValue);
-
-  // Click on the "decrypt" button.
-  let decryptButton = get_notification_button(
-    mc,
-    notificationBox,
-    notificationValue,
-    {
-      popup: null,
-    }
-  );
-  EventUtils.synthesizeMouseAtCenter(decryptButton, {}, mc.window);
-
-  // Assert that the message was decrypted and the partial decryption reminder
-  // notification is visible.
-  wait_for_notification_to_show(mc, notificationBox, "decryptInlinePGReminder");
-
-  Assert.ok(
-    OpenPGPTestUtils.hasEncryptedIconState(mc.window.document, "ok"),
-    "encrypted icon is displayed"
-  );
-
-  close_window(mc);
-});
+// After test testUpdateMessageSignature acceptance of Bob's key
+// has changed from verified to unverified.
 
 /**
  * Test that a signed (only) inline PGP message with UTF-8 characters
  * can be correctly verified.
  */
 add_task(async function testOpenSignedInlineWithUTF8() {
   let mc = await open_message_from_file(
     new FileUtils.File(getTestFilePath("data/eml/alice-utf.eml"))
deleted file mode 100644
--- a/mail/test/browser/openpgp/data/eml/alice-partially-encrypted.eml
+++ /dev/null
@@ -1,17 +0,0 @@
-From: "Alice Lovelace" <alice@openpgp.example>
-To: "Alice Lovelace" <alice@openpgp.example>
-Subject: partially encrypted test message
-Date: Wed, 29 Oct 2020 02:34:56 +0000
-Content-Type: text/plain
-MIME-Version: 1.0
-
------BEGIN PGP MESSAGE-----
-
-hF4DR2b2udXyHrYSAQdACSB+uDWodBJ2WRuPm53gxq/RUAc9TSEa1pbow+HTWU8w
-5SomxZAC/JN0vnLqgLWL7JKgmQyYD9d7HI76iTThvJf2cLZXp1+HRyHN2c9gCHjE
-0lIB7FhFzhbBPoT+4Nhla6ISM/KNTkbkebJ4VtZL05/hFn98qKJq61hn9iBvLQ5/
-URrmx+0iVgA1jUTUDuZSt5PRFHYFJqGoOvdHD2mccmIhawet
-=lIZv
------END PGP MESSAGE-----
-
-Additional unexpected text
--- a/mail/test/browser/openpgp/data/eml/bob-enc-html-nbsp.eml
+++ b/mail/test/browser/openpgp/data/eml/bob-enc-html-nbsp.eml
@@ -12,27 +12,27 @@ Content-Transfer-Encoding: quoted-printa
 
 <html>
 <head>
 <style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left:=
  #800000 2px solid; } --></style>
 </head>
 <body>
 <font face=3D"Arial" size=3D"2"><span style=3D"font-size:10pt;">
-<div>-----BEGIN PGP MESSAGE-----</div>
-<div>&nbsp;</div>
+<div>-----BEGIN PGP MESSAGE-----</div><br>
+<div>&nbsp;</div><br>
 <div>hE4DR2b2udXyHrYSAQdAINgYcnZM2bAYVKuB30JR5bPNGYtFFj5EEZuHzU7B1TAg</=
-div>
+div><br>
 <div>Q0qb&#43;biPpakzFZH5xXDLJVrZFo4H76bR0ds7UROgqjDSVAFVyLyVzbXQGBf8krPa</=
-div>
+div><br>
 <div>WuIrCJRc&#43;/GBk0CHwc3cV47F8kdbeH/7uHsTbanaz3yn5gtVXBhoR5iOanSaHfCE</=
-div>
+div><br>
 <div>vmaIc6oiurKdS9PuTnqbD91uW8PKdw=3D=3D</=
-div>
-<div>=3DVp7p</div>
-<div>-----END PGP MESSAGE-----</div>
+div><br>
+<div>=3DVp7p</div><br>
+<div>-----END PGP MESSAGE-----</div><br>
 <div>&nbsp;</div>
 <div>&nbsp;</div>
 </span></font>
 </body>
 </html>
 
 --_004_33f9d332df5c463d984f9ef386761a91VSMBX02_--
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-encrypt-for-alice-html.eml
@@ -0,0 +1,31 @@
+From: "Bob" <bob@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Encrypted for Alice, with extra text in multipart HTML
+Date: Wed, 14 Apr 2021 01:01:01 +0000
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494"
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+prefix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+-----BEGIN PGP MESSAGE-----
+
+hE4DR2b2udXyHrYSAQdAq+9AhQzI4XpD9WtuB7f3OZHNFvdHza5WND3yLgxX8kwg
+eXs+jZGr3TNUpR+XRxCf9+7Er2JyJk7fvL4suUHpHEzSbQG57r4TxneCcV9pukK3
+wzSqNt2o/q/eVO6WwOs3Lo5+31gs9+z6lrVhVjO2cynPdjlNLCQlwRudsQfpNgrF
+4pO7n0tCrX0qWaKYgdQuJwIt1HS2nLYd+ryb9eLWO/Xhy3quo8YpD0yueSHjexI=
+=rSoz
+-----END PGP MESSAGE-----
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+suffix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494--
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-encrypt-for-alice-plaintext.eml
@@ -0,0 +1,19 @@
+From: "Bob" <bob@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Encrypted for Alice, with extra plaintext
+Date: Wed, 14 Apr 2021 01:01:02 +0000
+MIME-Version: 1.0
+Content-Type: text/plain
+
+prefix
+
+-----BEGIN PGP MESSAGE-----
+
+hE4DR2b2udXyHrYSAQdAq+9AhQzI4XpD9WtuB7f3OZHNFvdHza5WND3yLgxX8kwg
+eXs+jZGr3TNUpR+XRxCf9+7Er2JyJk7fvL4suUHpHEzSbQG57r4TxneCcV9pukK3
+wzSqNt2o/q/eVO6WwOs3Lo5+31gs9+z6lrVhVjO2cynPdjlNLCQlwRudsQfpNgrF
+4pO7n0tCrX0qWaKYgdQuJwIt1HS2nLYd+ryb9eLWO/Xhy3quo8YpD0yueSHjexI=
+=rSoz
+-----END PGP MESSAGE-----
+
+suffix
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-encrypt-for-carol-html.eml
@@ -0,0 +1,41 @@
+From: "Bob" <bob@openpgp.example>
+To: "Carol" <carol@openpgp.example>
+Subject: Inline Encrypted for Caron, with extra text in multipart HTML
+Date: Wed, 14 Apr 2021 01:01:03 +0000
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494"
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+prefix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+-----BEGIN PGP MESSAGE-----
+
+hQIMA7L9So5P9bk9ARAA01Dr6NF4RrED8YADJx3WOOhIgUd55axpniQBPr66Xp6l
+mOCmPJnpSTA6DJzu28AyilrOedVx4rBfY9Bs4WS6d9joFo+zj+aoo9p8nBt2tu/8
+Ox8DbwWgVoQ4Po72LfZdH9FsPzfi4I2ytp/tjfHqjgl9Aakkm3vj09OM15aEfYxd
+oOO0DFk4vyuWojE6u1Y1bdg20hqPvmciyRFfgZC/51swcwFIDm34R20ASRzrwu1h
+kRUHEiGuz3JXPQnzADmK9OcLso9OxGX80WDe136BJG/wgFKqxCwmv0ykplOTJcm3
+VFWAJzguT27JGvJ+2/93IA2uyz1b7Rr4Ly6s6k9zhAPsDudyI2pOiIVpWWSGwiPW
+kX78JB5jvgjNs3Wh1dHp/TyKqivQz1qbgH2M78sKUdmbCHiD3Ak5b3F8h3JhrU7X
+3zwamZMmove1bkScL4TGXBMMZhwUe6BPg3fq42UHLtXccHlfm+XRWgHbT0su4ezZ
+2n3+5YDYozyfmytxZ7jeL9OSbQTNbNZmA+GTf10RX8ww9wwiffLNe8LGdwNaL96i
+F2lsC1Hfczw16fThBIEx7UF9LmJzzPNN7aOf+fbOLvkQFSPiGZg9tmXGzzRjDboT
+VKhpbV3GNFsCoOcry3Q7xzDgKiWXkdqCTqP9AGJfksQ0mdLQB94tfBYouX+g7PLS
+bQEyf6is0CReegpCSbSUZXURLPo381LrYdpV/PA0L+MDZse3xEKpc69zmE+H4oAT
+t/zF/Bh0ezxbN0AAHyldj82I7CP+Vtat0qSnUGsbd7G5nswwswxHXTA+FfDo+qBl
+U70ypxk/ZqPWcAAEkBo=
+=zsMo
+-----END PGP MESSAGE-----
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+suffix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494--
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-encrypt-for-carol-plaintext.eml
@@ -0,0 +1,29 @@
+From: "Bob" <bob@openpgp.example>
+To: "Carol" <carol@openpgp.example>
+Subject: Inline Encrypted for Carol, with extra plaintext
+Date: Wed, 14 Apr 2021 01:01:04 +0000
+MIME-Version: 1.0
+Content-Type: text/plain
+
+prefix
+
+-----BEGIN PGP MESSAGE-----
+
+hQIMA7L9So5P9bk9ARAA01Dr6NF4RrED8YADJx3WOOhIgUd55axpniQBPr66Xp6l
+mOCmPJnpSTA6DJzu28AyilrOedVx4rBfY9Bs4WS6d9joFo+zj+aoo9p8nBt2tu/8
+Ox8DbwWgVoQ4Po72LfZdH9FsPzfi4I2ytp/tjfHqjgl9Aakkm3vj09OM15aEfYxd
+oOO0DFk4vyuWojE6u1Y1bdg20hqPvmciyRFfgZC/51swcwFIDm34R20ASRzrwu1h
+kRUHEiGuz3JXPQnzADmK9OcLso9OxGX80WDe136BJG/wgFKqxCwmv0ykplOTJcm3
+VFWAJzguT27JGvJ+2/93IA2uyz1b7Rr4Ly6s6k9zhAPsDudyI2pOiIVpWWSGwiPW
+kX78JB5jvgjNs3Wh1dHp/TyKqivQz1qbgH2M78sKUdmbCHiD3Ak5b3F8h3JhrU7X
+3zwamZMmove1bkScL4TGXBMMZhwUe6BPg3fq42UHLtXccHlfm+XRWgHbT0su4ezZ
+2n3+5YDYozyfmytxZ7jeL9OSbQTNbNZmA+GTf10RX8ww9wwiffLNe8LGdwNaL96i
+F2lsC1Hfczw16fThBIEx7UF9LmJzzPNN7aOf+fbOLvkQFSPiGZg9tmXGzzRjDboT
+VKhpbV3GNFsCoOcry3Q7xzDgKiWXkdqCTqP9AGJfksQ0mdLQB94tfBYouX+g7PLS
+bQEyf6is0CReegpCSbSUZXURLPo381LrYdpV/PA0L+MDZse3xEKpc69zmE+H4oAT
+t/zF/Bh0ezxbN0AAHyldj82I7CP+Vtat0qSnUGsbd7G5nswwswxHXTA+FfDo+qBl
+U70ypxk/ZqPWcAAEkBo=
+=zsMo
+-----END PGP MESSAGE-----
+
+suffix
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-signed-from-bob-html.eml
@@ -0,0 +1,41 @@
+From: "Bob" <bob@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Signed by Bob, with extra text in multipart HTML
+Date: Wed, 14 Apr 2021 01:01:05 +0000
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494"
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+prefix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA512
+
+Insert a coin to play your personal lucky melody.
+-----BEGIN PGP SIGNATURE-----
+
+iQHIBAEBCgAyFiEE0aZuGiOxgsmYD3iM+/zIKgFeczAFAmB4Yg8UHGJvYkBvcGVu
+cGdwLmV4YW1wbGUACgkQ+/zIKgFeczC6twv/fYtlE8oNqhP5OzR48/rCEmJQ/U8Z
+NIp2Mvg3fpIMY1m2z4nwufCj4xNHM4okyqXnVouWBSLkRL3oPlkXj+syY1lV3Bv2
+Gbl5JMmpMbdSjKAEg7VaYg9C6ELbb25EhBLok1JYMXn5o+wfmm+UN+EU8IbXck5Q
+roFNueM6wFv6nvM64jQIkqoyJ2OvNYg1lTJXp7EXEnwRRIW9IDd1XInVrx4jou3Q
+Ax4/VbyJQiE37JC6NAJ9hBh/noO36IGAXvBeyN/TVOBySBFC1XoZdhjVoA7eWbZY
+m1Pxtar5P1Pb6Nac2c4b8Z1FHZFd81zYbJZkJYG6oApbOBFsn+Lf1+LkVKAiewos
+A91QVSP9pqiJmWFZ17tCxRM5YPIPRT35nV3TN3snHGsNvvAJ9mc3YOO7aM0aitx7
+1p3IqdFUz3G8qUlMDthV4WDBj7N1LnRyKCRU6W58hoDXLEjYXMBYSP8+UHqS953M
+ILOfsOglDqxjdwrNf2TK9y+zpyXX16yI1eHB
+=1Be6
+-----END PGP SIGNATURE-----
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+suffix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494--
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-signed-from-bob-plaintext.eml
@@ -0,0 +1,29 @@
+From: "Bob" <bob@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Signed by Bob, with extra plaintext
+Date: Wed, 14 Apr 2021 01:01:06 +0000
+MIME-Version: 1.0
+Content-Type: text/plain
+
+prefix
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA512
+
+Insert a coin to play your personal lucky melody.
+-----BEGIN PGP SIGNATURE-----
+
+iQHIBAEBCgAyFiEE0aZuGiOxgsmYD3iM+/zIKgFeczAFAmB4Yg8UHGJvYkBvcGVu
+cGdwLmV4YW1wbGUACgkQ+/zIKgFeczC6twv/fYtlE8oNqhP5OzR48/rCEmJQ/U8Z
+NIp2Mvg3fpIMY1m2z4nwufCj4xNHM4okyqXnVouWBSLkRL3oPlkXj+syY1lV3Bv2
+Gbl5JMmpMbdSjKAEg7VaYg9C6ELbb25EhBLok1JYMXn5o+wfmm+UN+EU8IbXck5Q
+roFNueM6wFv6nvM64jQIkqoyJ2OvNYg1lTJXp7EXEnwRRIW9IDd1XInVrx4jou3Q
+Ax4/VbyJQiE37JC6NAJ9hBh/noO36IGAXvBeyN/TVOBySBFC1XoZdhjVoA7eWbZY
+m1Pxtar5P1Pb6Nac2c4b8Z1FHZFd81zYbJZkJYG6oApbOBFsn+Lf1+LkVKAiewos
+A91QVSP9pqiJmWFZ17tCxRM5YPIPRT35nV3TN3snHGsNvvAJ9mc3YOO7aM0aitx7
+1p3IqdFUz3G8qUlMDthV4WDBj7N1LnRyKCRU6W58hoDXLEjYXMBYSP8+UHqS953M
+ILOfsOglDqxjdwrNf2TK9y+zpyXX16yI1eHB
+=1Be6
+-----END PGP SIGNATURE-----
+
+suffix
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-signed-from-carol-html.eml
@@ -0,0 +1,44 @@
+From: "Carol" <carol@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Signed by Carol, with extra text in multipart HTML
+Date: Wed, 14 Apr 2021 01:01:07 +0000
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494"
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+prefix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA512
+
+Insert a coin to play your personal lucky melody.
+-----BEGIN PGP SIGNATURE-----
+
+iQJGBAEBCgAwFiEEuPL29L060/gtxEaDMJn/EjiFK58FAmB4YicSHGNhcm9sQGV4
+YW1wbGUuY29tAAoJEDCZ/xI4hSuflLwP/1wmmla7bXjzbyIGFnSiC+xMT0vcos+s
+uv4jdcC1cPxpCj51EZEQGLzmKUMJaD1ruK7AnimhA55tb22NetDW0OHA917VeuoI
++cY1Hm8YqJI9LF9KbnzfbTtqeAcFKPjQe7OBFIvru3Z38Ng2JTnRXkM0xolZjpOz
+m14f241+LT62xQwKW3rlG3FLW1yWdVQ5vi8jptbZrhC4J7B2Mzhgt1BX0aV/IK69
+3heQKQIttjslwy2ka8IusfSgPiioSBSULcmlN+FV9kKPNCVAoFvjpGRR9hJfZ92E
+6ESuYdphCH+M8FTSKBrKrX6hvl21SpHS0qExr1Xh3MYJvE+8jX0egjuf32Rf/io8
+LYJ/aiBpkDbikCY8rQUD7+HmHGvCiN8tGakeIbjkS3V0vMA3WsZJPtUt/dmVaVHw
+TPuXUMnhbQpuqXI6K175WnzHFaOXoV67AVhLqM6CZTdhJLUz1NNVvaSJ1P8nxAz+
+wEEh33138gtuWfsT4xfaitbQ2KqmkVLvu1CJ7k1+GiEOxWNiPgSHo5Z/Iimi4VB3
+Bwxk77iZOOinqmlhd680s9UK/AnZxJ1I+5NYKx8yuATWYmYoorDKZLvJxZH5DPz5
+XTu+v79iGvIXcSLyOsvcMDLLnA6tj4pBRB+MgxweiVjHfrdvG7ohDwXgklI39I62
+eO84IXMU+peK
+=Kjsi
+-----END PGP SIGNATURE-----
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494
+Content-Type: text/html; charset=utf-8
+
+suffix
+
+--32989E6E4C7AEB7775BAD49432989E6E4C7AEB7775BAD494--
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/openpgp/data/eml/partial-signed-from-carol-plaintext.eml
@@ -0,0 +1,32 @@
+From: "Carol" <carol@openpgp.example>
+To: "Alice Lovelace" <alice@openpgp.example>
+Subject: Inline Signed by Carol, with extra plaintext
+Date: Wed, 14 Apr 2021 01:01:08 +0000
+MIME-Version: 1.0
+Content-Type: text/plain
+
+prefix
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA512
+
+Insert a coin to play your personal lucky melody.
+-----BEGIN PGP SIGNATURE-----
+
+iQJGBAEBCgAwFiEEuPL29L060/gtxEaDMJn/EjiFK58FAmB4YicSHGNhcm9sQGV4
+YW1wbGUuY29tAAoJEDCZ/xI4hSuflLwP/1wmmla7bXjzbyIGFnSiC+xMT0vcos+s
+uv4jdcC1cPxpCj51EZEQGLzmKUMJaD1ruK7AnimhA55tb22NetDW0OHA917VeuoI
++cY1Hm8YqJI9LF9KbnzfbTtqeAcFKPjQe7OBFIvru3Z38Ng2JTnRXkM0xolZjpOz
+m14f241+LT62xQwKW3rlG3FLW1yWdVQ5vi8jptbZrhC4J7B2Mzhgt1BX0aV/IK69
+3heQKQIttjslwy2ka8IusfSgPiioSBSULcmlN+FV9kKPNCVAoFvjpGRR9hJfZ92E
+6ESuYdphCH+M8FTSKBrKrX6hvl21SpHS0qExr1Xh3MYJvE+8jX0egjuf32Rf/io8
+LYJ/aiBpkDbikCY8rQUD7+HmHGvCiN8tGakeIbjkS3V0vMA3WsZJPtUt/dmVaVHw
+TPuXUMnhbQpuqXI6K175WnzHFaOXoV67AVhLqM6CZTdhJLUz1NNVvaSJ1P8nxAz+
+wEEh33138gtuWfsT4xfaitbQ2KqmkVLvu1CJ7k1+GiEOxWNiPgSHo5Z/Iimi4VB3
+Bwxk77iZOOinqmlhd680s9UK/AnZxJ1I+5NYKx8yuATWYmYoorDKZLvJxZH5DPz5
+XTu+v79iGvIXcSLyOsvcMDLLnA6tj4pBRB+MgxweiVjHfrdvG7ohDwXgklI39I62
+eO84IXMU+peK
+=Kjsi
+-----END PGP SIGNATURE-----
+
+suffix