2018-05-09 20:57:01 +02:00
|
|
|
import configparser
|
2020-06-11 00:54:34 +02:00
|
|
|
import logging
|
|
|
|
from typing import List
|
2017-10-25 01:54:43 +02:00
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
from django.core.mail import EmailMultiAlternatives
|
2021-01-28 19:28:34 +01:00
|
|
|
from django.core.mail.backends.smtp import EmailBackend
|
2017-10-25 01:54:43 +02:00
|
|
|
from django.template import loader
|
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2017-11-27 14:35:36 +01:00
|
|
|
def get_forward_address() -> str:
|
2017-10-25 01:58:05 +02:00
|
|
|
config = configparser.ConfigParser()
|
|
|
|
config.read(settings.FORWARD_ADDRESS_CONFIG_FILE)
|
|
|
|
try:
|
|
|
|
return config.get("DEV_EMAIL", "forward_address")
|
2018-05-24 16:41:34 +02:00
|
|
|
except (configparser.NoSectionError, configparser.NoOptionError):
|
2017-10-25 01:58:05 +02:00
|
|
|
return ""
|
|
|
|
|
2017-11-27 14:35:36 +01:00
|
|
|
def set_forward_address(forward_address: str) -> None:
|
2017-10-25 01:58:05 +02:00
|
|
|
config = configparser.ConfigParser()
|
|
|
|
config.read(settings.FORWARD_ADDRESS_CONFIG_FILE)
|
|
|
|
|
|
|
|
if not config.has_section("DEV_EMAIL"):
|
|
|
|
config.add_section("DEV_EMAIL")
|
|
|
|
config.set("DEV_EMAIL", "forward_address", forward_address)
|
|
|
|
|
|
|
|
with open(settings.FORWARD_ADDRESS_CONFIG_FILE, "w") as cfgfile:
|
2019-01-31 14:32:37 +01:00
|
|
|
config.write(cfgfile)
|
2017-10-25 01:58:05 +02:00
|
|
|
|
2021-01-28 19:28:34 +01:00
|
|
|
class EmailLogBackEnd(EmailBackend):
|
2017-10-27 13:03:15 +02:00
|
|
|
def log_email(self, email: EmailMultiAlternatives) -> None:
|
2017-10-25 01:54:43 +02:00
|
|
|
"""Used in development to record sent emails in a nice HTML log"""
|
|
|
|
html_message = 'Missing HTML message'
|
|
|
|
if len(email.alternatives) > 0:
|
|
|
|
html_message = email.alternatives[0][0]
|
|
|
|
|
|
|
|
context = {
|
|
|
|
'subject': email.subject,
|
|
|
|
'from_email': email.from_email,
|
2020-07-14 08:41:10 +02:00
|
|
|
'reply_to': email.reply_to,
|
2017-10-25 01:54:43 +02:00
|
|
|
'recipients': email.to,
|
|
|
|
'body': email.body,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
'html_message': html_message,
|
2017-10-25 01:54:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
new_email = loader.render_to_string('zerver/email.html', context)
|
|
|
|
|
|
|
|
# Read in the pre-existing log, so that we can add the new entry
|
|
|
|
# at the top.
|
|
|
|
try:
|
2020-04-09 21:51:58 +02:00
|
|
|
with open(settings.EMAIL_CONTENT_LOG_PATH) as f:
|
2017-10-25 01:54:43 +02:00
|
|
|
previous_emails = f.read()
|
|
|
|
except FileNotFoundError:
|
|
|
|
previous_emails = ""
|
|
|
|
|
|
|
|
with open(settings.EMAIL_CONTENT_LOG_PATH, "w+") as f:
|
|
|
|
f.write(new_email + previous_emails)
|
|
|
|
|
2021-01-28 19:28:34 +01:00
|
|
|
@staticmethod
|
|
|
|
def prepare_email_messages_for_forwarding(email_messages: List[EmailMultiAlternatives]) -> None:
|
|
|
|
localhost_email_images_base_uri = settings.ROOT_DOMAIN_URI + '/static/images/emails'
|
|
|
|
czo_email_images_base_uri = 'https://chat.zulip.org/static/images/emails'
|
|
|
|
|
|
|
|
for email_message in email_messages:
|
|
|
|
html_alternative = list(email_message.alternatives[0])
|
|
|
|
# Here, we replace the email addresses used in development
|
|
|
|
# with chat.zulip.org, so that web email providers like Gmail
|
|
|
|
# will be able to fetch the illustrations used in the emails.
|
|
|
|
html_alternative[0] = html_alternative[0].replace(localhost_email_images_base_uri, czo_email_images_base_uri)
|
|
|
|
email_message.alternatives[0] = tuple(html_alternative)
|
|
|
|
|
|
|
|
email_message.to = [get_forward_address()]
|
|
|
|
|
2017-10-27 13:03:15 +02:00
|
|
|
def send_messages(self, email_messages: List[EmailMultiAlternatives]) -> int:
|
2021-01-28 19:28:34 +01:00
|
|
|
num_sent = len(email_messages)
|
|
|
|
if get_forward_address():
|
|
|
|
self.prepare_email_messages_for_forwarding(email_messages)
|
|
|
|
num_sent = super().send_messages(email_messages)
|
|
|
|
|
|
|
|
if settings.DEVELOPMENT_LOG_EMAILS:
|
|
|
|
for email in email_messages:
|
2018-08-06 11:40:31 +02:00
|
|
|
self.log_email(email)
|
|
|
|
email_log_url = settings.ROOT_DOMAIN_URI + "/emails"
|
2020-05-02 08:44:14 +02:00
|
|
|
logging.info("Emails sent in development are available at %s", email_log_url)
|
2021-01-28 19:28:34 +01:00
|
|
|
return num_sent
|