forked from beba/foerderbarometer
Merge branch 'WM-4' into 'cosmocode'
[WM-4] (3) E-Mail Versand Closes WM-4 See merge request wikimedia/foerderbarometer!9
This commit is contained in:
commit
c751a9fc37
|
|
@ -0,0 +1,33 @@
|
||||||
|
TYPE_ALL = 'ALL'
|
||||||
|
|
||||||
|
TYPE_BIB = 'BIB' # Bibliotheksstipendium
|
||||||
|
TYPE_ELIT = 'ELIT' # eLiteraturstipendium
|
||||||
|
TYPE_SOFT = 'SOFT' # Softwarestipendium
|
||||||
|
TYPE_MAIL = 'MAIL' # E-Mail-Adresse
|
||||||
|
TYPE_IFG = 'IFG' # Kostenübernahme IFG-Anfrage
|
||||||
|
TYPE_LIT = 'LIT' # Literaturstipendium
|
||||||
|
TYPE_LIST = 'LIST' # Mailingliste
|
||||||
|
TYPE_TRAV = 'TRAV' # Reisekosten
|
||||||
|
TYPE_VIS = 'VIS' # Visitenkarten
|
||||||
|
TYPE_PROJ = 'PROJ' # Projektförderung
|
||||||
|
|
||||||
|
TYPES = [
|
||||||
|
TYPE_BIB,
|
||||||
|
TYPE_ELIT,
|
||||||
|
TYPE_SOFT,
|
||||||
|
TYPE_MAIL,
|
||||||
|
TYPE_IFG,
|
||||||
|
TYPE_LIT,
|
||||||
|
TYPE_LIST,
|
||||||
|
TYPE_TRAV,
|
||||||
|
TYPE_VIS,
|
||||||
|
TYPE_PROJ,
|
||||||
|
]
|
||||||
|
|
||||||
|
RECIPIENT_APPLICANT = 'applicant'
|
||||||
|
RECIPIENT_STAFF = 'staff'
|
||||||
|
|
||||||
|
RECIPIENTS = [
|
||||||
|
RECIPIENT_APPLICANT,
|
||||||
|
RECIPIENT_STAFF,
|
||||||
|
]
|
||||||
|
|
@ -6,6 +6,8 @@ from dotenv import load_dotenv
|
||||||
|
|
||||||
from input.utils.settings import env, password_validators
|
from input.utils.settings import env, password_validators
|
||||||
|
|
||||||
|
from .constants import *
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).parents[1]
|
BASE_DIR = Path(__file__).parents[1]
|
||||||
|
|
||||||
load_dotenv(BASE_DIR / '.env')
|
load_dotenv(BASE_DIR / '.env')
|
||||||
|
|
@ -165,3 +167,26 @@ NUTZUNGSBEDINGUNGEN_MAILINGLISTEN = 'static/input/nutzungsbedingungen-mailinglis
|
||||||
NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM = 'static/input/nutzungsbedingungen-literaturstipendium.pdf'
|
NUTZUNGSBEDINGUNGEN_LITERATURSTIPENDIUM = 'static/input/nutzungsbedingungen-literaturstipendium.pdf'
|
||||||
NUTZUNGSBEDINGUNGEN_OTRS = 'static/input/2025_Nutzungsvereinbarung_OTRS.docx.pdf'
|
NUTZUNGSBEDINGUNGEN_OTRS = 'static/input/2025_Nutzungsvereinbarung_OTRS.docx.pdf'
|
||||||
NUTZUNGSBEDINGUNGEN_VISITENKARTEN = 'static/input/nutzungsbedingungen-visitenkarten.pdf'
|
NUTZUNGSBEDINGUNGEN_VISITENKARTEN = 'static/input/nutzungsbedingungen-visitenkarten.pdf'
|
||||||
|
|
||||||
|
MAIL_ATTACHMENT_CACHE_DIR = env('MAIL_ATTACHMENT_CACHE_DIR', BASE_DIR / 'var' / 'mail-attachments')
|
||||||
|
MAIL_ATTACHMENT_TTL_SECONDS = env('MAIL_ATTACHMENT_TTL_SECONDS', 24 * 60 * 60)
|
||||||
|
MAIL_ATTACHMENT_URLS = {
|
||||||
|
RECIPIENT_APPLICANT: {
|
||||||
|
TYPE_ALL: [],
|
||||||
|
TYPE_VIS: [
|
||||||
|
'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-visitenkarten.pdf',
|
||||||
|
],
|
||||||
|
TYPE_MAIL: [
|
||||||
|
'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-mail.pdf',
|
||||||
|
],
|
||||||
|
TYPE_LIST: [
|
||||||
|
'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-mailinglisten.pdf',
|
||||||
|
],
|
||||||
|
TYPE_LIT: [
|
||||||
|
'https://foerderung.wikimedia.de/static/input/nutzungsbedingungen-literaturstipendium.pdf',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
RECIPIENT_STAFF: {
|
||||||
|
TYPE_ALL: [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
from input.utils.mail import send_decision_mails
|
||||||
|
|
||||||
from .forms import BaseProjectForm
|
from .forms import BaseProjectForm
|
||||||
from .models import (
|
from .models import (
|
||||||
Account,
|
Account,
|
||||||
|
|
@ -22,6 +24,7 @@ from .models import (
|
||||||
BusinessCard,
|
BusinessCard,
|
||||||
List,
|
List,
|
||||||
Literature,
|
Literature,
|
||||||
|
TYPE_PROJ,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -83,7 +86,7 @@ class ProjectAdminForm(BaseProjectForm):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
for field, model in self.categories.items():
|
for field, model in self.categories.items():
|
||||||
if self.initial[f'{field}_other']:
|
if self.initial.get(f'{field}_other'):
|
||||||
self.initial[field] = [*self.initial[field], model.other]
|
self.initial[field] = [*self.initial[field], model.other]
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
@ -100,8 +103,7 @@ class ProjectAdminForm(BaseProjectForm):
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Project)
|
class BaseProjectAdmin(admin.ModelAdmin):
|
||||||
class ProjectAdmin(admin.ModelAdmin):
|
|
||||||
save_as = True
|
save_as = True
|
||||||
form = ProjectAdminForm
|
form = ProjectAdminForm
|
||||||
search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status', 'end_quartal')
|
search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status', 'end_quartal')
|
||||||
|
|
@ -158,21 +160,42 @@ class ProjectAdmin(admin.ModelAdmin):
|
||||||
class Media:
|
class Media:
|
||||||
js = ('dropdown/js/otrs_link.js',)
|
js = ('dropdown/js/otrs_link.js',)
|
||||||
|
|
||||||
granted = True
|
granted: bool
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
return super().get_queryset(request).filter(granted=self.granted)
|
return super().get_queryset(request).filter(granted=self.granted)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Project)
|
||||||
|
class ProjectAdmin(BaseProjectAdmin):
|
||||||
|
granted = True
|
||||||
|
|
||||||
|
|
||||||
@admin.register(ProjectRequest)
|
@admin.register(ProjectRequest)
|
||||||
class ProjectRequestAdmin(ProjectAdmin):
|
class ProjectRequestAdmin(BaseProjectAdmin):
|
||||||
granted = None
|
granted = None
|
||||||
|
|
||||||
|
def save_model(self, request, obj: ProjectRequest, form: ProjectAdminForm, change: bool):
|
||||||
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
if obj.granted is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
transaction.on_commit(lambda: send_decision_mails(obj))
|
||||||
|
|
||||||
|
return obj.granted
|
||||||
|
|
||||||
|
|
||||||
@admin.register(ProjectDeclined)
|
@admin.register(ProjectDeclined)
|
||||||
class ProjectDeclinedAdmin(ProjectAdmin):
|
class ProjectDeclinedAdmin(BaseProjectAdmin):
|
||||||
granted = False
|
granted = False
|
||||||
|
|
||||||
|
def has_add_permission(self, request):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@admin.register(BusinessCard)
|
@admin.register(BusinessCard)
|
||||||
class BusinessCardAdmin(RequestURLBeforeInternNotesMixin, admin.ModelAdmin):
|
class BusinessCardAdmin(RequestURLBeforeInternNotesMixin, admin.ModelAdmin):
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ from datetime import date, timedelta
|
||||||
|
|
||||||
from django.core.management import CommandError
|
from django.core.management import CommandError
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.core.mail import BadHeaderError
|
from django.core.mail import BadHeaderError
|
||||||
from django.core.mail import EmailMultiAlternatives
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from input.models import Project, Library, HonoraryCertificate, Travel, Email,\
|
from input.models import Project, Library, HonoraryCertificate, Travel, Email,\
|
||||||
BusinessCard, List, IFG, Literature
|
BusinessCard, List, IFG, Literature
|
||||||
|
from input.utils.mail import send_email
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
''' mails will be sent here:
|
''' mails will be sent here:
|
||||||
|
|
@ -34,15 +34,11 @@ class Command(BaseCommand):
|
||||||
'name': name,
|
'name': name,
|
||||||
'pid': pid,
|
'pid': pid,
|
||||||
'SURVEY_PREFIX': settings.SURVEY_PREFIX, }
|
'SURVEY_PREFIX': settings.SURVEY_PREFIX, }
|
||||||
txt_mail_template = get_template('input/survey_mail.txt')
|
|
||||||
html_mail_template = get_template('input/survey_mail.html')
|
subject = 'Dein Feedback zur Förderung durch Wikimedia Deutschland'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', settings.IF_EMAIL, email
|
send_email('survey_mail', context, subject, email, bcc=[settings.SURVEY_EMAIL])
|
||||||
text_content = txt_mail_template.render(context)
|
|
||||||
html_content = html_mail_template.render(context)
|
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to], bcc=[settings.SURVEY_EMAIL])
|
|
||||||
msg.attach_alternative(html_content, "text/html")
|
|
||||||
msg.send()
|
|
||||||
#print('survey mail would have been send')
|
#print('survey mail would have been send')
|
||||||
|
|
||||||
#survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland',
|
#survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland',
|
||||||
|
|
@ -70,21 +66,14 @@ class Command(BaseCommand):
|
||||||
.exclude(end_mail_send = True)\
|
.exclude(end_mail_send = True)\
|
||||||
.filter(mail_state = 'NONE')
|
.filter(mail_state = 'NONE')
|
||||||
|
|
||||||
txt_mail_template = get_template('input/if_end_of_project.txt')
|
subject = 'Projektende erreicht'
|
||||||
html_mail_template = get_template('input/if_end_of_project.html')
|
recipient = settings.IF_EMAIL
|
||||||
|
|
||||||
|
|
||||||
for project in old:
|
for project in old:
|
||||||
context = {'project': project}
|
context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX}
|
||||||
context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, settings.IF_EMAIL
|
send_email('if_end_of_project', context, subject, recipient)
|
||||||
text_content = txt_mail_template.render(context)
|
|
||||||
html_content = html_mail_template.render(context)
|
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
|
|
||||||
msg.attach_alternative(html_content, "text/html")
|
|
||||||
msg.send()
|
|
||||||
#print('end of project mail would have been sent')
|
#print('end of project mail would have been sent')
|
||||||
|
|
||||||
#send_mail('Projektende erreicht',
|
#send_mail('Projektende erreicht',
|
||||||
|
|
@ -110,33 +99,19 @@ class Command(BaseCommand):
|
||||||
approved_end = Project.objects.filter(status = 'END')\
|
approved_end = Project.objects.filter(status = 'END')\
|
||||||
.exclude(end_mail_send = True)\
|
.exclude(end_mail_send = True)\
|
||||||
.filter(mail_state = 'INF')
|
.filter(mail_state = 'INF')
|
||||||
txt_mail_template = get_template('input/if_end_of_project_approved.txt')
|
|
||||||
html_mail_template = get_template('input/if_end_of_project_approved.html')
|
|
||||||
|
|
||||||
txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt')
|
|
||||||
html_informMail_template = get_template('input/if_end_of_project_orginformed.html')
|
|
||||||
# send the mail to project.email, which would be the mail of the volunteer filling out the form
|
# send the mail to project.email, which would be the mail of the volunteer filling out the form
|
||||||
|
|
||||||
for project in approved_end:
|
for project in approved_end:
|
||||||
context = {'project': project}
|
context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX}
|
||||||
context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email
|
send_email('if_end_of_project_approved', context, 'Projektende erreicht', project.email)
|
||||||
text_content = txt_mail_template.render(context)
|
|
||||||
html_content = html_mail_template.render(context)
|
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
|
|
||||||
msg.attach_alternative(html_content, "text/html")
|
|
||||||
msg.send()
|
|
||||||
#print('if and of project approved mail would have been sent')
|
#print('if and of project approved mail would have been sent')
|
||||||
|
|
||||||
inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL
|
send_email('if_end_of_project_orginformed', context, 'Projektorganisator*in wurde informiert', settings.IF_EMAIL)
|
||||||
inform_text_content = txt_informMail_template.render(context)
|
|
||||||
inform_html_content = html_informMail_template.render(context)
|
|
||||||
inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to])
|
|
||||||
inform_msg.attach_alternative(html_content, "text/html")
|
|
||||||
inform_msg.send()
|
|
||||||
#print('if end of project orginformed mail would have been sent')
|
#print('if end of project orginformed mail would have been sent')
|
||||||
|
|
||||||
#send_mail('Projektende erreicht',
|
#send_mail('Projektende erreicht',
|
||||||
|
|
@ -168,25 +143,15 @@ class Command(BaseCommand):
|
||||||
.exclude(end_mail_send = True)\
|
.exclude(end_mail_send = True)\
|
||||||
.filter(mail_state = 'INF')
|
.filter(mail_state = 'INF')
|
||||||
|
|
||||||
html_mail_template = get_template('input/if_not_of_project_approved.html')
|
|
||||||
txt_mail_template = get_template('input/if_not_of_project_approved.txt')
|
|
||||||
|
|
||||||
txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt')
|
|
||||||
html_informMail_template = get_template('input/if_end_of_project_orginformed.html')
|
|
||||||
# send the mail to project.email, which would be the mail of the volunteer that filled out the form
|
# send the mail to project.email, which would be the mail of the volunteer that filled out the form
|
||||||
|
|
||||||
for project in approved_notHappened:
|
for project in approved_notHappened:
|
||||||
context = {'project': project}
|
context = {'project': project, 'URL_PREFIX': settings.EMAIL_URL_PREFIX}
|
||||||
context['URL_PREFIX'] = settings.EMAIL_URL_PREFIX
|
|
||||||
try:
|
|
||||||
subject, from_email, to = 'Projektende erreicht', settings.IF_EMAIL, project.email
|
|
||||||
text_content = txt_mail_template.render(context)
|
|
||||||
html_content = html_mail_template.render(context)
|
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
|
|
||||||
msg.attach_alternative(html_content, "text/html")
|
|
||||||
msg.send()
|
|
||||||
#print('if not of project approved end mail would have been sent')
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
send_email('if_not_of_project_approved', context, 'Projektende erreicht', project.email)
|
||||||
|
|
||||||
|
#print('if not of project approved end mail would have been sent')
|
||||||
|
|
||||||
#send_mail('Projektende erreicht',
|
#send_mail('Projektende erreicht',
|
||||||
# mail_template.render(context),
|
# mail_template.render(context),
|
||||||
|
|
@ -194,12 +159,8 @@ class Command(BaseCommand):
|
||||||
# [project.email],
|
# [project.email],
|
||||||
# fail_silently=False)
|
# fail_silently=False)
|
||||||
|
|
||||||
inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', settings.IF_EMAIL, settings.IF_EMAIL
|
send_email('if_end_of_project_orginformed', context, 'Projektorganisator*in wurde informiert', settings.IF_EMAIL)
|
||||||
inform_text_content = txt_informMail_template.render(context)
|
|
||||||
inform_html_content = html_informMail_template.render(context)
|
|
||||||
inform_msg = EmailMultiAlternatives(inform_subject, inform_text_content, inform_from_email, [inform_to])
|
|
||||||
inform_msg.attach_alternative(html_content, "text/html")
|
|
||||||
inform_msg.send()
|
|
||||||
#print('if not of project approved end mail orginformed would have been sent')
|
#print('if not of project approved end mail orginformed would have been sent')
|
||||||
|
|
||||||
#send_mail('Projektorganisator*in wurde informiert',
|
#send_mail('Projektorganisator*in wurde informiert',
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ from django.utils.functional import cached_property, classproperty
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
from foerderbarometer.constants import *
|
||||||
|
|
||||||
|
|
||||||
EMAIL_STATES = {
|
EMAIL_STATES = {
|
||||||
'NONE': 'noch keine Mail versendet',
|
'NONE': 'noch keine Mail versendet',
|
||||||
'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet',
|
'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet',
|
||||||
|
|
@ -403,17 +406,6 @@ def type_link(path, label):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
TYPE_BIB = 'BIB'
|
|
||||||
TYPE_ELIT = 'ELIT'
|
|
||||||
TYPE_MAIL = 'MAIL'
|
|
||||||
TYPE_IFG = 'IFG'
|
|
||||||
TYPE_LIT = 'LIT'
|
|
||||||
TYPE_LIST = 'LIST'
|
|
||||||
TYPE_TRAV = 'TRAV'
|
|
||||||
TYPE_SOFT = 'SOFT'
|
|
||||||
TYPE_VIS = 'VIS'
|
|
||||||
TYPE_PROJ = 'PROJ'
|
|
||||||
|
|
||||||
TYPE_CHOICES = {
|
TYPE_CHOICES = {
|
||||||
TYPE_BIB: type_link('Zugang_zu_Fachliteratur#Bibliotheksstipendium', 'Bibliotheksstipendium'),
|
TYPE_BIB: type_link('Zugang_zu_Fachliteratur#Bibliotheksstipendium', 'Bibliotheksstipendium'),
|
||||||
TYPE_ELIT: type_link('Zugang_zu_Fachliteratur#eLiteraturstipendium', 'eLiteraturstipendium'),
|
TYPE_ELIT: type_link('Zugang_zu_Fachliteratur#eLiteraturstipendium', 'eLiteraturstipendium'),
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
Hallo {{data.realname}},
|
|
||||||
<br><br>
|
|
||||||
wir haben Deine Anfrage ({{data.type_label|striptags}}) erhalten.<br>
|
|
||||||
{% if data.choice in data.grant %}<br>
|
|
||||||
Vorraussichtliche Kosten: {{data.cost}}<br>
|
|
||||||
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
|
|
||||||
Domain: <a href="{{data.domain}}">{{data.domain}}</a><br>
|
|
||||||
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}<br>
|
|
||||||
Bibliothek: {{data.library}}<br>
|
|
||||||
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}<br>
|
|
||||||
Datenbank: {{data.library}}<br>
|
|
||||||
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}<br>
|
|
||||||
Software: {{data.library}}<br>
|
|
||||||
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}<br>
|
|
||||||
Anfrage-URL: <a href="{{data.url}}">{{data.url}}</a> {% elif data.choice == 'LIT'%}<br>
|
|
||||||
Info zum Werk: {{data.info}}<br>
|
|
||||||
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}<br>
|
|
||||||
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}<br>
|
|
||||||
Wikimedia-Projekt: {{data.project}}<br>
|
|
||||||
Persönliche Daten: {{data.data}}<br>
|
|
||||||
Variante: {{data.variant}}<br>
|
|
||||||
Sendungsadrese: {{data.send_to}} {% endif %}<br>
|
|
||||||
<br><br>
|
|
||||||
Das Team Comunitys und Engagement wird sich um die Bearbeitung deiner Anfrage kümmern<br>
|
|
||||||
und sich in den nächsten Tagen bei dir melden. Solltest du Rückfragen haben,<br>
|
|
||||||
wende dich gern an <a href = "mailto: community@wikimedia.de">community@wikimedia.de</a>.<br>
|
|
||||||
<br><br>
|
|
||||||
Viele Grüße, dein freundliches aber komplett unmenschliches automatisches
|
|
||||||
Formularbeantwortungssystem.
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hallo {{ data.realname }},</p>
|
||||||
|
|
||||||
|
<p>Deine Förderanfrage {{project.name}} wurde leider abgelehnt.</p>
|
||||||
|
|
||||||
|
<p>Fragen? <a href="mailto:community@wikimedia.de">community@wikimedia.de</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
Hallo {{ data.realname }},
|
||||||
|
|
||||||
|
deine Förderanfrage {{project.name}} wurde leider abgelehnt.
|
||||||
|
|
||||||
|
Fragen? community@wikimedia.de
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hallo Team Community-Konferenzen & Förderung,</p>
|
||||||
|
|
||||||
|
<p>Die Förderanfrage {{project.name}} von {{ data.realname }} wurde abgelehnt.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Hallo Team Community-Konferenzen & Förderung,
|
||||||
|
|
||||||
|
die Förderanfrage {{project.name}} von {{ data.realname }} wurde abgelehnt.
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hallo {{ data.realname }},</p>
|
||||||
|
|
||||||
|
<p>Deine Förderanfrage {{project.name}} wurde bewilligt.</p>
|
||||||
|
|
||||||
|
<p>Das Team Community-Konferenzen & Förderung meldet sich bald bei dir.<br>
|
||||||
|
Fragen? <a href="mailto:community@wikimedia.de">community@wikimedia.de</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
Hallo {{ data.realname }},
|
||||||
|
|
||||||
|
deine Förderanfrage {{project.name}} wurde bewilligt.
|
||||||
|
|
||||||
|
Das Team Community-Konferenzen & Förderung meldet sich bald bei dir.
|
||||||
|
Fragen? community@wikimedia.de
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hallo Team Community-Konferenzen & Förderung,</p>
|
||||||
|
|
||||||
|
<p>Die Förderanfrage {{project.name}} von {{ data.realname }} wurde bewilligt.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Hallo Team Community-Konferenzen & Förderung,
|
||||||
|
|
||||||
|
die Förderanfrage {{project.name}} von {{ data.realname }} wurde bewilligt.
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
Hallo Team Communitys und Engagement,
|
<p>Hallo Team Community-Konferenzen & Förderung,</p>
|
||||||
<br><br>
|
|
||||||
es gab einen neuen Antrag von {{data.realname}}.
|
<p>es gibt eine neue Anfrage von {{ data.realname }}.</p>
|
||||||
<br><br>
|
|
||||||
Der Nutzer mit dem Username {{data.username}} ({{data.email}}) fragt ein_e {{data.type_label|striptags}} an.<br>
|
<p>{{ data.username|default:data.realname }} ({{ data.email }}) fragt an: {{ data.type_label|striptags }}</p>
|
||||||
|
|
||||||
{% if data.choice in data.grant %}<br>
|
{% if data.choice in data.grant %}<br>
|
||||||
Vorraussichtliche Kosten: {{data.cost}}<br>
|
Vorraussichtliche Kosten: {{data.cost}}<br>
|
||||||
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
|
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
|
||||||
|
|
@ -24,9 +25,8 @@ Wikimedia-Projekt: {{data.project}}<br>
|
||||||
Persönliche Daten: {{data.data}}<br>
|
Persönliche Daten: {{data.data}}<br>
|
||||||
Variante: {{data.variant}}<br>
|
Variante: {{data.variant}}<br>
|
||||||
Sendungsadrese: {{data.send_to}} <br> {% endif %}
|
Sendungsadrese: {{data.send_to}} <br> {% endif %}
|
||||||
<br><br>
|
|
||||||
|
|
||||||
Zum Eintrag in der Förderdatenbank:
|
<p>Zum Eintrag in der Förderdatenbank:
|
||||||
{% if data.choice == 'BIB' %}
|
{% if data.choice == 'BIB' %}
|
||||||
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
|
<a href="{{data.url_prefix}}/admin/input/library/{{data.pk}}/change">{{data.url_prefix}}/admin/input/library/{{data.pk}}/change</a>
|
||||||
{% elif data.choice == 'ELIT'%}
|
{% elif data.choice == 'ELIT'%}
|
||||||
|
|
@ -46,13 +46,15 @@ Zum Eintrag in der Förderdatenbank:
|
||||||
{% elif data.choice == 'VIS'%}
|
{% elif data.choice == 'VIS'%}
|
||||||
<a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
|
<a href="{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change">{{data.url_prefix}}/admin/input/businesscard/{{data.pk}}/change</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br><br>
|
</p>
|
||||||
|
|
||||||
Zum Genehmigen hier klicken: <a href="{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}">{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}</a>
|
<p>Zum Genehmigen hier klicken:
|
||||||
<br><br>
|
<a href="{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}">{{data.url_prefix}}{% url 'authorize' data.choice data.pk %}</a>
|
||||||
Zu Ablehnen hier klicken: <a href="{{data.url_prefix}}{% url 'deny' data.choice data.pk %}">{{data.url_prefix}}{% url 'deny' data.choice data.pk %}</a>
|
</p>
|
||||||
<br><br>
|
|
||||||
Stets zu Diensten, Deine Förderdatenbank
|
<p>Zum Ablehnen hier klicken:
|
||||||
|
<a href="{{data.url_prefix}}{% url 'deny' data.choice data.pk %}">{{data.url_prefix}}{% url 'deny' data.choice data.pk %}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hallo {{ data.username|default:data.realname }},</p>
|
||||||
|
|
||||||
|
<p>vielen Dank für deine Anfrage ({{ data.type_label|striptags }}), die bei uns eingegangen ist.</p>
|
||||||
|
|
||||||
|
Dies ist eine automatisch generierte E-Mail. Im Folgenden findest du deine Formulareingaben nochmals zu deiner Übersicht:<br>
|
||||||
|
{% if data.choice in data.grant %}<br>
|
||||||
|
Vorraussichtliche Kosten: {{data.cost}}<br>
|
||||||
|
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}<br>
|
||||||
|
Domain: <a href="{{data.domain}}">{{data.domain}}</a><br>
|
||||||
|
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}<br>
|
||||||
|
Bibliothek: {{data.library}}<br>
|
||||||
|
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}<br>
|
||||||
|
Datenbank: {{data.library}}<br>
|
||||||
|
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}<br>
|
||||||
|
Software: {{data.library}}<br>
|
||||||
|
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}<br>
|
||||||
|
Anfrage-URL: <a href="{{data.url}}">{{data.url}}</a> {% elif data.choice == 'LIT'%}<br>
|
||||||
|
Info zum Werk: {{data.info}}<br>
|
||||||
|
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}<br>
|
||||||
|
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}<br>
|
||||||
|
Wikimedia-Projekt: {{data.project}}<br>
|
||||||
|
Persönliche Daten: {{data.data}}<br>
|
||||||
|
Variante: {{data.variant}}<br>
|
||||||
|
Sendungsadrese: {{data.send_to}} {% endif %}<br>
|
||||||
|
|
||||||
|
<p>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 <a href="mailto:community@wikimedia.de">community@wikimedia.de</a>.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
--<br>
|
||||||
|
Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin<br>
|
||||||
|
Zentrale: +49 30 5771162-0<br>
|
||||||
|
<a href="https://wikimedia.de">wikimedia.de</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unsere Vision ist eine Welt, in der alle Menschen am Wissen der Menschheit teilhaben, es nutzen und mehren können. Helfen Sie uns dabei!<br>
|
||||||
|
<a href="https://spenden.wikimedia.de">spenden.wikimedia.de</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>Datenschutzerklärung:<br>
|
||||||
|
Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer <a href="https://www.wikimedia.de/datenschutz/">Datenschutzerklärung </a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
from django.template.loader import get_template
|
||||||
|
|
||||||
|
from input.models import Project
|
||||||
|
|
||||||
|
from .attachments import collect_attachment_paths, attach_files
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'build_email',
|
||||||
|
'send_email',
|
||||||
|
'collect_attachment_paths',
|
||||||
|
'attach_files',
|
||||||
|
'send_applicant_decision_mail',
|
||||||
|
'send_staff_decision_mail',
|
||||||
|
'send_decision_mails',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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 get_decision_mail_context(obj: Project):
|
||||||
|
"""
|
||||||
|
Build a minimal, consistent context for decision mails (applicant & staff).
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
'project': obj,
|
||||||
|
'data': {
|
||||||
|
'realname': obj.realname or obj.email,
|
||||||
|
'name': obj.name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def send_base_decision_mail(obj: Project, scope: str, subject: str, recipient: str):
|
||||||
|
context = get_decision_mail_context(obj)
|
||||||
|
decision = 'granted' if obj.granted else 'denied'
|
||||||
|
decision_label = 'bewilligt' if obj.granted else 'abgelehnt'
|
||||||
|
subject = subject.format(name=obj.name, decision=decision_label)
|
||||||
|
|
||||||
|
return send_email(f'approval_{scope}_{decision}', context, subject, recipient)
|
||||||
|
|
||||||
|
|
||||||
|
def send_applicant_decision_mail(obj: Project):
|
||||||
|
"""
|
||||||
|
Send a decision email to the applicant after manual approval/denial.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if recipient := obj.email:
|
||||||
|
return send_base_decision_mail(obj, 'applicant', 'Deine Förderanfrage „{name}“ – {decision}', recipient)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def send_staff_decision_mail(obj: Project):
|
||||||
|
"""
|
||||||
|
Send a decision email to the internal team (staff) after approval/denial.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return send_base_decision_mail(obj, 'staff', 'Entscheidung: {name} ({decision})', settings.IF_EMAIL)
|
||||||
|
|
||||||
|
|
||||||
|
def send_decision_mails(obj: Project):
|
||||||
|
return send_applicant_decision_mail(obj) + send_staff_decision_mail(obj)
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import time
|
||||||
|
import mimetypes
|
||||||
|
|
||||||
|
from os import PathLike
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from urllib.request import urlretrieve
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
|
||||||
|
from foerderbarometer.constants import *
|
||||||
|
|
||||||
|
PathList = list[Path]
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_dir(directory: PathLike) -> Path:
|
||||||
|
"""
|
||||||
|
Ensure that the given directory exists.
|
||||||
|
Creates it recursively if it doesn't.
|
||||||
|
"""
|
||||||
|
|
||||||
|
directory = Path(directory)
|
||||||
|
|
||||||
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
return directory
|
||||||
|
|
||||||
|
|
||||||
|
def is_fresh(path: Path, ttl_seconds: int) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the cached file exists and is still fresh within TTL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
mtime = path.stat().st_mtime
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return time.time() - mtime < ttl_seconds
|
||||||
|
|
||||||
|
|
||||||
|
def get_attachment(url: str) -> Path:
|
||||||
|
filepath = urlparse(url).path
|
||||||
|
filename = posixpath.basename(filepath)
|
||||||
|
destination = ensure_dir(settings.MAIL_ATTACHMENT_CACHE_DIR) / filename
|
||||||
|
|
||||||
|
if is_fresh(destination, settings.MAIL_ATTACHMENT_TTL_SECONDS):
|
||||||
|
return destination
|
||||||
|
|
||||||
|
return download_attachment(url, destination)
|
||||||
|
|
||||||
|
|
||||||
|
def download_attachment(url: str, destination: Path) -> Path:
|
||||||
|
filepath = destination.with_suffix('.tmp')
|
||||||
|
|
||||||
|
try:
|
||||||
|
urlretrieve(url, filepath)
|
||||||
|
os.replace(filepath, destination)
|
||||||
|
finally:
|
||||||
|
filepath.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
return destination
|
||||||
|
|
||||||
|
|
||||||
|
def collect_attachment_paths(recipient: str, type_code: str) -> PathList:
|
||||||
|
assert recipient in RECIPIENTS
|
||||||
|
assert type_code in TYPES
|
||||||
|
|
||||||
|
config = settings.MAIL_ATTACHMENT_URLS[recipient]
|
||||||
|
urls = [*config[TYPE_ALL], *config.get(type_code, [])]
|
||||||
|
|
||||||
|
return [get_attachment(url) for url in urls]
|
||||||
|
|
||||||
|
|
||||||
|
def get_mime_type(path: Path) -> str:
|
||||||
|
mime_type, encoding = mimetypes.guess_type(path)
|
||||||
|
|
||||||
|
return mime_type or 'application/octet-stream'
|
||||||
|
|
||||||
|
|
||||||
|
def attach_files(message: EmailMultiAlternatives, files: list[Path]):
|
||||||
|
"""
|
||||||
|
Attach files to the EmailMultiAlternatives message.
|
||||||
|
MIME type is guessed from path; falls back to application/octet-stream.
|
||||||
|
"""
|
||||||
|
|
||||||
|
for path in files:
|
||||||
|
mime_type = get_mime_type(path)
|
||||||
|
|
||||||
|
with open(path, 'rb') as fp:
|
||||||
|
message.attach(path.name, fp.read(), mime_type)
|
||||||
|
|
@ -5,12 +5,14 @@ from django.shortcuts import render
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.core.mail import BadHeaderError, EmailMultiAlternatives
|
from django.core.mail import BadHeaderError
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
from django.utils.html import strip_tags
|
||||||
|
|
||||||
|
from input.utils.mail import collect_attachment_paths, attach_files, build_email
|
||||||
|
|
||||||
from .forms import (
|
from .forms import (
|
||||||
BaseApplicationForm,
|
BaseApplicationForm,
|
||||||
|
|
@ -208,15 +210,28 @@ class ApplicationView(FormView):
|
||||||
- Return the "done" response.
|
- Return the "done" response.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
data = self.prepare_data(form)
|
||||||
|
obj = self.save_obj(form, data)
|
||||||
|
|
||||||
|
if response := self.send_mail(obj, data):
|
||||||
|
return response
|
||||||
|
|
||||||
|
return done(self.request)
|
||||||
|
|
||||||
|
def prepare_data(self, form):
|
||||||
# Collect cleaned data and mark the current type
|
# Collect cleaned data and mark the current type
|
||||||
data = form.cleaned_data.copy()
|
|
||||||
data['choice'] = self.type_code
|
data = {**form.cleaned_data, 'choice': self.type_code}
|
||||||
|
|
||||||
# Special rule for literature applications
|
# Special rule for literature applications
|
||||||
if self.type_code == TYPE_LIT and data.get('selfbuy') == 'TRUE':
|
if self.type_code == TYPE_LIT and data.get('selfbuy') == 'TRUE':
|
||||||
data['selfbuy_give_data'] = 'False'
|
data['selfbuy_give_data'] = 'False'
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def save_obj(self, form, data):
|
||||||
# Save model instance
|
# Save model instance
|
||||||
|
|
||||||
modell = form.save(commit=False)
|
modell = form.save(commit=False)
|
||||||
|
|
||||||
# Username from session if present
|
# Username from session if present
|
||||||
|
|
@ -226,6 +241,7 @@ class ApplicationView(FormView):
|
||||||
# Copy common fields if provided by the form
|
# Copy common fields if provided by the form
|
||||||
if 'realname' in data:
|
if 'realname' in data:
|
||||||
modell.realname = data['realname']
|
modell.realname = data['realname']
|
||||||
|
|
||||||
if 'email' in data:
|
if 'email' in data:
|
||||||
modell.email = data['email']
|
modell.email = data['email']
|
||||||
|
|
||||||
|
|
@ -238,39 +254,51 @@ class ApplicationView(FormView):
|
||||||
modell.selfbuy_give_data = data['selfbuy_give_data']
|
modell.selfbuy_give_data = data['selfbuy_give_data']
|
||||||
|
|
||||||
modell.save()
|
modell.save()
|
||||||
|
|
||||||
if hasattr(form, 'save_m2m'):
|
if hasattr(form, 'save_m2m'):
|
||||||
form.save_m2m()
|
form.save_m2m()
|
||||||
|
|
||||||
|
return modell
|
||||||
|
|
||||||
|
def send_mail(self, obj, data):
|
||||||
# Prepare minimal mail context and send mails
|
# Prepare minimal mail context and send mails
|
||||||
data['pk'] = modell.pk
|
|
||||||
|
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['url_prefix'] = settings.EMAIL_URL_PREFIX
|
||||||
data['type_label'] = self.type_info.label
|
data['type_label'] = type_label_html
|
||||||
|
|
||||||
context = {'data': data}
|
context = {'data': data}
|
||||||
|
|
||||||
|
applicant_name = self.get_recipient_name(obj, data)
|
||||||
|
applicant_subject = 'Deine Förderanfrage bei Wikimedia Deutschland'
|
||||||
|
|
||||||
|
staff_subject = f'Anfrage {type_label_plain} von {applicant_name}'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Mail to applicant
|
self.send_email('applicant', 'ifg_volunteer_mail', applicant_subject, data['email'], context)
|
||||||
txt1 = get_template('input/ifg_volunteer_mail.txt').render(context)
|
self.send_email('staff', 'if_mail', staff_subject, settings.IF_EMAIL, context)
|
||||||
html1 = get_template('input/ifg_volunteer_mail.html').render(context)
|
|
||||||
msg1 = EmailMultiAlternatives(
|
|
||||||
'Formular ausgefüllt', txt1, settings.IF_EMAIL, [data['email']]
|
|
||||||
)
|
|
||||||
msg1.attach_alternative(html1, 'text/html')
|
|
||||||
msg1.send()
|
|
||||||
|
|
||||||
# Mail to IF
|
|
||||||
txt2 = get_template('input/if_mail.txt').render(context)
|
|
||||||
html2 = get_template('input/if_mail.html').render(context)
|
|
||||||
msg2 = EmailMultiAlternatives(
|
|
||||||
'Formular ausgefüllt', txt2, settings.IF_EMAIL, [settings.IF_EMAIL]
|
|
||||||
)
|
|
||||||
msg2.attach_alternative(html2, 'text/html')
|
|
||||||
msg2.send()
|
|
||||||
|
|
||||||
except BadHeaderError:
|
except BadHeaderError:
|
||||||
modell.delete()
|
obj.delete()
|
||||||
return HttpResponse('Invalid header found. Data not saved!')
|
return HttpResponse('Invalid header found. Data not saved!')
|
||||||
except SMTPException:
|
except SMTPException:
|
||||||
modell.delete()
|
obj.delete()
|
||||||
return HttpResponse('Error in sending mails (probably wrong adress?). Data not saved!')
|
return HttpResponse('Error in sending mails (probably wrong address?). Data not saved!')
|
||||||
|
|
||||||
return done(self.request)
|
def send_email(self, kind, template_name, subject, recipient, context, *, fail_silently=False):
|
||||||
|
email = build_email(template_name, context, subject, recipient)
|
||||||
|
applicant_files = collect_attachment_paths(kind, self.type_code)
|
||||||
|
|
||||||
|
attach_files(email, applicant_files)
|
||||||
|
|
||||||
|
return email.send(fail_silently)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_recipient_name(obj, data):
|
||||||
|
for field in 'username', 'realname', 'email':
|
||||||
|
if name := getattr(obj, field, None) or data.get(field):
|
||||||
|
return name
|
||||||
|
|
||||||
|
return 'Unbekannt'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue