From 2ed0adb075b745e6586ca88ce7cf6b169460a7d7 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 20 Apr 2016 18:35:29 +0100 Subject: [PATCH] Generate mails from a template --- synapse/config/emailconfig.py | 35 ++++++++++++++++++++++++---------- synapse/push/emailpusher.py | 12 ++++-------- synapse/push/mailer.py | 30 ++++++++++++++++------------- synapse/python_dependencies.py | 3 +++ 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/synapse/config/emailconfig.py b/synapse/config/emailconfig.py index 978826627b..68fb4d8060 100644 --- a/synapse/config/emailconfig.py +++ b/synapse/config/emailconfig.py @@ -28,19 +28,32 @@ class EmailConfig(Config): email_config = config.get("email", None) if email_config: self.email_enable_notifs = email_config.get("enable_notifs", True) - if ( - "smtp_host" not in email_config or - "smtp_port" not in email_config or - "notif_from" not in email_config - ): + + required = [ + "smtp_host", + "smtp_port", + "notif_from", + "template_dir", + "notif_template_html", + + ] + + missing = [] + for k in required: + if k not in email_config: + missing.append(k) + + if (len(missing) > 0): raise RuntimeError( - "You must set smtp_host, smtp_port and notif_from " - "to send email notifications" + "email.enable_notifs is True but required keys are missing: %s" % + (", ".join(["email."+k for k in missing]),) ) self.email_smtp_host = email_config["smtp_host"] self.email_smtp_port = email_config["smtp_port"] self.email_notif_from = email_config["notif_from"] + self.email_template_dir = email_config["template_dir"] + self.email_notif_template_html = email_config["notif_template_html"] # make sure it's valid parsed = email.utils.parseaddr(self.email_notif_from) @@ -48,9 +61,8 @@ class EmailConfig(Config): raise RuntimeError("Invalid notif_from address") else: self.email_enable_notifs = False - self.email_smtp_host = None - self.email_smtp_port = None - self.email_notif_from = None + # Not much point setting defaults for the rest: it would be an + # error for them to be used. def default_config(self, config_dir_path, server_name, **kwargs): return """ @@ -59,4 +71,7 @@ class EmailConfig(Config): # enable_notifs: false # smtp_host: "localhost" # smtp_port: 25 + # notif_from: Your Friendly Matrix Home Server + # template_dir: res/templates + # notif_template_html: notif.html """ diff --git a/synapse/push/emailpusher.py b/synapse/push/emailpusher.py index 820c8f8467..4e21221fb7 100644 --- a/synapse/push/emailpusher.py +++ b/synapse/push/emailpusher.py @@ -61,11 +61,7 @@ class EmailPusher(object): self.processing = False if self.hs.config.email_enable_notifs: - self.mailer = Mailer( - self.store, - self.hs.config.email_smtp_host, self.hs.config.email_smtp_port, - self.hs.config.email_notif_from, - ) + self.mailer = Mailer(self.hs) else: self.mailer = None @@ -149,7 +145,7 @@ class EmailPusher(object): # *one* email updating the user on their notifications, # we then consider all previously outstanding notifications # to be delivered. - yield self.send_notification(push_action) + yield self.send_notification(unprocessed) yield self.save_last_stream_ordering_and_success(max([ ea['stream_ordering'] for ea in unprocessed @@ -252,8 +248,8 @@ class EmailPusher(object): ) @defer.inlineCallbacks - def send_notification(self, push_action): + def send_notification(self, push_actions): logger.info("Sending notif email for user %r", self.user_id) yield self.mailer.send_notification_mail( - self.user_id, self.email, push_action + self.user_id, self.email, push_actions ) diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py index 97cba2ec2b..0f20d43f75 100644 --- a/synapse/push/mailer.py +++ b/synapse/push/mailer.py @@ -15,34 +15,38 @@ from twisted.internet import defer -import smtplib +from twisted.mail.smtp import sendmail import email.utils import email.mime.multipart from email.mime.text import MIMEText +import jinja2 + class Mailer(object): - def __init__(self, store, smtp_host, smtp_port, notif_from): - self.store = store - self.smtp_host = smtp_host - self.smtp_port = smtp_port - self.notif_from = notif_from + def __init__(self, hs): + self.hs = hs + loader = jinja2.FileSystemLoader(self.hs.config.email_template_dir) + env = jinja2.Environment(loader=loader) + self.notif_template = env.get_template(self.hs.config.email_notif_template_html) @defer.inlineCallbacks - def send_notification_mail(self, user_id, email_address, push_action): - raw_from = email.utils.parseaddr(self.notif_from)[1] + def send_notification_mail(self, user_id, email_address, push_actions): + raw_from = email.utils.parseaddr(self.hs.config.email_notif_from)[1] raw_to = email.utils.parseaddr(email_address)[1] if raw_to == '': raise RuntimeError("Invalid 'to' address") - plainText = "yo dawg, you got notifications!" + plainText = self.notif_template.render() text_part = MIMEText(plainText, "plain") text_part['Subject'] = "New Matrix Notifications" - text_part['From'] = self.notif_from + text_part['From'] = self.hs.config.email_notif_from text_part['To'] = email_address - smtp = smtplib.SMTP(self.smtp_host, self.smtp_port) - smtp.sendmail(raw_from, raw_to, text_part.as_string()) - smtp.quit() + yield sendmail( + self.hs.config.email_smtp_host, + raw_from, raw_to, text_part.as_string(), + port=self.hs.config.email_smtp_port + ) diff --git a/synapse/python_dependencies.py b/synapse/python_dependencies.py index b25b736493..a065c78b4d 100644 --- a/synapse/python_dependencies.py +++ b/synapse/python_dependencies.py @@ -45,6 +45,9 @@ CONDITIONAL_REQUIREMENTS = { "preview_url": { "netaddr>=0.7.18": ["netaddr"], }, + "email.enable_notifs": { + "Jinja2": ["Jinja2"], + }, }