Anna Sirota
cc900979d6
Based on the proposal #93 Email subjects change to the following: ``` Add-on approved: "Genuinely Disgusting" New comment on Add-on "Genuinely Disgusting" Add-on rated: "Genuinely Disgusting" Add-on reported: "Genuinely Disgusting" Add-on rating reported: "Genuinely Disgusting" Add-on changes requested: "Genuinely Disgusting" Add-on review requested: "Genuinely Disgusting" ``` Notification emails can also be viewed in the admin `Email previews` section (with fake objects constructed and passed into email template contexts). Indicating why the email was sent is not in this change because we currently don't store why **precisely** (can only guess it's either because of `moderators` group or extension follow, the state of either can change after the notification was generated). This can be part of the `Notification` records however, after that the reason can be included in the email. Reviewed-on: #96 Reviewed-by: Oleg-Komarov <oleg-komarov@noreply.localhost>
78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
"""Utilities for rendering email templates."""
|
|
from typing import List, Tuple, Dict, Any
|
|
import logging
|
|
|
|
from django.conf import settings
|
|
from django.core.mail import get_connection, EmailMultiAlternatives
|
|
from django.template import loader, TemplateDoesNotExist
|
|
|
|
from utils import absolute_url, html_to_text
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
def is_noreply(email: str) -> bool:
|
|
"""Return True if the email address is a no-reply address."""
|
|
return email.startswith('noreply@') or email.startswith('no-reply@')
|
|
|
|
|
|
def get_template_context() -> Dict[str, str]:
|
|
"""Return additional context for use in an email template."""
|
|
return {
|
|
'site_url': absolute_url('extensions:home'),
|
|
'profile_url': absolute_url('users:my-profile'),
|
|
'notifications_url': absolute_url('notifications:notifications'),
|
|
'DEFAULT_REPLY_TO_EMAIL': settings.DEFAULT_REPLY_TO_EMAIL,
|
|
}
|
|
|
|
|
|
def construct_email(email_name: str, context: Dict[str, Any]) -> Tuple[str, str, str]:
|
|
"""Construct an email message.
|
|
|
|
If plain text template is not found, text version will be generated from the HTML of the email.
|
|
|
|
:return: tuple (html, text, subject)
|
|
"""
|
|
context.update(**get_template_context())
|
|
base_path = 'emails'
|
|
subj_tmpl, html_tmpl, txt_tmpl = (
|
|
f'{base_path}/{email_name}_subject.txt',
|
|
f'{base_path}/{email_name}.html',
|
|
f'{base_path}/{email_name}.txt',
|
|
)
|
|
|
|
subject: str = loader.render_to_string(subj_tmpl, context)
|
|
context['subject'] = subject.strip()
|
|
|
|
email_body_html = loader.render_to_string(html_tmpl, context)
|
|
try:
|
|
email_body_txt = loader.render_to_string(txt_tmpl, context)
|
|
except TemplateDoesNotExist:
|
|
# Generate plain text content from the HTML one
|
|
email_body_txt = html_to_text(email_body_html)
|
|
return email_body_html, email_body_txt, context['subject']
|
|
|
|
|
|
def construct_and_send_email(
|
|
email_name: str, context: Dict[str, Any], recipient_list: List[str]
|
|
) -> int:
|
|
"""Construct an email message and send it.
|
|
|
|
:return: int
|
|
"""
|
|
email_body_html, email_body_txt, subject = construct_email(email_name, context)
|
|
|
|
connection = get_connection(fail_silently=False)
|
|
mail = EmailMultiAlternatives(
|
|
context['subject'],
|
|
email_body_txt,
|
|
from_email=None, # just use the configured default From-address.
|
|
to=recipient_list,
|
|
connection=connection,
|
|
reply_to=[settings.DEFAULT_REPLY_TO_EMAIL],
|
|
)
|
|
mail.attach_alternative(email_body_html, 'text/html')
|
|
|
|
return mail.send()
|