diff --git a/data/gui/contact_context_menu.ui b/data/gui/contact_context_menu.ui
index 0ef415beae0ad1280040e7e65c60cd575298682c..98d846d40abdbc5891c4cfbba95a3454bfb5f840 100644
--- a/data/gui/contact_context_menu.ui
+++ b/data/gui/contact_context_menu.ui
@@ -45,20 +45,6 @@
         <property name="use_underline">True</property>
       </object>
     </child>
-    <child>
-      <object class="GtkSeparatorMenuItem" id="encryption_separator">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkCheckMenuItem" id="toggle_e2e_menuitem">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="label" translatable="yes">Toggle End to End Encryption</property>
-        <property name="use_underline">True</property>
-      </object>
-    </child>
     <child>
       <object class="GtkSeparatorMenuItem" id="menuitem3">
         <property name="visible">True</property>
diff --git a/src/chat_control.py b/src/chat_control.py
index 07ff8adba07d1ebb0a52a759c24ce4e301ca90c2..b1beb22f7ef190c6b3c1e60dd2a1031154016eaf 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -280,7 +280,6 @@ class ChatControl(ChatControlBase):
 
         # Enable encryption if needed
         self.no_autonegotiation = False
-        e2e_is_active = self.session and self.session.enable_encryption
 
         self.update_ui()
         self.set_lock_image()
@@ -893,8 +892,6 @@ class ChatControl(ChatControlBase):
     def _on_authentication_button_clicked(self, widget):
         gajim.plugin_manager.gui_extension_point(
             'encryption_dialog' + self.encryption, self)
-        if self.session and self.session.enable_encryption:
-            dialogs.ESessionInfoWindow(self.session, self.parent_win.window)
 
     def send_message(self, message, keyID='', chatstate=None, xhtml=None,
     process_commands=True, attention=False):
@@ -914,11 +911,7 @@ class ChatControl(ChatControlBase):
             return None
 
         contact = self.contact
-
-        encrypted = bool(self.session) and self.session.enable_encryption
-
         keyID = contact.keyID
-        encrypted = True
 
         chatstates_on = gajim.config.get('outgoing_chat_state_notifications') != \
                 'disabled'
@@ -957,7 +950,7 @@ class ChatControl(ChatControlBase):
 
         ChatControlBase.send_message(self, message, keyID, type_='chat',
             chatstate=chatstate_to_send, xhtml=xhtml, callback=_on_sent,
-            callback_args=[message, encrypted, xhtml, self.get_seclabel()],
+            callback_args=[message, self.encryption, xhtml, self.get_seclabel()],
             process_commands=process_commands,
             attention=attention)
 
@@ -1426,19 +1419,7 @@ class ChatControl(ChatControlBase):
         if textbuffer.get_char_count():
             gajim.plugin_manager.gui_extension_point(
                 'typing' + self.encryption, self)
-            e2e_is_active = self.session and \
-                    self.session.enable_encryption
-            e2e_pref = gajim.config.get_per('accounts', self.account,
-                    'enable_esessions') and gajim.config.get_per('accounts',
-                    self.account, 'autonegotiate_esessions') and gajim.config.get_per(
-                    'contacts', self.contact.jid, 'autonegotiate_esessions')
-            want_e2e = not e2e_is_active and self.encryption == '' \
-                    and e2e_pref
-
-            if want_e2e and not self.no_autonegotiation \
-            and gajim.HAVE_PYCRYPTO and self.contact.supports(NS_ESESSION):
-                self.begin_e2e_negotiation()
-            elif (not self.session or not self.session.status) and \
+            if (not self.session or not self.session.status) and \
             gajim.connections[self.account].archiving_136_supported:
                 self.begin_archiving_negotiation()
 
