from django.views.generic.base import ContextMixin from django.template.loader import render_to_string from django.template.exceptions import TemplateDoesNotExist from django.core.mail import EmailMultiAlternatives from django.conf import settings from html.parser import HTMLParser from bs4 import BeautifulSoup class MailView(ContextMixin): def __init__(self, template_name=None, html_template_name=None, text_template_name=None): self.html_template_name = html_template_name self.text_template_name = text_template_name if template_name: self._template_name = template_name if len(template_name.split("/")[-1].split(".")[-1] in ("html", "txt")): basename = template_name.rsplit(".", 1)[0] else: basename = template_name for ext in ("html", "txt"): try: path = f"{basename}.{ext}" render_to_string(path) if ext == "html": self.html_template_name = self.html_template_name or path else: self.text_template_name = self.text_template_name or path except TemplateDoesNotExist: pass def render_to_html(self, **kwargs): if self.html_template_name: context = self.get_context_data(**kwargs) return render_to_string(self.html_template_name, context) else: return None def render_to_text(self, from_html=False, **kwargs): if self.text_template_name: context = self.get_context_data(**kwargs) return render_to_string(self.text_template_name, context) else: if from_html and (html := self.render_to_html(**kwargs)): return BeautifulSoup(html).get_text() return None def send(self, subject, recipient, context={}, attachments=[], sender=None, cc=[], bcc=[], text_from_html=False): text = self.render_to_text(text_from_html, **context) email = EmailMultiAlternatives(subject, text, sender, [recipient], cc=cc, bcc=bcc + DEFAULT_BCC_EMAILS, attachments=attachments) if html := self.render_to_html(**context): email.attach_alternative(html, "text/html") email.send()