From f5c9b0c76c2a5b23b9f6e13a9b6068f16b74d792 Mon Sep 17 00:00:00 2001
From: Oliver Zander
Date: Mon, 10 Nov 2025 17:51:24 +0100
Subject: [PATCH] WM-18: improved mails & added full form data
---
input/templates/mails/if_mail.html | 62 ++++------------
input/templates/mails/if_mail.txt | 56 ++------------
input/templates/mails/ifg_volunteer_mail.html | 31 ++------
input/templates/mails/ifg_volunteer_mail.txt | 45 +++++------
input/views.py | 74 ++++++++++++++++---
5 files changed, 111 insertions(+), 157 deletions(-)
diff --git a/input/templates/mails/if_mail.html b/input/templates/mails/if_mail.html
index 31237ba..a77bbb8 100755
--- a/input/templates/mails/if_mail.html
+++ b/input/templates/mails/if_mail.html
@@ -1,60 +1,26 @@
-
+
Hallo Team Community-Konferenzen & Förderung,
es gibt eine neue Anfrage von {{ data.realname }}.
-{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ data.type_label|striptags }}
+{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ type_label }}
-{% if data.choice in data.grant %}
-Vorraussichtliche Kosten: {{data.cost}}
-Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
-Adressenbestandteil: {{data.address}}
{% endif %} {% if data.choice == 'BIB' %}
-Bibliothek: {{data.library}}
-Dauer: {{data.duration}}
{% elif data.choice == 'ELIT' %}
-Datenbank: {{data.library}}
-Dauer: {{data.duration}}
{% elif data.choice == 'SOFT' %}
-Software: {{data.library}}
-Dauer: {{data.duration}}
{% elif data.choice == 'IFG'%}
-Anfrage-URL: {{data.url}}
{% elif data.choice == 'LIT'%}
-Info zum Werk: {{data.info}}
-Bezugsquelle: {{data.source}}
{% elif data.choice == 'MAIL'%}
-Adressenbestandteil frei gewählt: {{data.other}}
{% elif data.choice == 'VIS'%}
-Wikimedia-Projekt: {{data.project}}
-Persönliche Daten: {{data.data}}
-Variante: {{data.variant}}
-Sendungsadrese: {{data.send_to}}
{% endif %}
+
+ {% for label, value in form_data.items %}
+ {{ label }}: {{ value }}
+ {% endfor %}
+
-Zum Eintrag in der Förderdatenbank:
-{% if data.choice == 'BIB' %}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'ELIT'%}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'LIT'%}
-{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change
-{% elif data.choice == 'MAIL'%}
-{{data.url_prefix}}/admin/input/email/{{data.pk}}/change
-{% elif data.choice == 'IFG'%}
-{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change
-{% elif data.choice == 'LIST'%}
-{{data.url_prefix}}/admin/input/list/{{data.pk}}/change
-{% elif data.choice == 'TRAV'%}
-{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change
-{% elif data.choice == 'SOFT'%}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'VIS'%}
-{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change
+
Zum Eintrag in der Förderdatenbank: {{ urls.admin }}
+
+{% if urls.authorize %}
+ Zum Genehmigen hier klicken: {{ urls.authorize }}
{% endif %}
-
-Zum Genehmigen hier klicken:
- {{data.url_prefix}}{% url 'authorize' data.choice data.pk %}
-
-
-Zum Ablehnen hier klicken:
- {{data.url_prefix}}{% url 'deny' data.choice data.pk %}
-
+{% if urls.deny %}
+ Zum Ablehnen hier klicken: {{ urls.deny }}
+{% endif %}
diff --git a/input/templates/mails/if_mail.txt b/input/templates/mails/if_mail.txt
index 2e0c287..61c18f5 100755
--- a/input/templates/mails/if_mail.txt
+++ b/input/templates/mails/if_mail.txt
@@ -1,52 +1,12 @@
-Hallo Team Communitys und Engagement,
+Hallo Team Community-Konferenzen & Förderung,
-es gab einen neuen Antrag von {{data.realname}}.
+es gibt eine neue Anfrage von {{ data.realname }}.
-Der Nutzer mit dem Username {{data.username}} ({{data.email}}) fragt ein_e {{data.type_label|striptags}} an.
-{% if data.choice in data.grant %}
-Vorraussichtliche Kosten: {{data.cost}}
-Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
-Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
-Bibliothek: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
-Datenbank: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
-Software: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
-Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
-Info zum Werk: {{data.info}}
-Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
-Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
-Wikimedia-Projekt: {{data.project}}
-Persönliche Daten: {{data.data}}
-Variante: {{data.variant}}
-Sendungsadrese: {{data.send_to}} {% endif %}
+{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ type_label }}
-Zum Eintrag in der Förderdatenbank:
-{% if data.choice == 'BIB' %}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'ELIT'%}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'LIT'%}
-{{data.url_prefix}}/admin/input/literature/{{data.pk}}/change
-{% elif data.choice == 'MAIL'%}
-{{data.url_prefix}}/admin/input/email/{{data.pk}}/change
-{% elif data.choice == 'IFG'%}
-{{data.url_prefix}}/admin/input/ifg/{{data.pk}}/change
-{% elif data.choice == 'LIST'%}
-{{data.url_prefix}}/admin/input/list/{{data.pk}}/change
-{% elif data.choice == 'TRAV'%}
-{{data.url_prefix}}/admin/input/travel/{{data.pk}}/change
-{% elif data.choice == 'SOFT'%}
-{{data.url_prefix}}/admin/input/library/{{data.pk}}/change
-{% elif data.choice == 'VIS'%}
-{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change
-{% endif %}
+{% for label, value in form_data.items %}{{ label }}: {{ value }}
+{% endfor %}
-
-Zum Genehmigen hier klicken: {{data.url_prefix}}{% url 'authorize' data.choice data.pk %}
-
-Zu Ablehnen hier klicken: {{data.url_prefix}}{% url 'deny' data.choice data.pk %}
-
-Stets zu Diensten, Deine Förderdatenbank
+Zum Eintrag in der Förderdatenbank: {{ urls.admin }}
+{% if urls.authorize %}Zum Genehmigen hier klicken: {{ urls.authorize }}{% endif %}
+{% if urls.deny %}Zum Ablehnen hier klicken: {{ urls.deny }}{% endif %}
diff --git a/input/templates/mails/ifg_volunteer_mail.html b/input/templates/mails/ifg_volunteer_mail.html
index 5652db1..308cb9f 100755
--- a/input/templates/mails/ifg_volunteer_mail.html
+++ b/input/templates/mails/ifg_volunteer_mail.html
@@ -1,29 +1,14 @@
-
+
-Hallo {{ data.username|default:data.realname }},
+Hallo {{ applicant_name }},
-vielen Dank für deine Anfrage ({{ data.type_label|striptags }}), die bei uns eingegangen ist.
+vielen Dank für deine Anfrage ({{ type_label }}), die bei uns eingegangen ist.
Dies ist eine automatisch generierte E-Mail. Im Folgenden findest du deine Formulareingaben nochmals zu deiner Übersicht:
-{% if data.choice in data.grant %}
-Vorraussichtliche Kosten: {{data.cost}}
-Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
-Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
-Bibliothek: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
-Datenbank: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
-Software: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
-Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
-Info zum Werk: {{data.info}}
-Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
-Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
-Wikimedia-Projekt: {{data.project}}
-Persönliche Daten: {{data.data}}
-Variante: {{data.variant}}
-Sendungsadrese: {{data.send_to}} {% endif %}
+
+{% for label, value in form_data.items %}
+{{ label }}: {{ value }}
+{% endfor %}
Das Team Community-Konferenzen & Förderung wird sich um deine Anfrage kümmern und sich in den nächsten Tagen bei dir melden. Wenn du Fragen hast, wende dich gern jederzeit an community@wikimedia.de.
@@ -44,4 +29,4 @@ Sendungsadrese: {{data.send_to}} {% endif %}
Datenschutzerklärung:
Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung .
-
\ No newline at end of file
+
diff --git a/input/templates/mails/ifg_volunteer_mail.txt b/input/templates/mails/ifg_volunteer_mail.txt
index 976954d..9e15437 100755
--- a/input/templates/mails/ifg_volunteer_mail.txt
+++ b/input/templates/mails/ifg_volunteer_mail.txt
@@ -1,29 +1,22 @@
-Hallo {{data.realname}},
+Hallo {{ applicant_name }},
-wir haben Deine Anfrage ({{data.type_label|striptags}}) erhalten.
-{% if data.choice in data.grant %}
-Vorraussichtliche Kosten: {{data.cost}}
-Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
-Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
-Bibliothek: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
-Datenbank: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
-Software: {{data.library}}
-Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
-Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
-Info zum Werk: {{data.info}}
-Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
-Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
-Wikimedia-Projekt: {{data.project}}
-Persönliche Daten: {{data.data}}
-Variante: {{data.variant}}
-Sendungsadrese: {{data.send_to}} {% endif %}
+vielen Dank für deine Anfrage ({{type_label}}), die bei uns eingegangen ist.
-Das Team Comunitys und Engagement wird sich um die Bearbeitung deiner Anfrage kümmern
-und sich in den nächsten Tagen bei dir melden. Solltest du Rückfragen haben,
-wende dich gern an community@wikimedia.de.
+{% for label, value in form_data.items %}{{ label }}: {{ value }}
+{% endfor %}
-Viele Grüße, dein freundliches aber komplett unmenschliches automatisches
-Formularbeantwortungssystem.
+Das Team Community-Konferenzen & Förderung wird sich um deine Anfrage kümmern und sich in den nächsten Tagen bei dir melden. Wenn du Fragen hast, wende dich gern jederzeit an community@wikimedia.de.
+
+--
+
+Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
+Zentrale: +49 30 5771162-0
+https://wikimedia.de
+
+Unsere Vision ist eine Welt, in der alle Menschen am Wissen der Menschheit teilhaben, es nutzen und mehren können. Helfen Sie uns dabei!
+https://spenden.wikimedia.de
+
+Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Charlottenburg, VR 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. Geschäftsführende Vorständin: Franziska Heine.
+
+Datenschutzerklärung:
+Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung (https://www.wikimedia.de/datenschutz/).
diff --git a/input/views.py b/input/views.py
index 912bc26..2fb898f 100755
--- a/input/views.py
+++ b/input/views.py
@@ -1,9 +1,16 @@
+import datetime
+
from dataclasses import dataclass
from smtplib import SMTPException
from typing import Optional
+from urllib.parse import urljoin
+from django.forms import ChoiceField, BoundField, Field
from django.shortcuts import render, redirect
from django.http import HttpResponse, Http404
+from django.urls import reverse
+from django.utils.choices import flatten_choices
+from django.utils.formats import date_format
from django.utils.functional import cached_property
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.safestring import mark_safe
@@ -14,6 +21,7 @@ from django.views.generic import TemplateView
from django.views.generic.edit import FormView
from django.utils.html import strip_tags
+from input.utils.admin import admin_url_name
from input.utils.mail import build_email, collect_and_attach
from .forms import (
@@ -43,6 +51,7 @@ from .models import (
TYPE_SOFT,
TYPE_TRAV,
TYPE_VIS,
+ Project,
)
HELP_TEXTS = {
@@ -286,19 +295,9 @@ class ApplicationView(FormView):
def send_mail(self, obj, data):
# Prepare minimal mail context and send mails
- type_label_html = self.type_info.label
- type_label_plain = strip_tags(type_label_html)
-
- data['pk'] = obj.pk
- data['url_prefix'] = settings.EMAIL_URL_PREFIX
- data['type_label'] = type_label_html
-
- context = {'data': data}
-
- applicant_name = self.get_recipient_name(obj, data)
+ context = self.get_email_context(obj, data)
applicant_subject = 'Deine Förderanfrage bei Wikimedia Deutschland'
-
- staff_subject = f'Anfrage {type_label_plain} von {applicant_name}'
+ staff_subject = 'Anfrage {type_label} von {applicant_name}'.format(**context)
try:
self.send_email('applicant', 'ifg_volunteer_mail', applicant_subject, data['email'], context)
@@ -310,6 +309,57 @@ class ApplicationView(FormView):
obj.delete()
return HttpResponse('Error in sending mails (probably wrong address?). Data not saved!')
+ def get_email_context(self, obj, data):
+ return {
+ 'data': data,
+ 'urls': self.get_urls(obj),
+ 'form_data': self.get_form_data(obj, data),
+ 'applicant_name': self.get_recipient_name(obj, data),
+ 'type_label': self.sanitize_label(self.type_info.label),
+ }
+
+ def get_urls(self, obj, **urls):
+ urls['admin'] = self.get_absolute_url(admin_url_name(obj, 'change'), obj.id)
+
+ if isinstance(obj, Project):
+ urls['authorize'] = urls['deny'] = None
+ else:
+ urls['authorize'] = self.get_absolute_url('authorize', self.type_info.code, obj.id)
+ urls['deny'] = self.get_absolute_url('deny', self.type_info.code, obj.id)
+
+ return urls
+
+ @staticmethod
+ def get_absolute_url(view, *args):
+ return urljoin(settings.EMAIL_URL_PREFIX, reverse(view, args=args))
+
+ def get_form_data(self, obj, data):
+ return {
+ self.sanitize_label(field.label): self.format_value(field.field, field.initial)
+ for field in self.type_info.form_class(initial=data)
+ }
+
+ @staticmethod
+ def sanitize_label(label: str):
+ label = strip_tags(label)
+ words = str.split(label)
+
+ return ' '.join(words)
+
+ @staticmethod
+ def format_value(field: Field, value):
+ if isinstance(field, ChoiceField):
+ choices = flatten_choices(field.choices)
+ value = dict(choices).get(value, value)
+ elif isinstance(value, bool):
+ value = '✓' if value else '✗'
+ elif isinstance(value, datetime.date):
+ value = date_format(value)
+ elif value in field.empty_values:
+ value = '–'
+
+ return value
+
def send_email(self, kind, template_name, subject, recipient, context, *, fail_silently=False):
email = build_email(template_name, context, subject, recipient)