@@ -1635,21 +1616,22 @@ class ChatControl(ChatControlBase):
         """
         dialogs.TransformChatToMUC(self.account, [self.contact.jid])
 
-    def _on_toggle_e2e_menuitem_activate(self, widget):
-        if self.session and self.session.enable_encryption:
-            # e2e was enabled, disable it
-            jid = str(self.session.jid)
-            thread_id = self.session.thread_id
+    def activate_esessions(self):
+        if not (self.session and self.session.enable_encryption):
+            self.begin_e2e_negotiation()
 
-            self.session.terminate_e2e()
+    def terminate_esessions(self):
+        # e2e was enabled, disable it
+        jid = str(self.session.jid)
+        thread_id = self.session.thread_id
 
-            gajim.connections[self.account].delete_session(jid, thread_id)
+        self.session.terminate_e2e()
 
-            # presumably the user had a good reason to shut it off, so
-            # disable autonegotiation too
-            self.no_autonegotiation = True
-        else:
-            self.begin_e2e_negotiation()
+        gajim.connections[self.account].delete_session(jid, thread_id)
+
+        # presumably the user had a good reason to shut it off, so
+        # disable autonegotiation too
+        self.no_autonegotiation = True
 
     def begin_negotiation(self):
         self.no_autonegotiation = True
diff --git a/src/chat_control_base.py b/src/chat_control_base.py
index 248d4990f50c8081dda3a7314b11edf4b228f257..3b6cde993f7e21d7b6ffbe15dd673c377a9ad408 100644
--- a/src/chat_control_base.py
+++ b/src/chat_control_base.py
@@ -434,6 +434,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
             plugin = gajim.plugin_manager.encryption_plugins[encryption]
             if not plugin.activate_encryption(self):
                 return
+        else:
+            self.terminate_esessions()
         action.set_state(param)
         gajim.config.set_per(
             'contacts', self.contact.jid, 'encryption', encryption)
diff --git a/src/common/config.py b/src/common/config.py
index b1c096d8aa29e861e929561a8b0632e6e1ea9467..9c8585fedfe23979df2c48aead01eff9ab5816be 100644
--- a/src/common/config.py
+++ b/src/common/config.py
@@ -481,7 +481,6 @@ class Config:
             }, {}),
             'contacts': ({
                     'encryption': [ opt_str, '', _('Encryption used for this contact.')],
-                    'autonegotiate_esessions': [opt_bool, False, _('Should Gajim automatically start an encrypted session with this contact when possible?')],
                     'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')],
             }, {}),
             'rooms': ({
diff --git a/src/common/connection.py b/src/common/connection.py
index e9f1ab2bbb85007cc6058cdf8e29fc2b470c2cf9..baf18bc45860c88107e02497db37c909b0d38af6 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -319,10 +319,6 @@ class CommonConnection:
             if obj.session:
                 obj.session.last_send = time.time()
 
-                # XEP-0200
-                if obj.session.enable_encryption:
-                    obj.correction_msg = obj.session.encrypt_stanza(obj.correction_msg)
-
             self._push_stanza_message_outgoing(obj, obj.correction_msg)
             return
 
@@ -418,20 +414,6 @@ class CommonConnection:
                 obj.session.last_send = time.time()
                 msg_iq.setThread(obj.session.thread_id)
 
-                # XEP-0200
-                if obj.session.enable_encryption:
-                    msg_iq = obj.session.encrypt_stanza(msg_iq)
-                    if self.carbons_enabled:
-                        msg_iq.addChild(name='private',
-                                        namespace=nbxmpp.NS_CARBONS)
-                    msg_iq.addChild(name='no-permanent-store',
-                                    namespace=nbxmpp.NS_MSG_HINTS)
-                    msg_iq.addChild(name='no-copy',
-                                    namespace=nbxmpp.NS_MSG_HINTS)
-                    if only_chatste:
-                        msg_iq.addChild(name='no-store',
-                                        namespace=nbxmpp.NS_MSG_HINTS)
-
         self._push_stanza_message_outgoing(obj, msg_iq)
 
     def _push_stanza_message_outgoing(self, obj, msg_iq):
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index ec25feaf95783c34e17b3dd3db037ad8b7fb07fb..80f4cf19de28273917b0b380c0bc6301d870e7db 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -1089,15 +1089,6 @@ class ConnectionHandlersBase:
         if not obj.encrypted:
             self._on_message_received(obj)
 
-        if obj.encrypted == 'xep200':
-            try:
-                obj.stanza = obj.session.decrypt_stanza(obj.stanza)
-                obj.msgtxt = obj.stanza.getBody()
-            except Exception:
-                gajim.nec.push_incoming_event(FailedDecryptEvent(None,
-                    conn=self, msg_obj=obj))
-                return
-
     def _on_message_received(self, obj):
         if isinstance(obj, MessageReceivedEvent):
             gajim.nec.push_incoming_event(
diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py
index c30823ccc2ad09a35bf0f7e4c6900230e606307b..ed2a9dd414eca40988f4787b0c26f27d94296ee4 100644
--- a/src/common/connection_handlers_events.py
+++ b/src/common/connection_handlers_events.py
@@ -1122,6 +1122,7 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
         self.get_id()
         self.forwarded = False
         self.sent = False
+        self.encrypted = False
         account = self.conn.name
 
         our_full_jid = gajim.get_jid_from_account(account, full=True)
@@ -1281,52 +1282,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
 
             self.session.last_receive = time_time()
 
-        # check if the message is a XEP-0020 feature negotiation request
-        if not self.forwarded and self.stanza.getTag('feature',
-                                                     namespace=nbxmpp.NS_FEATURE):
-            if gajim.HAVE_PYCRYPTO:
-                feature = self.stanza.getTag(name='feature',
-                                             namespace=nbxmpp.NS_FEATURE)
-                form = nbxmpp.DataForm(node=feature.getTag('x'))
-                if not form:
-                    return
-
-                if not form.getField('FORM_TYPE'):
-                    return
-
-                if form['FORM_TYPE'] == 'urn:xmpp:ssn':
-                    self.session.handle_negotiation(form)
-                else:
-                    reply = self.stanza.buildReply()
-                    reply.setType('error')
-                    reply.addChild(feature)
-                    err = nbxmpp.ErrorNode('service-unavailable', typ='cancel')
-                    reply.addChild(node=err)
-                    self.conn.connection.send(reply)
-            return
-
-        if not self.forwarded and self.stanza.getTag('init',
-                                                     namespace=nbxmpp.NS_ESESSION_INIT):
-            init = self.stanza.getTag(name='init',
-                                      namespace=nbxmpp.NS_ESESSION_INIT)
-            form = nbxmpp.DataForm(node=init.getTag('x'))
-
-            self.session.handle_negotiation(form)
-
-            return
-
         self._generate_timestamp(self.stanza.getTimestamp())
 
-
-        self.encrypted = False
-        xep_200_encrypted = self.stanza.getTag('c',
-                                               namespace=nbxmpp.NS_STANZA_CRYPTO)
-        if xep_200_encrypted:
-            if self.forwarded:
-                # Ignore E2E forwarded encrypted messages
-                return False
-            self.encrypted = 'xep200'
-
         return True
 
 class ZeroconfMessageReceivedEvent(MessageReceivedEvent):
diff --git a/src/dialogs.py b/src/dialogs.py
index bfe84ba306aa09fbce29941b8afd5d64e6757213..48203b566e0b7647af6f4190f4be82fff3c2421c 100644
--- a/src/dialogs.py
+++ b/src/dialogs.py
@@ -5315,82 +5315,6 @@ class DataFormWindow(Dialog):
             self.df_response_ok(form)
         self.destroy()
 
-class ESessionInfoWindow:
-    """
-    Class for displaying information about a XEP-0116 encrypted session
-    """
-    def __init__(self, session, transient_for=None):
-        self.session = session
-
-        self.xml = gtkgui_helpers.get_gtk_builder('esession_info_window.ui')
-        self.xml.connect_signals(self)
-
-        self.security_image = self.xml.get_object('security_image')
-        self.verify_now_button = self.xml.get_object('verify_now_button')
-        self.button_label = self.xml.get_object('verification_status_label')
-        self.window = self.xml.get_object('esession_info_window')
-        self.update_info()
-        self.window.set_transient_for(transient_for)
-
-        self.window.show_all()
-
-    def update_info(self):
-        labeltext = _('''Your chat session with <b>%(jid)s</b> is encrypted.\n\nThis session's Short Authentication String is <b>%(sas)s</b>.''') % {'jid': self.session.jid, 'sas': self.session.sas}
-
-        if self.session.verified_identity:
-            labeltext += '\n\n' + _('''You have already verified this contact's identity.''')
-            security_image = 'security-high'
-            if self.session.control:
-                self.session.control._show_lock_image(True, 'E2E', True,
-                    self.session.is_loggable(), True)
-
-            verification_status = _('''Contact's identity verified''')
-            self.window.set_title(verification_status)
-            self.xml.get_object('verification_status_label').set_markup(
-                    '<b><span size="x-large">%s</span></b>' % verification_status)
-
-            self.xml.get_object('dialog-action_area1').set_no_show_all(True)
-            self.button_label.set_text(_('Verify again…'))
-        else:
-            if self.session.control:
-                self.session.control._show_lock_image(True, 'E2E', True,
-                     self.session.is_loggable(), False)
-            labeltext += '\n\n' + _('''To be certain that <b>only</b> the expected person can read your messages or send you messages, you need to verify their identity by clicking the button below.''')
-            security_image = 'security-low'
-
-            verification_status = _('''Contact's identity NOT verified''')
-            self.window.set_title(verification_status)
-            self.xml.get_object('verification_status_label').set_markup(
-                '<b><span size="x-large">%s</span></b>' % verification_status)
-
-            self.button_label.set_text(_('Verify…'))
-
-        path = gtkgui_helpers.get_icon_path(security_image, 32)
-        self.security_image.set_from_file(path)
-
-        self.xml.get_object('info_display').set_markup(labeltext)
-
-    def on_close_button_clicked(self, widget):
-        self.window.destroy()
-
-    def on_verify_now_button_clicked(self, widget):
-        pritext = _('''Have you verified the contact's identity?''')
-        sectext = _('''To prevent talking to an unknown person, you should speak to <b>%(jid)s</b> directly (in person or on the phone) and verify that they see the same Short Authentication String (SAS) as you.\n\nThis session's Short Authentication String is <b>%(sas)s</b>.''') % {'jid': self.session.jid, 'sas': self.session.sas}
-        sectext += '\n\n' + _('Did you talk to the remote contact and verify the SAS?')
-
-        def on_yes(checked):
-            self.session._verified_srs_cb()
-            self.session.verified_identity = True
-            self.update_info()
-
-        def on_no():
-            self.session._unverified_srs_cb()
-            self.session.verified_identity = False
-            self.update_info()
-
-        YesNoDialog(pritext, sectext, on_response_yes=on_yes,
-            on_response_no=on_no, transient_for=self.window)
-
 
 class ResourceConflictDialog(TimeoutDialog, InputDialog):
     def __init__(self, title, text, resource, ok_handler):
diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py
index f61ae68bd9f906bc12b2eab85acebe12dc814975..f03d61a87b23fa81605db3e9f2ee8188bc413e7b 100644
--- a/src/gui_menu_builder.py
+++ b/src/gui_menu_builder.py
@@ -245,8 +245,6 @@ control=None, gc_contact=None, is_anonymous=True):
             'remove_from_roster_menuitem')
     manage_contact_menuitem = xml.get_object('manage_contact')
     convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem')
-    encryption_separator = xml.get_object('encryption_separator')
-    toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem')
     last_separator = xml.get_object('last_separator')
 
     items_to_hide = []
@@ -321,21 +319,6 @@ control=None, gc_contact=None, is_anonymous=True):
     if not show_start_chat:
         items_to_hide.append(start_chat_menuitem)
 
-    if not show_encryption or not control:
-        items_to_hide += [encryption_separator, toggle_e2e_menuitem]
-    else:
-        e2e_is_active = control.session is not None and \
-                control.session.enable_encryption
-
-        # disable esessions if we or the other client don't support them
-        if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) or \
-        not gajim.config.get_per('accounts', account, 'enable_esessions'):
-            toggle_e2e_menuitem.set_sensitive(False)
-        else:
-            toggle_e2e_menuitem.set_active(e2e_is_active)
-            toggle_e2e_menuitem.connect('activate',
-                    control._on_toggle_e2e_menuitem_activate)
-
     if not show_buttonbar_items:
         items_to_hide += [history_menuitem, send_file_menuitem,
                 information_menuitem, convert_to_gc_menuitem, last_separator]