Bug 1643250 - Update composer OpenPGP settings after switching the sender identity. r=mkmelin,PatrickBrunschwig a=wsmwk
authorKai Engert <kaie@kuix.de>
Sat, 06 Jun 2020 01:12:28 +0200
changeset 39397 2f809d3fe53bb2fc7eed975af9560df429f8e72b
parent 39396 0e39b8506d47c922ce6dc9ef7cbfdb7e831d5722
child 39398 a894f36fc41ae6e5c067ed699ebf71b612e2d46e
push id402
push userclokep@gmail.com
push dateMon, 29 Jun 2020 20:48:04 +0000
reviewersmkmelin, PatrickBrunschwig, wsmwk
bugs1643250
Bug 1643250 - Update composer OpenPGP settings after switching the sender identity. r=mkmelin,PatrickBrunschwig a=wsmwk Differential Revision: https://phabricator.services.mozilla.com/D78586
mail/components/compose/content/MsgComposeCommands.js
mail/extensions/openpgp/content/modules/encryption.jsm
mail/extensions/openpgp/content/strings/enigmail.properties
mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -1762,17 +1762,23 @@ function setSecuritySettings(menu_id) {
     if (!isSmimeSigningConfigured()) {
       disableSig = true;
     }
     if (!isSmimeEncryptionConfigured()) {
       disableEnc = true;
     }
   }
 
