changeset 1855:1c9b2c184663

plugin account: email sending improvments: the following new options are handled: - email_sender_domain (default None) - email_port (default 25) - email_username (defaut None) - email_password (default None) - email_starttls true to force starttls (default false) - email_auth true to require authentication (default false) in addition, admin_email has been deprecated in favor of email_admins_list which can handle several addresses
author Goffi <goffi@goffi.org>
date Sat, 27 Feb 2016 14:49:20 +0100
parents 3c0bb714a80b
children d7e29a12ec2c
files src/plugins/plugin_misc_account.py
diffstat 1 files changed, 61 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_misc_account.py	Thu Feb 25 16:21:17 2016 +0100
+++ b/src/plugins/plugin_misc_account.py	Sat Feb 27 14:49:20 2016 +0100
@@ -25,7 +25,7 @@
 from sat.memory.memory import Sessions
 from sat.memory.crypto import PasswordHasher
 from sat.core.constants import Const as C
-
+import ConfigParser
 from twisted.internet import reactor, defer, protocol
 from twisted.python.procutils import which
 from twisted.python.failure import Failure
@@ -56,7 +56,14 @@
 
 default_conf = {"email_from": "NOREPLY@example.net",
                 "email_server": "localhost",
-                "admin_email": "admin@example.net",
+                "email_sender_domain": "",
+                "email_port": 25,
+                "email_username": "",
+                "email_password": "",
+                "email_starttls": "false",
+                "email_auth": "false",
+                "email_admins_list": [],
+                "admin_email": "",
                 "new_account_server": "localhost",
                 "new_account_domain": "example.net",
                 "prosody_path": None, # prosody path (where prosodyctl will be executed from), or None to automaticaly find it
@@ -155,6 +162,17 @@
         self.__delete_account_id = host.registerCallback(self.__deleteAccountCb, with_data=True)
 
     def getConfig(self, name):
+        if name.startswith("email_"):
+            # XXX: email_ parameters were first in [plugin account] section
+            #      but as it make more sense to have them in common with other plugins,
+            #      they can now be in [DEFAULT] section
+            try:
+                value = self.host.memory.getConfig(None, name, Exception)
+            except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+                pass
+            else:
+                return value
+
         return self.host.memory.getConfig(CONFIG_SECTION, name, default_conf[name])
 
     def generatePassword(self):
@@ -232,19 +250,42 @@
 
         email_host = self.getConfig('email_server')
         email_from = self.getConfig("email_from")
+        email_sender_domain = self.getConfig("email_sender_domain") or None
+        email_port = int(self.getConfig("email_port"))
+        email_username = self.getConfig("email_username") or None
+        email_password = self.getConfig("email_password") or None
+        email_starttls = C.bool(self.getConfig("email_starttls"))
+        email_auth = C.bool(self.getConfig("email_auth"))
         domain = self.getConfig('new_account_domain')
 
+        # admin
+        admins_emails = self.getConfig('email_admins_list')
+        admin_email = self.getConfig('admin_email')
+        if admin_email:
+            log.warning(u"admin_email parameter is deprecated, please use email_admins_list instead")
+            admins_emails.append(admin_email)
+
         # email to the administrator
-        body = (u"""New account created: %(profile)s [%(email)s]""" % {'profile': profile, 'email': email}).encode('utf-8')
-        msg = MIMEText(body, 'plain', 'UTF-8')
-        msg['Subject'] = _('New Libervia account created')
-        msg['From'] = email_from
-        msg['To'] = self.getConfig('admin_email')
+        if not admins_emails:
+            log.warning(u"No known admin email, we can't send email to administrator(s).\nPlease fill email_admins_list parameter")
+            d_admin = defer.fail(exceptions.DataError("no admin email"))
+        else:
+            body = (u"""New account created: %(profile)s [%(email)s]""" % {'profile': profile, 'email': email}).encode('utf-8')
+            msg = MIMEText(body, 'plain', 'UTF-8')
+            msg['Subject'] = _('New Libervia account created')
+            msg['From'] = email_from
+            msg['To'] = ", ".join(admins_emails)
 
-        admin_email = self.getConfig('admin_email')
-        d_admin = sendmail(email_host, email_from, admin_email, msg.as_string())
-        d_admin.addCallbacks(lambda dummy: log.debug(u"Account creation notification sent to admin <%s>" % admin_email),
-                             lambda dummy: log.error(u"Failed to send account creation notification to admin <%s>" % admin_email))
+            d_admin = sendmail(email_host, email_from, admins_emails, msg.as_string(),
+                senderDomainName=email_sender_domain,
+                port=email_port,
+                username=email_username,
+                password=email_password,
+                requireAuthentication=email_starttls,
+                requireTransportSecurity=email_auth)
+        admins_emails_txt = u', '.join([u"<{}>".format(addr) for addr in admins_emails])
+        d_admin.addCallbacks(lambda dummy: log.debug(u"Account creation notification sent to admin(s) {}".format(admins_emails_txt)),
+                             lambda dummy: log.error(u"Failed to send account creation notification to admin {}".format(admins_emails_txt)))
         if not email:
             return d_admin
 
@@ -282,7 +323,13 @@
         # XXX: this will not fail when the email address doesn't exist
         # FIXME: check email reception to validate email given by the user
         # FIXME: delete the profile if the email could not been sent?
-        d_user = sendmail(email_host, email_from, email, msg.as_string())
+        d_user = sendmail(email_host, email_from, email, msg.as_string(),
+            senderDomainName=email_sender_domain,
+            port=email_port,
+            username=email_username,
+            password=email_password,
+            requireAuthentication=email_starttls,
+            requireTransportSecurity=email_auth)
         d_user.addCallbacks(lambda dummy: log.debug(u"Account creation confirmation sent to <%s>" % email),
                             email_ko)
         return defer.DeferredList([d_user, d_admin])
@@ -308,7 +355,7 @@
         form_ui.addLabel(D_("New password (again)"))
         form_ui.addPassword("new_passwd2", value="")
 
-        # FIXME: uncomment and fix these features 
+        # FIXME: uncomment and fix these features
         """
         if 'GROUPBLOG' in self.host.plugins:
             tab_container.addTab("delete_posts", D_("Delete your posts"), container=xml_tools.PairsContainer)
@@ -349,7 +396,7 @@
             return {'xmlui': error_ui.toXml()}
 
         # check for account deletion
-        # FIXME: uncomment and fix these features 
+        # FIXME: uncomment and fix these features
         """
         delete_passwd = data[xml_tools.SAT_FORM_PREFIX + 'delete_passwd']
         delete_checkbox = data[xml_tools.SAT_FORM_PREFIX + 'delete_checkbox']