from django.conf import settings from django.core.mail import EmailMultiAlternatives from django.template.loader import get_template from django.utils.html import strip_tags from input.models import TYPE_CHOICES from .attachments import collect_attachment_paths, attach_files __all__ = [ 'build_email', 'send_email', 'collect_attachment_paths', 'attach_files', 'send_decision_mail', 'send_staff_decision_mail', ] def build_email(template_name: str, context: dict, subject: str, *recipients: str, **kwargs): body = get_template(f'mails/{template_name}.txt').render(context) html = get_template(f'mails/{template_name}.html').render(context) kwargs.setdefault('from_email', settings.IF_EMAIL) kwargs['subject'] = subject kwargs['body'] = body kwargs['to'] = recipients email = EmailMultiAlternatives(**kwargs) email.attach_alternative(html, 'text/html') return email def send_email(template_name: str, context: dict, subject: str, *recipients: str, fail_silently=False, **kwargs): return build_email(template_name, context, subject, *recipients, **kwargs).send(fail_silently) def _type_labels(choice: str): """ Resolve the human-readable type label. Returns (HTML label, plain text label). """ html = TYPE_CHOICES.get(choice, choice) plain = strip_tags(html) return html, plain def _decision_context(obj, choice_code: str) -> dict: """ Build a minimal, consistent context for decision mails (applicant & staff). Also exposes the full project object as 'project' for template access. """ type_html, type_plain = _type_labels(choice_code) realname = getattr(obj, 'realname', '') or getattr(obj, 'email', '') return { 'data': { 'realname': realname, 'type_label': type_html, 'type_label_plain': type_plain, 'name': getattr(obj, 'name', None), }, 'project': obj, } def send_decision_mail(obj, choice_code: str, granted: bool) -> None: """ Send a decision email to the applicant after manual approval/denial. Uses: input/approval_granted.(txt|html) or input/approval_denied.(txt|html) """ recipient = getattr(obj, 'email', None) if not recipient: return # no recipient -> skip ctx = _decision_context(obj, choice_code) template_suffix = 'granted' if granted else 'denied' project_name = getattr(obj, 'name', None) or '(ohne Projektnamen)' decision_word = 'bewilligt' if granted else 'abgelehnt' subject = f'Deine Förderanfrage „{project_name}“ – {decision_word}' return send_email(f'approval_{template_suffix}', ctx, subject, recipient) def send_staff_decision_mail(obj, choice_code: str, granted: bool) -> None: """ Send a decision email to the internal team (staff) after approval/denial. Uses: input/approval_granted_staff.(txt|html) or input/approval_denied_staff.(txt|html) """ ctx = _decision_context(obj, choice_code) template_suffix = 'granted' if granted else 'denied' project_name = getattr(obj, 'name', None) or '(ohne Projektnamen)' decision_word = 'bewilligt' if granted else 'abgelehnt' subject = f'Entscheidung: {project_name} ({decision_word})' return send_email(f'approval_{template_suffix}_staff', ctx, subject, settings.IF_EMAIL)