-  enc0Item.disabled = disableEnc;
+  // The radio button to disable encryption is always active.
+  // This is necessary, even if the current identity doesn't have
+  // e2ee configured. If the user switches the sender identity of an
+  // email, we might keep encryption enabled, to not surprise the user.
+  // This means, we must always allow the user to disable encryption.
+  enc0Item.disabled = false;
+
   //enc1Item.disabled = disableEnc;
   enc2Item.disabled = disableEnc;
 
   sigItem.disabled = disableSig;
 
   if (MailConstants.MOZ_OPENPGP) {
     let pgpItem = document.getElementById("encTech_OpenPGP" + menu_id);
     let smimeItem = document.getElementById("encTech_SMIME" + menu_id);
@@ -3723,16 +3729,155 @@ function WizCallback(state) {
   if (state) {
     ComposeStartup(null);
   } else {
     // The account wizard is still closing so we can't close just yet
     setTimeout(MsgComposeCloseWindow, 0);
   }
 }
 
+function adjustSignEncryptAfterIdentityChanged(prevId, newId) {
+  let configuredSMIME =
+    isSmimeSigningConfigured() || isSmimeEncryptionConfigured();
+
+  let configuredOpenPGP = false;
+  if (MailConstants.MOZ_OPENPGP && BondOpenPGP.allDependenciesLoaded()) {
+    configuredOpenPGP = isPgpConfigured();
+  }
+
+  if (!prevId) {
+    gSelectedTechnologyIsPGP = false;
+
+    if (configuredOpenPGP) {
+      if (!configuredSMIME) {
+        gSelectedTechnologyIsPGP = true;
+      } else {
+        // both are configured
+        let techPref = gCurrentIdentity.getIntAttribute("e2etechpref");
+        gSelectedTechnologyIsPGP = techPref != 1;
+
+        // TODO: if !techPref, we might set another flag, and
+        // decide dynamically which one to use, based on the
+        // availability of recipient keys etc.
+      }
+    }
+  }
+  // If the new identity has only one technology configured,
+  // which is different than the currently selected technology,
+  // then switch over to that other technology.
+
+  // However, if the new account doesn't have any technology
+  // configured, then it doesn't really matter, so let's keep what's
+  // currently selected for consistency (in case the user switches
+  // the identity again).
+  else if (gSelectedTechnologyIsPGP && !configuredOpenPGP && configuredSMIME) {
+    gSelectedTechnologyIsPGP = false;
+  } else if (
+    !gSelectedTechnologyIsPGP &&
+    !configuredSMIME &&
+    configuredOpenPGP
+  ) {
+    gSelectedTechnologyIsPGP = true;
+  }
+
+  // Not yet implemented
+  gOptionalEncryption = false;
+  gOptionalEncryptionInitial = gOptionalEncryption;
+
+  if (!prevId) {
+    if (configuredOpenPGP || configuredSMIME) {
+      gSendEncrypted = gCurrentIdentity.getIntAttribute("encryptionpolicy") > 0;
+      gSendSigned = gCurrentIdentity.getBoolAttribute("sign_mail");
+    }
+
+    gSendEncryptedInitial = gSendEncrypted;
+    gSendSignedInitial = gSendSigned;
+    gAttachMyPublicPGPKeyInitial = gAttachMyPublicPGPKey;
+
+    // automatic changes after this line
+    if (gSendSigned && gSelectedTechnologyIsPGP) {
+      gAttachMyPublicPGPKey = true;
+    }
+  } else {
+    // When switching the Sender identity, use the more secure setting
+    // for encryption and signing, respectively.
+
+    // For encryption, the more secure setting is "enabled".
+
+    // If the user has had encryption enabled for a message initially,
+    // then the user might have seen status in the user interface,
+    // and might "know and assume" that encryption is enabled.
+    // We should not surprise the user, and switching to a different
+    // identity should never automatically disable encryption, even
+    // if the new identity isn't configured for encryption. The user
+    // should be required to acknowledge that encryption will no longer
+    // be used, by deliberately disabling it.
+
+    // If encryption isn't enabled yet, but the new identity asks for
+    // encryption by default, then enable it.
+
+    if (!gSendEncrypted) {
+      let newDefaultEncrypted =
+        gCurrentIdentity.getIntAttribute("encryptionpolicy") > 0;
+
+      if (newDefaultEncrypted) {
+        gSendEncrypted = true;
+        gSendEncryptedInitial = gSendEncrypted;
+      }
+    }
+
+    // For signing, the more secure setting is "disabled" (this is from
+    // the sender's perspective - don't add a proof of identity unless
+    // the user requests it).
+
+    // Automatically disabling signing is also important from the user
+    // interface perspective. If no encryption technology is configured,
+    // then the user interface checkbox is disabled in the user
+    // interface, so keeping it enabled would have the consequence that
+    // the user is unable to disable the setting and consequently unable
+    // to send the message.
+
+    if (gSendSigned) {
+      let newDefaultSigned = gCurrentIdentity.getBoolAttribute("sign_mail");
+
+      if (!newDefaultSigned) {
+        gSendSigned = false;
+        gSendSignedInitial = gSendSigned;
+
+        if (!gUserTouchedAttachMyPubKey) {
+          gAttachMyPublicPGPKey = false;
+        }
+      }
+    }
+  }
+
+  if (gAttachMyPublicPGPKey && !configuredOpenPGP) {
+    gAttachMyPublicPGPKey = false;
+  }
+
+  // automatic changes after this line
+  if (
+    gEncryptedURIService &&
+    gEncryptedURIService.isEncrypted(gMsgCompose.originalMsgURI)
+  ) {
+    gIsRelatedToEncryptedOriginal = true;
+  }
+
+  if (gIsRelatedToEncryptedOriginal) {
+    gSendEncrypted = true;
+  }
+
+  if (gSMFields && !gSelectedTechnologyIsPGP) {
+    gSMFields.requireEncryptMessage = gSendEncrypted;
+    gSMFields.signMessage = gSendSigned;
+  }
+
+  setEncSigStatusUI();
+}
+
 function ComposeLoad() {
   let otherHeaders = Services.prefs.getCharPref(
     "mail.compose.other.header",
     ""
   );
 
   AddMessageComposeOfflineQuitObserver();
 
@@ -3802,74 +3947,17 @@ function ComposeLoad() {
   gMsgCompose.compFields.composeSecure = null;
   gSMFields = Cc[
     "@mozilla.org/messengercompose/composesecure;1"
   ].createInstance(Ci.nsIMsgComposeSecure);
   if (gSMFields) {
     gMsgCompose.compFields.composeSecure = gSMFields;
   }
 
-  let configuredSMIME =
-    isSmimeSigningConfigured() || isSmimeEncryptionConfigured();
-  let configuredOpenPGP = false;
-
-  if (MailConstants.MOZ_OPENPGP && BondOpenPGP.allDependenciesLoaded()) {
-    configuredOpenPGP = isPgpConfigured();
-  }
-
-  gSelectedTechnologyIsPGP = false;
-
-  if (configuredOpenPGP) {
-    if (!configuredSMIME) {
-      gSelectedTechnologyIsPGP = true;
-    } else {
-      // both are configured
-      let techPref = gCurrentIdentity.getIntAttribute("e2etechpref");
-      gSelectedTechnologyIsPGP = techPref != 1;
-
-      // TODO: if !techPref, we might set another flag, and
-      // decide dynamically which one to use, based on the
-      // availability of recipient keys etc.
-    }
-  }
-
-  if (configuredOpenPGP || configuredSMIME) {
-    gSendEncrypted = gCurrentIdentity.getIntAttribute("encryptionpolicy") > 0;
-    gOptionalEncryption = false;
-    gSendSigned = gCurrentIdentity.getBoolAttribute("sign_mail");
-  }
-
-  gSendSignedInitial = gSendSigned;
-  gAttachMyPublicPGPKeyInitial = gAttachMyPublicPGPKey;
-  gSendEncryptedInitial = gSendEncrypted;
-  gOptionalEncryptionInitial = gOptionalEncryption;
-
-  // automatic changes after this line
-
-  if (gSendSigned && gSelectedTechnologyIsPGP) {
-    gAttachMyPublicPGPKey = true;
-  }
-
-  if (
-    gEncryptedURIService &&
-    gEncryptedURIService.isEncrypted(gMsgCompose.originalMsgURI)
-  ) {
-    gIsRelatedToEncryptedOriginal = true;
-  }
-
-  if (gIsRelatedToEncryptedOriginal) {
-    gSendEncrypted = true;
-  }
-
-  if (gSMFields && !gSelectedTechnologyIsPGP) {
-    gSMFields.requireEncryptMessage = gSendEncrypted;
-    gSMFields.signMessage = gSendSigned;
-  }
-
-  setEncSigStatusUI();
+  adjustSignEncryptAfterIdentityChanged(null, gCurrentIdentity);
 
   ExtensionParent.apiManager.emit(
     "extension-browser-inserted",
     GetCurrentEditorElement()
   );
 
   setDefaultHeaderMinHeight();
 }
@@ -7060,16 +7148,18 @@ function LoadIdentity(startup) {
             .filter(
               x => !toCcBccAddrs.has(...msgCompFields.splitRecipients(x, true))
             )
             .join(", ");
           awAddRecipients(msgCompFields, "addr_bcc", newBcc);
         }
       }
 
+      adjustSignEncryptAfterIdentityChanged(prevIdentity, gCurrentIdentity);
+
       try {
         gMsgCompose.identity = gCurrentIdentity;
       } catch (ex) {
         dump("### Cannot change the identity: " + ex + "\n");
       }
 
       window.dispatchEvent(new CustomEvent("compose-from-changed"));
 
--- a/mail/extensions/openpgp/content/modules/encryption.jsm
+++ b/mail/extensions/openpgp/content/modules/encryption.jsm
@@ -355,16 +355,20 @@ var EnigmailEncryption = {
     );
 
     let keyList = [];
     let ret = {
       keyId: null,
       errorMsg: null,
     };
 
+    if (!fromMailAddr) {
+      return ret;
+    }
+
     let sign = !!(sendFlags & EnigmailConstants.SEND_SIGNED);
     let encrypt = !!(sendFlags & EnigmailConstants.SEND_ENCRYPTED);
 
     if (fromMailAddr.search(/^(0x)?[A-Z0-9]+$/) === 0) {
       // key ID specified
       let key = EnigmailKeyRing.getKeyById(fromMailAddr);
       keyList.push(key);
     } else {
--- a/mail/extensions/openpgp/content/strings/enigmail.properties
+++ b/mail/extensions/openpgp/content/strings/enigmail.properties
@@ -628,13 +628,13 @@ importSettings.button.abortImport=&Abort
 
 cannotUseOwnKeyBecause=Unable to send the message, because there is a problem with your personal key. %S
 cannotEncryptBecauseMissing=Unable to send this message with end-to-end encryption, because there are problems with the keys of the following recipients: %S
 
 
 
 
 fileToBigToImport=This file is too big. Please don't import a large set of keys at once.
-
-
+cannotSendSigBecauseNoOwnKey=Cannot digitally sign this message, because you haven't yet configured end-to-end encryption for <%S>
+cannotSendEncBecauseNoOwnKey=Cannot send this message encrypted, because you haven't yet configured end-to-end encryption for <%S>
 
 
 confirmPermissiveImport=Import failed. The key you are trying to import might be corrupt or use unknown attributes. Would you like to attempt to import the parts that are correct? This might result in the import of incomplete and unusable keys.
--- a/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
@@ -171,21 +171,16 @@ Enigmail.msg = {
     Enigmail.msg.composeBodyReady = false;
 
     // Listen to message sending event
     addEventListener(
       "compose-send-message",
       Enigmail.msg.sendMessageListener.bind(Enigmail.msg),
       true
     );
-    addEventListener(
-      "compose-from-changed",
-      Enigmail.msg.fromChangedListener.bind(Enigmail.msg),
-      true
-    );
 
     // Relabel SMIME button and menu item
     //var smimeButton = document.getElementById("button-security");
     //let toolbar = document.getElementById("composeToolbar2");
 
     /*
     if (smimeButton) {
       smimeButton.setAttribute("label", "S/MIME");
@@ -378,26 +373,16 @@ Enigmail.msg = {
 
   setIdentityDefaults() {
     EnigmailLog.DEBUG(
       "enigmailMsgComposeOverlay.js: Enigmail.msg.setIdentityDefaults\n"
     );
 
     this.identity = getCurrentIdentity();
 
-    if (!Enigmail.msg.isEnigmailEnabledForIdentity()) {
-      // reset status strings in menu to useful defaults
-      this.statusEncryptedStr = EnigmailLocale.getString("encryptNo");
-      this.statusSignedStr = EnigmailLocale.getString("signNo", [""]);
-      //this.statusPGPMimeStr = EnigmailLocale.getString("pgpmimeNormal");
-      //this.statusInlinePGPStr = EnigmailLocale.getString("inlinePGPNormal");
-      //this.statusSMimeStr = EnigmailLocale.getString("smimeNormal");
-      this.statusAttachOwnKey = EnigmailLocale.getString("attachOwnKeyNo");
-    }
-
     // reset default send settings, unless we have changed them already
 
     // instead of sendModeDirty, use gUserTouched*
 
     /*
     if (!this.sendModeDirty) {
       //this.mimePreferOpenPGP = this.identity.getIntAttribute("mimePreferOpenPGP");
       //this.processAccountSpecificDefaultOptions();
@@ -1213,39 +1198,16 @@ Enigmail.msg = {
     } else {
       this.editorInsertText(" ");
     }
 
     this.editorSelectAll();
     this.editorInsertText(text);
   },
 
-  goAccountManager() {
-    EnigmailLog.DEBUG(
-      "enigmailMsgComposeOverlay.js: Enigmail.msg.goAccountManager:\n"
-    );
-    EnigmailCore.getService(window);
-    let currentId = null;
-    let account = null;
-    try {
-      currentId = getCurrentIdentity();
-      account = EnigmailFuncs.getAccountForIdentity(currentId);
-    } catch (ex) {}
-    window.openDialog(
-      "chrome://openpgp/content/ui/editSingleAccount.xhtml",
-      "",
-      "dialog,modal,centerscreen",
-      {
-        identity: currentId,
-        account,
-      }
-    );
-    this.setIdentityDefaults();
-  },
-
   /**
    * Determine if Enigmail is enabled for the account
    */
 
   wasEnigmailAddOnInstalled() {
     return EnigmailPrefs.getPref("configuredVersion") !== "";
   },
 
@@ -1911,17 +1873,17 @@ Enigmail.msg = {
           }
       }
     }
 
     return true;
   },
   */
 
