prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  mail controlpanel: doesn't keep password field
  Saving the mail settings in the controlpanel doesn't keep the password field value, as it is obviously never shown in ESMTP password.
  
  Steps to reproduce:
  1. Fill in ESMTP username and ESMTP password. Save settings. They are correctly stored.
  2. Apply save settings again. ESMTP password is incorrectly stored as None.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `Products/CMFPlone/controlpanel/browser/mail.py`
  Content:
  ```
  1 from Products.CMFCore.utils import getToolByName
  2 from Products.CMFPlone import PloneMessageFactory as _
  3 from Products.CMFPlone.interfaces.controlpanel import IMailSchema
  4 from Products.MailHost.MailHost import MailHostError
  5 from Products.statusmessages.interfaces import IStatusMessage
  6 from logging import getLogger
  7 from plone.app.registry.browser import controlpanel
  8 from plone.registry.interfaces import IRegistry
  9 from z3c.form import button
  10 from zope.component import getUtility
  11 
  12 import smtplib
  13 import socket
  14 import sys
  15 
  16 log = getLogger('Plone')
  17 
  18 
  19 class MailControlPanelForm(controlpanel.RegistryEditForm):
  20 
  21     id = "MailControlPanel"
  22     label = _(u"Mail Settings")
  23     schema = IMailSchema
  24     schema_prefix = "plone"
  25 
  26     @button.buttonAndHandler(_('Save'), name=None)
  27     def handleSave(self, action):
  28         self.save()
  29 
  30     @button.buttonAndHandler(_('Cancel'), name='cancel')
  31     def handleCancel(self, action):
  32         super(MailControlPanelForm, self).handleCancel(self, action)
  33 
  34     def save(self):
  35         data, errors = self.extractData()
  36         if errors:
  37             self.status = self.formErrorsMessage
  38             return False
  39         self.applyChanges(data)
  40         return True
  41 
  42     @button.buttonAndHandler(
  43         _('label_smtp_test', default='Save and send test e-mail'),
  44         name='test')
  45     def handle_test_action(self, action):
  46         # Save data first
  47         if not self.save():
  48             return
  49         mailhost = getToolByName(self.context, 'MailHost')
  50 
  51         registry = getUtility(IRegistry)
  52         mail_settings = registry.forInterface(IMailSchema, prefix='plone')
  53         fromaddr = mail_settings.email_from_address
  54         fromname = mail_settings.email_from_name
  55 
  56         message = ("Hi,\n\nThis is a test message sent from the Plone "
  57                    "'Mail settings' control panel. Your receipt of this "
  58                    "message (at the address specified in the Site 'From' "
  59                    "address field) indicates that your e-mail server is "
  60                    "working!\n\n"
  61                    "Have a nice day.\n\n"
  62                    "Love,\n\nPlone")
  63         email_charset = mail_settings.email_charset
  64         subject = "Test e-mail from Plone"
  65 
  66         # Make the timeout incredibly short. This is enough time for most mail
  67         # servers, wherever they may be in the world, to respond to the
  68         # connection request. Make sure we save the current value
  69         # and restore it afterward.
  70         timeout = socket.getdefaulttimeout()
  71         try:
  72             socket.setdefaulttimeout(3)
  73             try:
  74                 mailhost.send(message,
  75                               mto=fromaddr,
  76                               mfrom=fromaddr,
  77                               subject=subject,
  78                               charset=email_charset,
  79                               immediate=True)
  80 
  81             except (socket.error, MailHostError, smtplib.SMTPException):
  82                 # Connection refused or timeout.
  83                 log.exception('Unable to send test e-mail.')
  84                 value = sys.exc_info()[1]
  85                 msg = _(u'Unable to send test e-mail ${error}.',
  86                         mapping={'error': unicode(value)})
  87                 IStatusMessage(self.request).addStatusMessage(
  88                     msg, type='error')
  89             else:
  90                 IStatusMessage(self.request).addStatusMessage(
  91                     _(u'Success! Check your mailbox for the test message.'),
  92                     type='info')
  93         finally:
  94             # Restore timeout to default value
  95             socket.setdefaulttimeout(timeout)
  96 
  97 
  98 class MailControlPanel(controlpanel.ControlPanelFormWrapper):
  99     form = MailControlPanelForm
  100
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/Products/CMFPlone/controlpanel/browser/mail.py b/Products/CMFPlone/controlpanel/browser/mail.py
  --- a/Products/CMFPlone/controlpanel/browser/mail.py
  +++ b/Products/CMFPlone/controlpanel/browser/mail.py
  @@ -36,6 +36,10 @@
           if errors:
               self.status = self.formErrorsMessage
               return False
  +        #keep password field
  +        if (data.get('smtp_userid') is not None
  +            and data.get('smtp_pass') is None):
  +            del data['smtp_pass']
           self.applyChanges(data)
           return True
  
verification_info: {"golden_diff": "diff --git a/Products/CMFPlone/controlpanel/browser/mail.py b/Products/CMFPlone/controlpanel/browser/mail.py\n--- a/Products/CMFPlone/controlpanel/browser/mail.py\n+++ b/Products/CMFPlone/controlpanel/browser/mail.py\n@@ -36,6 +36,10 @@\n         if errors:\n             self.status = self.formErrorsMessage\n             return False\n+        #keep password field\n+        if (data.get('smtp_userid') is not None\n+            and data.get('smtp_pass') is None):\n+            del data['smtp_pass']\n         self.applyChanges(data)\n         return True\n", "issue": "mail controlpanel: doesn't keep password field\nSaving the mail settings in the controlpanel doesn't keep the password field value, as it is obviously never shown in ESMTP password.\n\nSteps to reproduce:\n1. Fill in ESMTP username and ESMTP password. Save settings. They are correctly stored.\n2. Apply save settings again. ESMTP password is incorrectly stored as None.\n\n", "before_files": [{"content": "from Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.interfaces.controlpanel import IMailSchema\nfrom Products.MailHost.MailHost import MailHostError\nfrom Products.statusmessages.interfaces import IStatusMessage\nfrom logging import getLogger\nfrom plone.app.registry.browser import controlpanel\nfrom plone.registry.interfaces import IRegistry\nfrom z3c.form import button\nfrom zope.component import getUtility\n\nimport smtplib\nimport socket\nimport sys\n\nlog = getLogger('Plone')\n\n\nclass MailControlPanelForm(controlpanel.RegistryEditForm):\n\n    id = \"MailControlPanel\"\n    label = _(u\"Mail Settings\")\n    schema = IMailSchema\n    schema_prefix = \"plone\"\n\n    @button.buttonAndHandler(_('Save'), name=None)\n    def handleSave(self, action):\n        self.save()\n\n    @button.buttonAndHandler(_('Cancel'), name='cancel')\n    def handleCancel(self, action):\n        super(MailControlPanelForm, self).handleCancel(self, action)\n\n    def save(self):\n        data, errors = self.extractData()\n        if errors:\n            self.status = self.formErrorsMessage\n            return False\n        self.applyChanges(data)\n        return True\n\n    @button.buttonAndHandler(\n        _('label_smtp_test', default='Save and send test e-mail'),\n        name='test')\n    def handle_test_action(self, action):\n        # Save data first\n        if not self.save():\n            return\n        mailhost = getToolByName(self.context, 'MailHost')\n\n        registry = getUtility(IRegistry)\n        mail_settings = registry.forInterface(IMailSchema, prefix='plone')\n        fromaddr = mail_settings.email_from_address\n        fromname = mail_settings.email_from_name\n\n        message = (\"Hi,\\n\\nThis is a test message sent from the Plone \"\n                   \"'Mail settings' control panel. Your receipt of this \"\n                   \"message (at the address specified in the Site 'From' \"\n                   \"address field) indicates that your e-mail server is \"\n                   \"working!\\n\\n\"\n                   \"Have a nice day.\\n\\n\"\n                   \"Love,\\n\\nPlone\")\n        email_charset = mail_settings.email_charset\n        subject = \"Test e-mail from Plone\"\n\n        # Make the timeout incredibly short. This is enough time for most mail\n        # servers, wherever they may be in the world, to respond to the\n        # connection request. Make sure we save the current value\n        # and restore it afterward.\n        timeout = socket.getdefaulttimeout()\n        try:\n            socket.setdefaulttimeout(3)\n            try:\n                mailhost.send(message,\n                              mto=fromaddr,\n                              mfrom=fromaddr,\n                              subject=subject,\n                              charset=email_charset,\n                              immediate=True)\n\n            except (socket.error, MailHostError, smtplib.SMTPException):\n                # Connection refused or timeout.\n                log.exception('Unable to send test e-mail.')\n                value = sys.exc_info()[1]\n                msg = _(u'Unable to send test e-mail ${error}.',\n                        mapping={'error': unicode(value)})\n                IStatusMessage(self.request).addStatusMessage(\n                    msg, type='error')\n            else:\n                IStatusMessage(self.request).addStatusMessage(\n                    _(u'Success! Check your mailbox for the test message.'),\n                    type='info')\n        finally:\n            # Restore timeout to default value\n            socket.setdefaulttimeout(timeout)\n\n\nclass MailControlPanel(controlpanel.ControlPanelFormWrapper):\n    form = MailControlPanelForm\n", "path": "Products/CMFPlone/controlpanel/browser/mail.py"}], "after_files": [{"content": "from Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.interfaces.controlpanel import IMailSchema\nfrom Products.MailHost.MailHost import MailHostError\nfrom Products.statusmessages.interfaces import IStatusMessage\nfrom logging import getLogger\nfrom plone.app.registry.browser import controlpanel\nfrom plone.registry.interfaces import IRegistry\nfrom z3c.form import button\nfrom zope.component import getUtility\n\nimport smtplib\nimport socket\nimport sys\n\nlog = getLogger('Plone')\n\n\nclass MailControlPanelForm(controlpanel.RegistryEditForm):\n\n    id = \"MailControlPanel\"\n    label = _(u\"Mail Settings\")\n    schema = IMailSchema\n    schema_prefix = \"plone\"\n\n    @button.buttonAndHandler(_('Save'), name=None)\n    def handleSave(self, action):\n        self.save()\n\n    @button.buttonAndHandler(_('Cancel'), name='cancel')\n    def handleCancel(self, action):\n        super(MailControlPanelForm, self).handleCancel(self, action)\n\n    def save(self):\n        data, errors = self.extractData()\n        if errors:\n            self.status = self.formErrorsMessage\n            return False\n        #keep password field\n        if (data.get('smtp_userid') is not None\n            and data.get('smtp_pass') is None):\n            del data['smtp_pass']\n        self.applyChanges(data)\n        return True\n\n    @button.buttonAndHandler(\n        _('label_smtp_test', default='Save and send test e-mail'),\n        name='test')\n    def handle_test_action(self, action):\n        # Save data first\n        if not self.save():\n            return\n        mailhost = getToolByName(self.context, 'MailHost')\n\n        registry = getUtility(IRegistry)\n        mail_settings = registry.forInterface(IMailSchema, prefix='plone')\n        fromaddr = mail_settings.email_from_address\n        fromname = mail_settings.email_from_name\n\n        message = (\"Hi,\\n\\nThis is a test message sent from the Plone \"\n                   \"'Mail settings' control panel. Your receipt of this \"\n                   \"message (at the address specified in the Site 'From' \"\n                   \"address field) indicates that your e-mail server is \"\n                   \"working!\\n\\n\"\n                   \"Have a nice day.\\n\\n\"\n                   \"Love,\\n\\nPlone\")\n        email_charset = mail_settings.email_charset\n        subject = \"Test e-mail from Plone\"\n\n        # Make the timeout incredibly short. This is enough time for most mail\n        # servers, wherever they may be in the world, to respond to the\n        # connection request. Make sure we save the current value\n        # and restore it afterward.\n        timeout = socket.getdefaulttimeout()\n        try:\n            socket.setdefaulttimeout(3)\n            try:\n                mailhost.send(message,\n                              mto=fromaddr,\n                              mfrom=fromaddr,\n                              subject=subject,\n                              charset=email_charset,\n                              immediate=True)\n\n            except (socket.error, MailHostError, smtplib.SMTPException):\n                # Connection refused or timeout.\n                log.exception('Unable to send test e-mail.')\n                value = sys.exc_info()[1]\n                msg = _(u'Unable to send test e-mail ${error}.',\n                        mapping={'error': unicode(value)})\n                IStatusMessage(self.request).addStatusMessage(\n                    msg, type='error')\n            else:\n                IStatusMessage(self.request).addStatusMessage(\n                    _(u'Success! Check your mailbox for the test message.'),\n                    type='info')\n        finally:\n            # Restore timeout to default value\n            socket.setdefaulttimeout(timeout)\n\n\nclass MailControlPanel(controlpanel.ControlPanelFormWrapper):\n    form = MailControlPanelForm\n", "path": "Products/CMFPlone/controlpanel/browser/mail.py"}]}