From c072f5caf2c0857a9390e940d4955f61a0122c2d Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 18 Nov 2025 23:48:21 +0100 Subject: [PATCH] chore(mailer/*): reformat using ruff (#14) --- jdav_web/mailer/admin.py | 139 ++++++++++++------- jdav_web/mailer/apps.py | 4 +- jdav_web/mailer/mailutils.py | 40 +++--- jdav_web/mailer/models.py | 255 +++++++++++++++++++---------------- jdav_web/mailer/rules.py | 1 + jdav_web/mailer/urls.py | 4 +- jdav_web/mailer/views.py | 42 +++--- 7 files changed, 282 insertions(+), 203 deletions(-) diff --git a/jdav_web/mailer/admin.py b/jdav_web/mailer/admin.py index 15848f2..2fa17cc 100644 --- a/jdav_web/mailer/admin.py +++ b/jdav_web/mailer/admin.py @@ -1,20 +1,29 @@ -from django.contrib import admin, messages +import json + +from contrib.admin import CommonAdminInlineMixin +from contrib.admin import CommonAdminMixin from django.conf import settings +from django.contrib import admin +from django.contrib import messages from django.contrib.admin import helpers -from django.utils.translation import gettext_lazy as _ from django.shortcuts import render -from django.db import models -from django import forms -#from easy_select2 import apply_select2 -import json - -from rules.contrib.admin import ObjectPermissionsModelAdmin - -from .models import Message, Attachment, MessageForm, EmailAddress, EmailAddressForm -from .mailutils import NOT_SENT, PARTLY_SENT -from members.models import Member +from django.utils.translation import ( + gettext_lazy as _, +) from members.admin import FilteredMemberFieldMixin -from contrib.admin import CommonAdminMixin, CommonAdminInlineMixin +from members.models import Member +from rules.contrib.admin import ( + ObjectPermissionsModelAdmin, +) + +from .mailutils import NOT_SENT +from .mailutils import PARTLY_SENT +from .models import Attachment +from .models import EmailAddress +from .models import EmailAddressForm +from .models import Message +from .models import MessageForm +# from easy_select2 import apply_select2 class AttachmentInline(CommonAdminInlineMixin, admin.TabularInline): @@ -23,91 +32,127 @@ class AttachmentInline(CommonAdminInlineMixin, admin.TabularInline): class EmailAddressAdmin(FilteredMemberFieldMixin, admin.ModelAdmin): - list_display = ('email', 'internal_only') - fields = ('name', 'to_members', 'to_groups', 'internal_only') - #formfield_overrides = { + list_display = ("email", "internal_only") + fields = ( + "name", + "to_members", + "to_groups", + "internal_only", + ) + # formfield_overrides = { # models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # models.ForeignKey: {'widget': apply_select2(forms.Select)} - #} - filter_horizontal = ('to_members',) + # } + filter_horizontal = ("to_members",) form = EmailAddressForm -class MessageAdmin(FilteredMemberFieldMixin, CommonAdminMixin, ObjectPermissionsModelAdmin): +class MessageAdmin( + FilteredMemberFieldMixin, + CommonAdminMixin, + ObjectPermissionsModelAdmin, +): """Message creation view""" - exclude = ('created_by', 'to_notelist') - list_display = ('subject', 'get_recipients', 'sent') - search_fields = ('subject',) - list_filter = ('sent',) + + exclude = ("created_by", "to_notelist") + list_display = ( + "subject", + "get_recipients", + "sent", + ) + search_fields = ("subject",) + list_filter = ("sent",) change_form_template = "mailer/change_form.html" - readonly_fields = ('sent',) - #formfield_overrides = { + readonly_fields = ("sent",) + # formfield_overrides = { # models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # models.ForeignKey: {'widget': apply_select2(forms.Select)} - #} + # } inlines = [AttachmentInline] - actions = ['send_message'] + actions = ["send_message"] form = MessageForm - filter_horizontal = ('to_members','reply_to') + filter_horizontal = ("to_members", "reply_to") def save_model(self, request, obj, form, change): - if not change and hasattr(request.user, 'member'): + if not change and hasattr(request.user, "member"): obj.created_by = request.user.member super().save_model(request, obj, form, change) def send_message(self, request, queryset): - if request.POST.get('confirmed'): + if request.POST.get("confirmed"): for msg in queryset: submit_message(msg, request) else: context = { - 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, - 'mails': queryset, - 'ids': queryset.values_list("id"), - 'some_sent': any(m.sent for m in queryset)} - return render(request, 'mailer/confirm_send.html', context) + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + "mails": queryset, + "ids": queryset.values_list("id"), + "some_sent": any(m.sent for m in queryset), + } + return render( + request, + "mailer/confirm_send.html", + context, + ) + send_message.short_description = _("Send message") def response_change(self, request, obj): if "_send" in request.POST: submit_message(obj, request) - return super(MessageAdmin, self).response_change(request, obj) + return super().response_change(request, obj) def response_add(self, request, obj): if "_send" in request.POST: submit_message(obj, request) - return super(MessageAdmin, self).response_add(request, obj) + return super().response_add(request, obj) def get_form(self, request, obj=None, **kwargs): - form = super(MessageAdmin, self).get_form(request, obj, **kwargs) - raw_members = request.GET.get('members', None) + form = super().get_form(request, obj, **kwargs) + raw_members = request.GET.get("members", None) if raw_members is not None: m_ids = json.loads(raw_members) - if type(m_ids) != list: + if type(m_ids) is not list: return form members = Member.objects.filter(pk__in=m_ids) - form.base_fields['to_members'].initial = members + form.base_fields["to_members"].initial = members return form def submit_message(msg, request): sender = None - if not hasattr(request.user, 'member'): - messages.error(request, _("Your account is not connected to a member. Please contact your system administrator.")) + if not hasattr(request.user, "member"): + messages.error( + request, + _( + "Your account is not connected to a member. Please contact your system administrator." + ), + ) return sender = request.user.member if not sender.has_internal_email(): - messages.error(request, - _("Your email address is not an internal email address. Please use an email address with one of the following domains: %(domains)s.") % {'domains': ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)}) + messages.error( + request, + _( + "Your email address is not an internal email address. Please use an email address with one of the following domains: %(domains)s." + ) + % {"domains": ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)}, + ) return success = msg.submit(sender) if success == NOT_SENT: messages.error(request, _("Failed to send message")) elif success == PARTLY_SENT: - messages.warning(request, _("Failed to send some messages")) + messages.warning( + request, + _("Failed to send some messages"), + ) else: - messages.success(request, _("Successfully sent message")) + messages.success( + request, + _("Successfully sent message"), + ) admin.site.register(Message, MessageAdmin) diff --git a/jdav_web/mailer/apps.py b/jdav_web/mailer/apps.py index 77c32f0..33395e9 100644 --- a/jdav_web/mailer/apps.py +++ b/jdav_web/mailer/apps.py @@ -3,5 +3,5 @@ from django.utils.translation import gettext_lazy as _ class MailerConfig(AppConfig): - name = 'mailer' - verbose_name = _('mailer') + name = "mailer" + verbose_name = _("mailer") diff --git a/jdav_web/mailer/mailutils.py b/jdav_web/mailer/mailutils.py index d3de5af..c98dca1 100644 --- a/jdav_web/mailer/mailutils.py +++ b/jdav_web/mailer/mailutils.py @@ -1,8 +1,8 @@ +import logging + +from django.conf import settings from django.core import mail from django.core.mail import EmailMessage -from django.conf import settings -import logging -import os logger = logging.getLogger(__name__) @@ -10,14 +10,16 @@ logger = logging.getLogger(__name__) NOT_SENT, SENT, PARTLY_SENT = 0, 1, 2 -def send(subject, content, sender, recipients, message_id=None, reply_to=None, - attachments=None, cc=None): + +def send( + subject, content, sender, recipients, message_id=None, reply_to=None, attachments=None, cc=None +): failed, succeeded = False, False - if type(recipients) != list: + if type(recipients) is not list: recipients = [recipients] if not cc: cc = [] - elif type(cc) != list: + elif type(cc) is not list: cc = [cc] if reply_to is not None: kwargs = {"reply_to": reply_to} @@ -26,15 +28,16 @@ def send(subject, content, sender, recipients, message_id=None, reply_to=None, if sender == settings.DEFAULT_SENDING_MAIL: sender = addr_with_name(settings.DEFAULT_SENDING_MAIL, settings.DEFAULT_SENDING_NAME) url = prepend_base_url("/newsletter/unsubscribe") - headers = {'List-Unsubscribe': '<{unsubscribe_url}>'.format(unsubscribe_url=url)} + headers = {"List-Unsubscribe": "<{unsubscribe_url}>".format(unsubscribe_url=url)} if message_id is not None: - headers['Message-ID'] = message_id + headers["Message-ID"] = message_id # construct mails mails = [] for recipient in set(recipients): - email = EmailMessage(subject, content, sender, [recipient], cc=cc, - headers=headers, **kwargs) + email = EmailMessage( + subject, content, sender, [recipient], cc=cc, headers=headers, **kwargs + ) if attachments is not None: for attach in attachments: email.attach_file(attach) @@ -50,15 +53,16 @@ def send(subject, content, sender, recipients, message_id=None, reply_to=None, else: succeeded = True - return NOT_SENT if failed and not succeeded else SENT if not failed\ - and succeeded else PARTLY_SENT + return ( + NOT_SENT if failed and not succeeded else SENT if not failed and succeeded else PARTLY_SENT + ) def get_content(content, registration_complete=True): - url = prepend_base_url("/newsletter/unsubscribe") prepend = settings.PREPEND_INCOMPLETE_REGISTRATION_TEXT - text = "{prepend}{content}".format(prepend="" if registration_complete else prepend, - content=content) + text = "{prepend}{content}".format( + prepend="" if registration_complete else prepend, content=content + ) return text @@ -102,7 +106,9 @@ def get_invite_as_user_key(key): def prepend_base_url(absolutelink): - return "{protocol}://{base}{link}".format(protocol=settings.PROTOCOL, base=settings.BASE_URL, link=absolutelink) + return "{protocol}://{base}{link}".format( + protocol=settings.PROTOCOL, base=settings.BASE_URL, link=absolutelink + ) def addr_with_name(addr, name): diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index dc0ee73..da77291 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -1,118 +1,140 @@ import logging -from django.db import models -from django.core.exceptions import ValidationError +import os + +from contrib.models import CommonModel +from contrib.rules import has_global_perm from django import forms -from django.utils.translation import gettext_lazy as _ +from django.conf import settings +from django.core.exceptions import ValidationError +from django.core.validators import RegexValidator +from django.db import models from django.utils.translation import gettext -from .mailutils import send, get_content, NOT_SENT, SENT, PARTLY_SENT,\ - addr_with_name +from django.utils.translation import gettext_lazy as _ from utils import RestrictedFileField -from jdav_web.celery import app -from django.core.validators import RegexValidator -from django.conf import settings -from contrib.rules import has_global_perm -from contrib.models import CommonModel +from .mailutils import addr_with_name +from .mailutils import get_content +from .mailutils import NOT_SENT +from .mailutils import PARTLY_SENT +from .mailutils import send +from .mailutils import SENT from .rules import is_creator -import os - logger = logging.getLogger(__name__) -alphanumeric = RegexValidator(r'^[0-9a-zA-Z._-]*$', - _('Only alphanumeric characters, ., - and _ are allowed')) +alphanumeric = RegexValidator( + r"^[0-9a-zA-Z._-]*$", _("Only alphanumeric characters, ., - and _ are allowed") +) class EmailAddress(models.Model): """Represents an email address, that is forwarded to specific members""" - name = models.CharField(_('name'), max_length=50, validators=[alphanumeric], - unique=True) - to_members = models.ManyToManyField('members.Member', - verbose_name=_('Forward to participants'), - blank=True) - to_groups = models.ManyToManyField('members.Group', - verbose_name=_('Forward to group'), - blank=True) - internal_only = models.BooleanField(verbose_name=_('Restrict to internal email addresses'), - help_text=_('Only allow forwarding to this e-mail address from one of the following domains: %(domains)s.') % {'domains': ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)}, - default=False) - allowed_senders = models.ManyToManyField('members.Group', - verbose_name=_('Allowed sender'), - help_text=_('Only forward e-mails of members of selected groups. Leave empty to allow all senders.'), - blank=True, - related_name='allowed_sender_on_emailaddresses') + + name = models.CharField(_("name"), max_length=50, validators=[alphanumeric], unique=True) + to_members = models.ManyToManyField( + "members.Member", verbose_name=_("Forward to participants"), blank=True + ) + to_groups = models.ManyToManyField( + "members.Group", verbose_name=_("Forward to group"), blank=True + ) + internal_only = models.BooleanField( + verbose_name=_("Restrict to internal email addresses"), + help_text=_( + "Only allow forwarding to this e-mail address from one of the following domains: %(domains)s." + ) + % {"domains": ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)}, + default=False, + ) + allowed_senders = models.ManyToManyField( + "members.Group", + verbose_name=_("Allowed sender"), + help_text=_( + "Only forward e-mails of members of selected groups. Leave empty to allow all senders." + ), + blank=True, + related_name="allowed_sender_on_emailaddresses", + ) @property def email(self): - return "{0}@{1}".format(self.name, settings.DOMAIN) + return "{}@{}".format(self.name, settings.DOMAIN) @property def forwards(self): - mails = set(member.email for member in self.to_members.all()) - mails.update([member.email for group in self.to_groups.all() for member in group.member_set.all()]) + mails = {member.email for member in self.to_members.all()} + mails.update( + [member.email for group in self.to_groups.all() for member in group.member_set.all()] + ) return mails def __str__(self): return self.email class Meta: - verbose_name = _('email address') - verbose_name_plural = _('email addresses') + verbose_name = _("email address") + verbose_name_plural = _("email addresses") class EmailAddressForm(forms.ModelForm): - class Meta: model = EmailAddress exclude = [] def clean(self): - super(EmailAddressForm, self).clean() - group = self.cleaned_data.get('to_groups') - members = self.cleaned_data.get('to_members') + super().clean() + group = self.cleaned_data.get("to_groups") + members = self.cleaned_data.get("to_members") if not group and not members: - raise ValidationError(_('Either a group or at least' - ' one member is required as forward recipient.')) - + raise ValidationError( + _("Either a group or at least one member is required as forward recipient.") + ) # Create your models here. class Message(CommonModel): """Represents a message that can be sent to some members""" - subject = models.CharField(_('subject'), max_length=50) - content = models.TextField(_('content')) - to_groups = models.ManyToManyField('members.Group', - verbose_name=_('to group'), - blank=True) - to_freizeit = models.ForeignKey('members.Freizeit', - verbose_name=_('to freizeit'), - on_delete=models.CASCADE, - blank=True, - null=True) - to_notelist = models.ForeignKey('members.MemberNoteList', - verbose_name=_('to notes list'), - on_delete=models.CASCADE, - blank=True, - null=True) - to_members = models.ManyToManyField('members.Member', - verbose_name=_('to member'), - blank=True) - reply_to = models.ManyToManyField('members.Member', - verbose_name=_('reply to participant'), - blank=True, - related_name='reply_to') - reply_to_email_address = models.ManyToManyField('mailer.EmailAddress', - verbose_name=_('reply to custom email address'), - blank=True, - related_name='reply_to_email_addr') - sent = models.BooleanField(_('sent'), default=False) - created_by = models.ForeignKey('members.Member', verbose_name=_('Created by'), - blank=True, - null=True, - on_delete=models.SET_NULL, - related_name='created_messages') + + subject = models.CharField(_("subject"), max_length=50) + content = models.TextField(_("content")) + to_groups = models.ManyToManyField("members.Group", verbose_name=_("to group"), blank=True) + to_freizeit = models.ForeignKey( + "members.Freizeit", + verbose_name=_("to freizeit"), + on_delete=models.CASCADE, + blank=True, + null=True, + ) + to_notelist = models.ForeignKey( + "members.MemberNoteList", + verbose_name=_("to notes list"), + on_delete=models.CASCADE, + blank=True, + null=True, + ) + to_members = models.ManyToManyField("members.Member", verbose_name=_("to member"), blank=True) + reply_to = models.ManyToManyField( + "members.Member", + verbose_name=_("reply to participant"), + blank=True, + related_name="reply_to", + ) + reply_to_email_address = models.ManyToManyField( + "mailer.EmailAddress", + verbose_name=_("reply to custom email address"), + blank=True, + related_name="reply_to_email_addr", + ) + sent = models.BooleanField(_("sent"), default=False) + created_by = models.ForeignKey( + "members.Member", + verbose_name=_("Created by"), + blank=True, + null=True, + on_delete=models.SET_NULL, + related_name="created_messages", + ) def __str__(self): return self.subject @@ -126,9 +148,10 @@ class Message(CommonModel): if 3 > self.to_members.count() > 0: recipients.extend([m.name for m in self.to_members.all()]) elif self.to_members.count() > 2: - recipients.append(gettext('Some other members')) + recipients.append(gettext("Some other members")) return ", ".join(recipients) - get_recipients.short_description = _('recipients') + + get_recipients.short_description = _("recipients") def submit(self, sender=None): """Sends the mail to the specified group of members""" @@ -141,24 +164,21 @@ class Message(CommonModel): members.update(self.to_members.all()) # get all the members of the selected freizeit if self.to_freizeit is not None: - members.update([mol.member for mol in - self.to_freizeit.membersonlist.all()]) + members.update([mol.member for mol in self.to_freizeit.membersonlist.all()]) members.update(self.to_freizeit.jugendleiter.all()) # get all the members of the selected notes list if self.to_notelist is not None: - members.update([mol.member for mol in - self.to_notelist.membersonlist.all()]) + members.update([mol.member for mol in self.to_notelist.membersonlist.all()]) filtered = [m for m in members if m.gets_newsletter] logger.info(f"sending mail to {filtered}") - attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) - if a.f.name] + attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) if a.f.name] emails = [member.email for member in filtered] emails.extend([member.alternative_email for member in filtered if member.alternative_email]) # remove any underscores from subject to prevent Arne from using # terrible looking underscores in subjects - self.subject = self.subject.replace('_', ' ') + self.subject = self.subject.replace("_", " ") # generate message id message_id = "<{pk}@{domain}>".format(pk=self.pk, domain=settings.DOMAIN) # reply to addresses @@ -176,15 +196,23 @@ class Message(CommonModel): # if sending from the association email has been disabled, # a sender was supplied and the reply to is empty, add the sender's # DAV360 email as reply to - if sender and not settings.SEND_FROM_ASSOCIATION_EMAIL and sender.has_internal_email() and reply_to == []: + if ( + sender + and not settings.SEND_FROM_ASSOCIATION_EMAIL + and sender.has_internal_email() + and reply_to == [] + ): reply_to.append(addr_with_name(sender.email, sender.name)) try: - success = send(self.subject, get_content(self.content, registration_complete=True), - from_addr, - emails, - message_id=message_id, - attachments=attach, - reply_to=reply_to) + success = send( + self.subject, + get_content(self.content, registration_complete=True), + from_addr, + emails, + message_id=message_id, + attachments=attach, + reply_to=reply_to, + ) if success == SENT or success == PARTLY_SENT: self.sent = True for a in Attachment.objects.filter(msg__id=self.pk): @@ -200,51 +228,48 @@ class Message(CommonModel): return success class Meta(CommonModel.Meta): - verbose_name = _('message') - verbose_name_plural = _('messages') - permissions = ( - ("submit_mails", _("Can submit mails")), - ) + verbose_name = _("message") + verbose_name_plural = _("messages") + permissions = (("submit_mails", _("Can submit mails")),) rules_permissions = { - "view_obj": is_creator | has_global_perm('mailer.view_global_message'), - "change_obj": is_creator | has_global_perm('mailer.change_global_message'), - "delete_obj": is_creator | has_global_perm('mailer.delete_global_message'), + "view_obj": is_creator | has_global_perm("mailer.view_global_message"), + "change_obj": is_creator | has_global_perm("mailer.change_global_message"), + "delete_obj": is_creator | has_global_perm("mailer.delete_global_message"), } class MessageForm(forms.ModelForm): - class Meta: model = Message exclude = [] def clean(self): - group = self.cleaned_data.get('to_groups') - freizeit = self.cleaned_data.get('to_freizeit') - notelist = self.cleaned_data.get('to_notelist') - members = self.cleaned_data.get('to_members') + group = self.cleaned_data.get("to_groups") + freizeit = self.cleaned_data.get("to_freizeit") + notelist = self.cleaned_data.get("to_notelist") + members = self.cleaned_data.get("to_members") if not group and freizeit is None and not members and notelist is None: - raise ValidationError(_('Either a group, a memberlist or at least' - ' one member is required as recipient')) + raise ValidationError( + _("Either a group, a memberlist or at least one member is required as recipient") + ) + class Attachment(CommonModel): """Represents an attachment to an email""" + msg = models.ForeignKey(Message, on_delete=models.CASCADE) # file (not naming it file because of builtin) - f = RestrictedFileField(_('file'), - upload_to='attachments', - max_upload_size=10) + f = RestrictedFileField(_("file"), upload_to="attachments", max_upload_size=10) def __str__(self): return os.path.basename(self.f.name) if self.f.name else str(_("Empty")) class Meta: - verbose_name = _('attachment') - verbose_name_plural = _('attachments') + verbose_name = _("attachment") + verbose_name_plural = _("attachments") rules_permissions = { - "add_obj": is_creator | has_global_perm('mailer.view_global_message'), - "view_obj": is_creator | has_global_perm('mailer.view_global_message'), - "change_obj": is_creator | has_global_perm('mailer.change_global_message'), - "delete_obj": is_creator | has_global_perm('mailer.delete_global_message'), + "add_obj": is_creator | has_global_perm("mailer.view_global_message"), + "view_obj": is_creator | has_global_perm("mailer.view_global_message"), + "change_obj": is_creator | has_global_perm("mailer.change_global_message"), + "delete_obj": is_creator | has_global_perm("mailer.delete_global_message"), } - diff --git a/jdav_web/mailer/rules.py b/jdav_web/mailer/rules.py index a1c6db1..14be807 100644 --- a/jdav_web/mailer/rules.py +++ b/jdav_web/mailer/rules.py @@ -1,6 +1,7 @@ from contrib.rules import memberize_user from rules import predicate + @predicate @memberize_user def is_creator(self, message): diff --git a/jdav_web/mailer/urls.py b/jdav_web/mailer/urls.py index a682f6d..0bfff67 100644 --- a/jdav_web/mailer/urls.py +++ b/jdav_web/mailer/urls.py @@ -4,6 +4,6 @@ from . import views app_name = "mailer" urlpatterns = [ - re_path(r'^$', views.index, name='index'), - re_path(r'^unsubscribe', views.unsubscribe, name='unsubscribe'), + re_path(r"^$", views.index, name="index"), + re_path(r"^unsubscribe", views.unsubscribe, name="unsubscribe"), ] diff --git a/jdav_web/mailer/views.py b/jdav_web/mailer/views.py index d529f3e..63cd1a7 100644 --- a/jdav_web/mailer/views.py +++ b/jdav_web/mailer/views.py @@ -1,57 +1,59 @@ +from django.conf import settings +from django.http import HttpResponseRedirect from django.shortcuts import render -from django import forms -from django.utils.translation import gettext_lazy as _ from django.urls import reverse -from django.http import HttpResponseRedirect -from .mailutils import send as send_mail, get_unsubscribe_link -from django.conf import settings - +from django.utils.translation import gettext_lazy as _ from members.models import Member +from .mailutils import get_unsubscribe_link +from .mailutils import send as send_mail + def index(request): - return HttpResponseRedirect(reverse('mailer:unsubscribe')) + return HttpResponseRedirect(reverse("mailer:unsubscribe")) def render_unsubscribe(request, error_message=""): context = {} if error_message: - context['error_message'] = error_message - return render(request, 'mailer/unsubscribe.html', context) + context["error_message"] = error_message + return render(request, "mailer/unsubscribe.html", context) def render_unsubscribed(request, email): - return render(request, 'mailer/unsubscribed.html', {'email': email}) + return render(request, "mailer/unsubscribed.html", {"email": email}) def unsubscribe(request): - if request.method == 'GET' and 'key' in request.GET: + if request.method == "GET" and "key" in request.GET: try: - key = request.GET['key'] + key = request.GET["key"] member = Member.objects.get(unsubscribe_key=key) if not member.unsubscribe(key): raise KeyError except (KeyError, Member.DoesNotExist): - return render_unsubscribe(request, - _("Can't verify this link. Try again!")) + return render_unsubscribe(request, _("Can't verify this link. Try again!")) else: return render_unsubscribed(request, member.email) - elif not request.POST.get('post', False): + elif not request.POST.get("post", False): # just calling up unsubscribe page return render_unsubscribe(request) try: - email = request.POST['email'] + email = request.POST["email"] member = Member.objects.filter(email=email).first() if not member: # member not found raise KeyError except (KeyError, Member.DoesNotExist): return render_unsubscribe(request, _("Please fill in every field")) else: - send_mail(_("Unsubscription confirmation"), - settings.UNSUBSCRIBE_CONFIRMATION_TEXT.format(link=get_unsubscribe_link(member)), - settings.DEFAULT_SENDING_MAIL, email) + send_mail( + _("Unsubscription confirmation"), + settings.UNSUBSCRIBE_CONFIRMATION_TEXT.format(link=get_unsubscribe_link(member)), + settings.DEFAULT_SENDING_MAIL, + email, + ) return render_confirmation_sent(request, email) def render_confirmation_sent(request, email): - return render(request, 'mailer/confirmation_sent.html', {'email': email}) + return render(request, "mailer/confirmation_sent.html", {"email": email})