-  getEncryptionFlags(msgSendType) {
+  getEncryptionFlags() {
     let f = 0;
 
     console.debug(
       `in getEncryptionFlags, gSendEncrypted=${gSendEncrypted}, gSendSigned=${gSendSigned}`
     );
 
     if (gSendEncrypted) {
       f |= EnigmailConstants.SEND_ENCRYPTED;
@@ -2196,44 +2158,44 @@ Enigmail.msg = {
     EnigmailLog.DEBUG(
       "enigmailMsgComposeOverlay.js: Enigmail.msg.prepareSecurityInfo: securityInfo = " +
         newSecurityInfo +
         "\n"
     );
     return newSecurityInfo;
   },
 
-  async encryptMsg(msgSendType) {
+  async prepareSendMsg(msgSendType) {
     // msgSendType: value from nsIMsgCompDeliverMode
     EnigmailLog.DEBUG(
-      "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: msgSendType=" +
+      "enigmailMsgComposeOverlay.js: Enigmail.msg.prepareSendMsg: msgSendType=" +
         msgSendType +
         ", gSendSigned=" +
         gSendSigned +
         ", gSendEncrypted=" +
         gSendEncrypted +
         "\n"
     );
 
     const SIGN = EnigmailConstants.SEND_SIGNED;
     const ENCRYPT = EnigmailConstants.SEND_ENCRYPTED;
     const DeliverMode = Ci.nsIMsgCompDeliverMode;
 
     var ioService = Services.io;
     // EnigSend: Handle both plain and encrypted messages below
     var isOffline = ioService && ioService.offline;
 
-    let sendFlags = this.getEncryptionFlags(msgSendType);
+    let sendFlags = this.getEncryptionFlags();
 
     switch (msgSendType) {
       case DeliverMode.SaveAsDraft:
       case DeliverMode.SaveAsTemplate:
       case DeliverMode.AutoSaveAsDraft:
         EnigmailLog.DEBUG(
-          "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: detected save draft\n"
+          "enigmailMsgComposeOverlay.js: Enigmail.msg.prepareSendMsg: detected save draft\n"
         );
 
         // saving drafts is simpler and works differently than the rest of Enigmail.
         // All rules except account-settings are ignored.
         return this.saveDraftMessage();
     }
 
     this.unsetAdditionalHeader("x-enigmail-draft-status");
@@ -2251,29 +2213,40 @@ Enigmail.msg = {
       var bundle = document.getElementById("bundle_composeMsgs");
       EnigmailDialog.alert(window, bundle.getString("12511"));
       return false;
     }
 
     this.identity = getCurrentIdentity();
     let senderKeyId = this.identity.getUnicharAttribute("openpgp_key_id");
 
-    let senderKeyUsable = EnigmailEncryption.determineOwnKeyUsability(
-      sendFlags,
-      senderKeyId
-    );
-    if (senderKeyUsable.errorMsg) {
-      let fullAlert = EnigmailLocale.getString("cannotUseOwnKeyBecause", [
-        senderKeyUsable.errorMsg,
-      ]);
-
+    if ((gSendEncrypted || gSendSigned) && !senderKeyId) {
+      let msgId = gSendEncrypted
+        ? "cannotSendEncBecauseNoOwnKey"
+        : "cannotSendSigBecauseNoOwnKey";
+      let fullAlert = EnigmailLocale.getString(msgId, [this.identity.email]);
       EnigmailDialog.alert(window, fullAlert);
       return false;
     }
 
+    if (senderKeyId) {
+      let senderKeyUsable = EnigmailEncryption.determineOwnKeyUsability(
+        sendFlags,
+        senderKeyId
+      );
+      if (senderKeyUsable.errorMsg) {
+        let fullAlert = EnigmailLocale.getString("cannotUseOwnKeyBecause", [
+          senderKeyUsable.errorMsg,
+        ]);
+
+        EnigmailDialog.alert(window, fullAlert);
+        return false;
+      }
+    }
+
     if (gSendEncrypted) {
       let canEncryptDetails = await this.determineSendFlags();
       if (canEncryptDetails.errArray.length != 0) {
         let isFirst = true;
         let allProblems = "";
         for (let obj of canEncryptDetails.errArray) {
           if (isFirst) {
             isFirst = false;
@@ -2341,16 +2314,25 @@ Enigmail.msg = {
       /*
       if (!this.checkProtectHeaders(sendFlags)) {
         return false;
       }
       */
 
       // ----------------------- Rewrapping code, taken from function "encryptInline"
 
+      if (sendFlags & ENCRYPT && !usingPGPMime) {
+        throw new Error("Sending encrypted inline not supported!");
+      }
+      if (sendFlags & SIGN && !usingPGPMime && gMsgCompose.composeHTML) {
+        throw new Error(
+          "Sending signed inline only supported for plain text composition!"
+        );
+      }
+
       // Check wrapping, if sign only and inline and plaintext
       if (
         sendFlags & SIGN &&
         !(sendFlags & ENCRYPT) &&
         !usingPGPMime &&
         !gMsgCompose.composeHTML
       ) {
         var wrapresultObj = {};
@@ -2390,17 +2372,17 @@ Enigmail.msg = {
           sendFlags,
           fromAddr: rcpt.fromAddr,
           toAddr: toAddrStr,
           bccAddr: bccAddrStr,
           uiFlags,
           bucketList: document.getElementById("attachmentBucket"),
         };
 
-        if (!this.encryptInline(sendInfo)) {
+        if (!this.signInline(sendInfo)) {
           return false;
         }
       }
 
       // update the list of attachments
       Attachments2CompFields(msgCompFields);
 
       if (
@@ -2419,27 +2401,27 @@ Enigmail.msg = {
           (usingPGPMime && sendFlags & (ENCRYPT | SIGN)) ||
           (!usingPGPMime && sendFlags & ENCRYPT)
         ) {
           try {
             // make sure plaintext is not changed to 7bit
             if (typeof msgCompFields.forceMsgEncoding == "boolean") {
               msgCompFields.forceMsgEncoding = true;
               EnigmailLog.DEBUG(
-                "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: enabled forceMsgEncoding\n"
+                "enigmailMsgComposeOverlay.js: Enigmail.msg.prepareSendMsg: enabled forceMsgEncoding\n"
               );
             }
           } catch (ex) {
             console.debug(ex);
           }
         }
       }
     } catch (ex) {
       EnigmailLog.writeException(
-        "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg",
+        "enigmailMsgComposeOverlay.js: Enigmail.msg.prepareSendMsg",
         ex
       );
       return false;
     }
 
     // The encryption process for PGP/MIME messages follows "here". It's
     // called automatically from nsMsgCompose->sendMsg().
     // registration for this is done in core.jsm: startup()
@@ -2485,53 +2467,37 @@ Enigmail.msg = {
         this.displayProtectHeadersStatus();
       }
     }
 
     return true;
   },
   */
 
-  encryptInline(sendInfo) {
-    // sign/encrypt message using inline-PGP
+  signInline(sendInfo) {
+    // sign message using inline-PGP
+
+    if (sendInfo.sendFlags & ENCRYPT) {
+      throw new Error("Encryption not supported in inline messages!");
+    }
+    if (gMsgCompose.composeHTML) {
+      throw new Error(
+        "Signing inline only supported for plain text composition!"
+      );
+    }
 
     const dce = Ci.nsIDocumentEncoder;
     const SIGN = EnigmailConstants.SEND_SIGNED;
     const ENCRYPT = EnigmailConstants.SEND_ENCRYPTED;
 
     var enigmailSvc = EnigmailCore.getService(window);
     if (!enigmailSvc) {
       return false;
     }
 
-    if (gMsgCompose.composeHTML) {
-      var errMsg = EnigmailLocale.getString("hasHTML");
-      EnigmailDialog.alertCount(window, "composeHtmlAlertCount", errMsg);
-    }
-
-    try {
-      var convert = DetermineConvertibility();
-      if (convert == Ci.nsIMsgCompConvertible.No) {
-        if (
-          !EnigmailDialog.confirmDlg(
-            window,
-            EnigmailLocale.getString("strippingHTML"),
-            EnigmailLocale.getString("msgCompose.button.sendAnyway")
-          )
-        ) {
-          return false;
-        }
-      }
-    } catch (ex) {
-      EnigmailLog.writeException(
-        "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptInline",
-        ex
-      );
-    }
-
     try {
       if (this.getMailPref("mail.strictly_mime")) {
         if (
           EnigmailDialog.confirmPref(
             window,
             EnigmailLocale.getString("quotedPrintableWarn"),
             "quotedPrintableWarn"
           )
@@ -2544,51 +2510,17 @@ Enigmail.msg = {
     var sendFlowed;
     try {
       sendFlowed = this.getMailPref("mailnews.send_plaintext_flowed");
     } catch (ex) {
       sendFlowed = true;
     }
     var encoderFlags = dce.OutputFormatted | dce.OutputLFLineBreak;
 
-    var editor = gMsgCompose.editor.QueryInterface(Ci.nsIEditorMailSupport);
-    var wrapWidth = 72;
-
-    if (!(sendInfo.sendFlags & ENCRYPT)) {
-      // signed messages only
-      if (gMsgCompose.composeHTML) {
-        // enforce line wrapping here
-        // otherwise the message isn't signed correctly
-        try {
-          wrapWidth = this.getMailPref("editor.htmlWrapColumn");
-
-          if (wrapWidth > 0 && wrapWidth < 68 && gMsgCompose.wrapLength > 0) {
-            if (
-              EnigmailDialog.confirmDlg(
-                window,
-                EnigmailLocale.getString("minimalLineWrapping", [wrapWidth])
-              )
-            ) {
-              EnigmailPrefs.getPrefRoot().setIntPref(
-                "editor.htmlWrapColumn",
-                68
-              );
-            }
-          }
-          if (EnigmailPrefs.getPref("wrapHtmlBeforeSend")) {
-            if (wrapWidth) {
-              editor.wrapWidth = wrapWidth - 2; // prepare for the worst case: a 72 char's long line starting with '-'
-              editor.rewrap(false);
-            }
-          }
-        } catch (ex) {}
-      } else {
-        // plaintext: Wrapping code has been moved to superordinate function encryptMsg to enable interactive format switch
-      }
-    }
+    // plaintext: Wrapping code has been moved to superordinate function prepareSendMsg to enable interactive format switch
 
     var exitCodeObj = {};
     var statusFlagsObj = {};
     var errorMsgObj = {};
     var exitCode;
 
     // Get plain text
     // (Do we need to set the nsIDocumentEncoder.* flags?)
@@ -2597,17 +2529,17 @@ Enigmail.msg = {
       origText = "";
     }
 
     if (origText.length > 0) {
       // Sign/encrypt body text
 
       var escText = origText; // Copy plain text for possible escaping
 
-      if (sendFlowed && !(sendInfo.sendFlags & ENCRYPT)) {
+      if (sendFlowed) {
         // Prevent space stuffing a la RFC 2646 (format=flowed).
 
         //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: escText["+encoderFlags+"] = '"+escText+"'\n");
 
         escText = escText.replace(/^From /gm, "~From ");
         escText = escText.replace(/^>/gm, "|");
         escText = escText.replace(/^[ \t]+$/gm, "");
         escText = escText.replace(/^ /gm, "~ ");
@@ -2621,30 +2553,27 @@ Enigmail.msg = {
 
       // Replace plain text and get it again (to avoid linewrapping problems)
       this.replaceEditorText(escText);
 
       escText = this.editorGetContentAs("text/plain", encoderFlags);
 
       //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: escText["+encoderFlags+"] = '"+escText+"'\n");
 
-      // Encrypt plaintext
       var charset = this.editorGetCharset();
       EnigmailLog.DEBUG(
-        "enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: charset=" +
+        "enigmailMsgComposeOverlay.js: Enigmail.msg.signInline: charset=" +
           charset +
           "\n"
       );
 
       // Encode plaintext to charset from unicode
-      var plainText =
-        sendInfo.sendFlags & ENCRYPT
-          ? EnigmailData.convertFromUnicode(origText, charset)
-          : EnigmailData.convertFromUnicode(escText, charset);
-
+      var plainText = EnigmailData.convertFromUnicode(escText, charset);
+
+      // this will sign, not encrypt
       var cipherText = EnigmailEncryption.encryptMessage(
         window,
         sendInfo.uiFlags,
         plainText,
         sendInfo.fromAddr,
         sendInfo.toAddr,
         sendInfo.bccAddr,
         sendInfo.sendFlags,
@@ -2654,52 +2583,33 @@ Enigmail.msg = {
       );
 
       exitCode = exitCodeObj.value;
 
       //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: cipherText = '"+cipherText+"'\n");
       if (cipherText && exitCode === 0) {
         // Encryption/signing succeeded; overwrite plaintext
 
-        if (gMsgCompose.composeHTML) {
-          // workaround for Thunderbird bug (TB adds an extra space in front of the text)
-          cipherText = "\n" + cipherText;
-        } else {
-          cipherText = cipherText.replace(/\r\n/g, "\n");
-        }
-
-        if (
-          sendInfo.sendFlags & ENCRYPT &&
-          charset &&
-          charset.search(/^us-ascii$/i) !== 0
-        ) {
-          // Add Charset armor header for encrypted blocks
-          cipherText = cipherText.replace(
-            /(-----BEGIN PGP MESSAGE----- *)(\r?\n)/,
-            "$1$2Charset: " + charset + "$2"
-          );
-        }
+        cipherText = cipherText.replace(/\r\n/g, "\n");
 
         // Decode ciphertext from charset to unicode and overwrite
         this.replaceEditorText(
           EnigmailData.convertToUnicode(cipherText, charset)
         );
-        //this.enableUndoEncryption(true);
 
         // Save original text (for undo)
         this.processed = {
           origText,
           charset,
         };
       } else {
         // Restore original text
         this.replaceEditorText(origText);
-        //this.enableUndoEncryption(false);
-
-        if (sendInfo.sendFlags & (ENCRYPT | SIGN)) {
+
+        if (sendInfo.sendFlags & SIGN) {
           // Encryption/signing failed
 
           /*if (statusFlagsObj.statusMsg) {
             // check if own key is invalid
             let s = new RegExp("^(\\[GNUPG:\\] )?INV_(RECP|SGNR) [0-9]+ \\<?" + sendInfo.fromAddr + "\\>?", "m");
             if (statusFlagsObj.statusMsg.search(s) >= 0) {
               errorMsgObj.value += "\n\n" + EnigmailLocale.getString("keyError.resolutionAction");
             }
@@ -2890,87 +2800,16 @@ Enigmail.msg = {
 
   getCurrentIncomingServer() {
     let currentAccountKey = getCurrentAccountKey();
     let account = MailServices.accounts.getAccount(currentAccountKey);
 
     return account.incomingServer; /* returns nsIMsgIncomingServer */
   },
 
-  fromChangedListener(event) {
-    EnigmailLog.DEBUG(
-      "enigmailMsgComposeOverlay.js: Enigmail.msg.fromChangedListener\n"
-    );
-
-    /* TODO:
-     * reset gSendSigned, gAttachMyPublicPGPKey, gSendEncrypted, gOptionalEncryption
-     * to account's default setting, but only if settings haven't been touched
-     * by the user in this composer windows, i.e. check
-     * gUserTouchedSendEncrypted, gUserTouchedSendSigned, gUserTouchedAttachMyPubKey
-     */
-
-    /*
-  if (!gSMFields) {
-    return;
-  }
-
-  var encryptionPolicy = gCurrentIdentity.getIntAttribute("encryptionpolicy");
-  var useEncryption = false;
-  if (!gEncryptOptionChanged) {
-    // Encryption wasn't manually checked.
-    // Set up the encryption policy from the setting of the new identity.
-
-    useEncryption = encryptionPolicy == kEncryptionPolicy_Always;
-  } else if (encryptionPolicy != kEncryptionPolicy_Always) {
-    // The encryption policy was manually checked. That means we can get into
-    // the situation that the new identity doesn't have a cert to encrypt with.
-    // If it doesn't, don't encrypt.
-
-    // Encrypted (policy unencrypted, manually changed).
-    // Make sure we have a cert for encryption.
-    useEncryption = !!gCurrentIdentity.getUnicharAttribute(
-      "encryption_cert_name"
-    );
-  }
-  gSMFields.requireEncryptMessage = useEncryption;
-  if (useEncryption) {
-    setEncryptionUI();
-  } else {
-    setNoEncryptionUI();
-  }
-
-  var signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
-  var useSigning = false;
-  if (!gSignOptionChanged) {
-    // Signing wasn't manually checked.
-    // Set up the signing policy from the setting of the new identity.
-
-    useSigning = signMessage;
-  } else if (!signMessage) {
-    // The signing policy was manually checked. That means we can get into
-    // the situation that the new identity doesn't have a cert to sign with.
-    // If it doesn't, don't sign.
-
-    // Signed (policy unsigned, manually changed).
-    // Make sure we have a cert for signing.
-    useSigning = !!gCurrentIdentity.getUnicharAttribute("signing_cert_name");
-  }
-  gSMFields.signMessage = useSigning;
-  if (useSigning) {
-    setSignatureUI();
-  } else {
-    setNoSignatureUI();
-  }
-    */
-  },
-
-  /**
-   * Perform handling of the compose-send-message' event from TB (or SendLater)
-   */
-
   /**
    * Handle the 'compose-send-message' event from TB
    */
   sendMessageListener(event) {
     console.debug("in Enigmail.msg.sendMessageListener");
     EnigmailLog.DEBUG(
       "enigmailMsgComposeOverlay.js: Enigmail.msg.sendMessageListener\n"
     );
@@ -2989,17 +2828,17 @@ Enigmail.msg = {
       this.sendProcess = true;
       //let bc = document.getElementById("enigmail-bc-sendprocess");
 
       try {
         this.modifyCompFields();
         //bc.setAttribute("disabled", "true");
 
         const cApi = EnigmailCryptoAPI();
-        let encryptResult = cApi.sync(this.encryptMsg(sendMsgType));
+        let encryptResult = cApi.sync(this.prepareSendMsg(sendMsgType));
         if (!encryptResult) {
           this.resetUpdatedFields();
           event.preventDefault();
           event.stopPropagation();
         }
       } catch (ex) {
         console.debug(ex);
       }
@@ -3580,17 +3419,16 @@ Enigmail.msg = {
     try {
       EnigmailLog.DEBUG(
         "enigmailMsgComposeOverlay.js: Enigmail.msg.fireSendFlags\n"
       );
       if (!this.determineSendFlagId) {
         this.determineSendFlagId = EnigmailTimer.setTimeout(async () => {
           try {
             await this.determineSendFlags();
-            this.fireSearchKeys();
           } catch (x) {}
           this.determineSendFlagId = null;
         }, 0);
       }
     } catch (ex) {}
   },
 
   /**
@@ -3603,98 +3441,16 @@ Enigmail.msg = {
       if (r !== subjElem.value) {
         subjElem.value = r;
         if (typeof subjElem.oninput === "function") {
           subjElem.oninput();
         }
       }
     }
   },
-
-  fireSearchKeys() {
-    if (Enigmail.msg.isEnigmailEnabledForIdentity()) {
-      if (this.searchKeysTimeout) {
-        return;
-      }
-
-      let self = this;
-
-      this.searchKeysTimeout = EnigmailTimer.setTimeout(function() {
-        self.searchKeysTimeout = null;
-        Enigmail.msg.findMissingKeys();
-      }, 5000); // 5 Seconds
-    }
-  },
-
-  /**
-   * Determine if all addressees have a valid key ID; if not, attempt to
-   * import them via WKD or Autocrypt.
-   */
-  async findMissingKeys() {
-    /*
-    try {
-      EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: findMissingKeys()\n");
-
-      let missingKeys = this.determineSendFlags();
-
-      if ("errArray" in missingKeys && missingKeys.errArray.length > 0) {
-        let missingEmails = missingKeys.errArray.map(function(i) {
-          return i.addr.toLowerCase().trim();
-        });
-
-        let lookupList = [];
-
-        // only search for keys not checked before
-        for (let k of missingEmails) {
-          if (!this.keyLookupDone.includes(k)) {
-            lookupList.push(k);
-            this.keyLookupDone.push(k);
-          }
-        }
-
-        if (lookupList.length > 0) {
-          try {
-            let foundKeys;
-
-            if (this.isAutocryptEnabled()) {
-              foundKeys = await EnigmailAutocrypt.importAutocryptKeys(lookupList, this.encryptForced === EnigmailConstants.ENIG_ALWAYS);
-              EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: findMissingKeys: got " + foundKeys.length + " autocrypt keys\n");
-              if (foundKeys.length > 0) {
-                this.determineSendFlags();
-              }
-            }
-
-            if (EnigmailPrefs.getPref("autoWkdLookup") === 0) {
-              return;
-            }
-
-            // old buggy: if autocrypt is disabled, foundKeys is still undefined
-            // if (foundKeys.length >= lookupList.length) return;
-
-            foundKeys = await EnigmailWkdLookup.findKeys(lookupList);
-            EnigmailLog.DEBUG(
-              "enigmailMsgComposeOverlay.js: findMissingKeys: wkd got " +
-                foundKeys +
-                "\n"
-            );
-            if (foundKeys) {
-              this.determineSendFlags();
-            }
-          } catch (err) {
-            EnigmailLog.DEBUG(
-              "enigmailMsgComposeOverlay.js: findMissingKeys: error " +
-                err +
-                "\n"
-            );
-          }
-        }
-      }
-    } catch (ex) {}
-    */
-  },
 };
 
 Enigmail.composeStateListener = {
   NotifyComposeFieldsReady() {
     // Note: NotifyComposeFieldsReady is only called when a new window is created (i.e. not in case a window object is reused).
     EnigmailLog.DEBUG(
       "enigmailMsgComposeOverlay.js: ECSL.NotifyComposeFieldsReady\n"
     );