# HG changeset patch # User Goffi # Date 1456580960 -3600 # Node ID 1c9b2c184663a0c15e1b203563052b39a304a8a5 # Parent 3c0bb714a80bf0b0d6fc59d0302ca712435e9ffd 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 diff -r 3c0bb714a80b -r 1c9b2c184663 src/plugins/plugin_misc_account.py --- 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']