diff --git a/synapse/push/mailer.py b/synapse/push/mailer.py
index d57a66a697..c38e037281 100644
--- a/synapse/push/mailer.py
+++ b/synapse/push/mailer.py
@@ -16,18 +16,17 @@
import email.mime.multipart
import email.utils
import logging
-import time
+import urllib.parse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import Iterable, List, TypeVar
-from six.moves import urllib
-
import bleach
import jinja2
from synapse.api.constants import EventTypes
from synapse.api.errors import StoreError
+from synapse.config.emailconfig import EmailSubjectConfig
from synapse.logging.context import make_deferred_yieldable
from synapse.push.presentable_names import (
calculate_room_name,
@@ -43,23 +42,6 @@ logger = logging.getLogger(__name__)
T = TypeVar("T")
-MESSAGE_FROM_PERSON_IN_ROOM = (
- "You have a message on %(app)s from %(person)s in the %(room)s room..."
-)
-MESSAGE_FROM_PERSON = "You have a message on %(app)s from %(person)s..."
-MESSAGES_FROM_PERSON = "You have messages on %(app)s from %(person)s..."
-MESSAGES_IN_ROOM = "You have messages on %(app)s in the %(room)s room..."
-MESSAGES_IN_ROOM_AND_OTHERS = (
- "You have messages on %(app)s in the %(room)s room and others..."
-)
-MESSAGES_FROM_PERSON_AND_OTHERS = (
- "You have messages on %(app)s from %(person)s and others..."
-)
-INVITE_FROM_PERSON_TO_ROOM = (
- "%(person)s has invited you to join the %(room)s room on %(app)s..."
-)
-INVITE_FROM_PERSON = "%(person)s has invited you to chat on %(app)s..."
-
CONTEXT_BEFORE = 1
CONTEXT_AFTER = 1
@@ -122,6 +104,7 @@ class Mailer(object):
self.state_handler = self.hs.get_state_handler()
self.storage = hs.get_storage()
self.app_name = app_name
+ self.email_subjects = hs.config.email_subjects # type: EmailSubjectConfig
logger.info("Created Mailer for app_name %s" % app_name)
@@ -148,7 +131,8 @@ class Mailer(object):
await self.send_email(
email_address,
- "[%s] Password Reset" % self.hs.config.server_name,
+ self.email_subjects.password_reset
+ % {"server_name": self.hs.config.server_name},
template_vars,
)
@@ -175,7 +159,8 @@ class Mailer(object):
await self.send_email(
email_address,
- "[%s] Register your Email Address" % self.hs.config.server_name,
+ self.email_subjects.email_validation
+ % {"server_name": self.hs.config.server_name},
template_vars,
)
@@ -203,7 +188,8 @@ class Mailer(object):
await self.send_email(
email_address,
- "[%s] Validate Your Email" % self.hs.config.server_name,
+ self.email_subjects.email_validation
+ % {"server_name": self.hs.config.server_name},
template_vars,
)
@@ -270,16 +256,13 @@ class Mailer(object):
user_id, app_id, email_address
),
"summary_text": summary_text,
- "app_name": self.app_name,
"rooms": rooms,
"reason": reason,
}
- await self.send_email(
- email_address, "[%s] %s" % (self.app_name, summary_text), template_vars
- )
+ await self.send_email(email_address, summary_text, template_vars)
- async def send_email(self, email_address, subject, template_vars):
+ async def send_email(self, email_address, subject, extra_template_vars):
"""Send an email with the given information and template text"""
try:
from_string = self.hs.config.email_notif_from % {"app": self.app_name}
@@ -292,6 +275,13 @@ class Mailer(object):
if raw_to == "":
raise RuntimeError("Invalid 'to' address")
+ template_vars = {
+ "app_name": self.app_name,
+ "server_name": self.hs.config.server.server_name,
+ }
+
+ template_vars.update(extra_template_vars)
+
html_text = self.template_html.render(**template_vars)
html_part = MIMEText(html_text, "html", "utf8")
@@ -477,12 +467,12 @@ class Mailer(object):
inviter_name = name_from_member_event(inviter_member_event)
if room_name is None:
- return INVITE_FROM_PERSON % {
+ return self.email_subjects.invite_from_person % {
"person": inviter_name,
"app": self.app_name,
}
else:
- return INVITE_FROM_PERSON_TO_ROOM % {
+ return self.email_subjects.invite_from_person_to_room % {
"person": inviter_name,
"room": room_name,
"app": self.app_name,
@@ -500,13 +490,13 @@ class Mailer(object):
sender_name = name_from_member_event(state_event)
if sender_name is not None and room_name is not None:
- return MESSAGE_FROM_PERSON_IN_ROOM % {
+ return self.email_subjects.message_from_person_in_room % {
"person": sender_name,
"room": room_name,
"app": self.app_name,
}
elif sender_name is not None:
- return MESSAGE_FROM_PERSON % {
+ return self.email_subjects.message_from_person % {
"person": sender_name,
"app": self.app_name,
}
@@ -514,7 +504,10 @@ class Mailer(object):
# There's more than one notification for this room, so just
# say there are several
if room_name is not None:
- return MESSAGES_IN_ROOM % {"room": room_name, "app": self.app_name}
+ return self.email_subjects.messages_in_room % {
+ "room": room_name,
+ "app": self.app_name,
+ }
else:
# If the room doesn't have a name, say who the messages
# are from explicitly to avoid, "messages in the Bob room"
@@ -532,7 +525,7 @@ class Mailer(object):
]
)
- return MESSAGES_FROM_PERSON % {
+ return self.email_subjects.messages_from_person % {
"person": descriptor_from_member_events(member_events.values()),
"app": self.app_name,
}
@@ -541,7 +534,7 @@ class Mailer(object):
# ...but we still refer to the 'reason' room which triggered the mail
if reason["room_name"] is not None:
- return MESSAGES_IN_ROOM_AND_OTHERS % {
+ return self.email_subjects.messages_in_room_and_others % {
"room": reason["room_name"],
"app": self.app_name,
}
@@ -561,7 +554,7 @@ class Mailer(object):
[room_state_ids[room_id][("m.room.member", s)] for s in sender_ids]
)
- return MESSAGES_FROM_PERSON_AND_OTHERS % {
+ return self.email_subjects.messages_from_person_and_others % {
"person": descriptor_from_member_events(member_events.values()),
"app": self.app_name,
}
@@ -646,72 +639,3 @@ def string_ordinal_total(s):
for c in s:
tot += ord(c)
return tot
-
-
-def format_ts_filter(value, format):
- return time.strftime(format, time.localtime(value / 1000))
-
-
-def load_jinja2_templates(
- template_dir,
- template_filenames,
- apply_format_ts_filter=False,
- apply_mxc_to_http_filter=False,
- public_baseurl=None,
-):
- """Loads and returns one or more jinja2 templates and applies optional filters
-
- Args:
- template_dir (str): The directory where templates are stored
- template_filenames (list[str]): A list of template filenames
- apply_format_ts_filter (bool): Whether to apply a template filter that formats
- timestamps
- apply_mxc_to_http_filter (bool): Whether to apply a template filter that converts
- mxc urls to http urls
- public_baseurl (str|None): The public baseurl of the server. Required for
- apply_mxc_to_http_filter to be enabled
-
- Returns:
- A list of jinja2 templates corresponding to the given list of filenames,
- with order preserved
- """
- logger.info(
- "loading email templates %s from '%s'", template_filenames, template_dir
- )
- loader = jinja2.FileSystemLoader(template_dir)
- env = jinja2.Environment(loader=loader)
-
- if apply_format_ts_filter:
- env.filters["format_ts"] = format_ts_filter
-
- if apply_mxc_to_http_filter and public_baseurl:
- env.filters["mxc_to_http"] = _create_mxc_to_http_filter(public_baseurl)
-
- templates = []
- for template_filename in template_filenames:
- template = env.get_template(template_filename)
- templates.append(template)
-
- return templates
-
-
-def _create_mxc_to_http_filter(public_baseurl):
- def mxc_to_http_filter(value, width, height, resize_method="crop"):
- if value[0:6] != "mxc://":
- return ""
-
- serverAndMediaId = value[6:]
- fragment = None
- if "#" in serverAndMediaId:
- (serverAndMediaId, fragment) = serverAndMediaId.split("#", 1)
- fragment = "#" + fragment
-
- params = {"width": width, "height": height, "method": resize_method}
- return "%s_matrix/media/v1/thumbnail/%s?%s%s" % (
- public_baseurl,
- serverAndMediaId,
- urllib.parse.urlencode(params),
- fragment or "",
- )
-
- return mxc_to_http_filter
|