chore(mailer/*): reformat using ruff (#14)

mk-personal-profile
Christian Merten 4 weeks ago committed by GitHub
parent aae75ce291
commit c072f5caf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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.conf import settings
from django.contrib import admin
from django.contrib import messages
from django.contrib.admin import helpers from django.contrib.admin import helpers
from django.utils.translation import gettext_lazy as _
from django.shortcuts import render from django.shortcuts import render
from django.db import models from django.utils.translation import (
from django import forms gettext_lazy as _,
#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 members.admin import FilteredMemberFieldMixin 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): class AttachmentInline(CommonAdminInlineMixin, admin.TabularInline):
@ -23,91 +32,127 @@ class AttachmentInline(CommonAdminInlineMixin, admin.TabularInline):
class EmailAddressAdmin(FilteredMemberFieldMixin, admin.ModelAdmin): class EmailAddressAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
list_display = ('email', 'internal_only') list_display = ("email", "internal_only")
fields = ('name', 'to_members', 'to_groups', 'internal_only') fields = (
#formfield_overrides = { "name",
"to_members",
"to_groups",
"internal_only",
)
# formfield_overrides = {
# models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
# models.ForeignKey: {'widget': apply_select2(forms.Select)} # models.ForeignKey: {'widget': apply_select2(forms.Select)}
#} # }
filter_horizontal = ('to_members',) filter_horizontal = ("to_members",)
form = EmailAddressForm form = EmailAddressForm
class MessageAdmin(FilteredMemberFieldMixin, CommonAdminMixin, ObjectPermissionsModelAdmin): class MessageAdmin(
FilteredMemberFieldMixin,
CommonAdminMixin,
ObjectPermissionsModelAdmin,
):
"""Message creation view""" """Message creation view"""
exclude = ('created_by', 'to_notelist')
list_display = ('subject', 'get_recipients', 'sent') exclude = ("created_by", "to_notelist")
search_fields = ('subject',) list_display = (
list_filter = ('sent',) "subject",
"get_recipients",
"sent",
)
search_fields = ("subject",)
list_filter = ("sent",)
change_form_template = "mailer/change_form.html" change_form_template = "mailer/change_form.html"
readonly_fields = ('sent',) readonly_fields = ("sent",)
#formfield_overrides = { # formfield_overrides = {
# models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
# models.ForeignKey: {'widget': apply_select2(forms.Select)} # models.ForeignKey: {'widget': apply_select2(forms.Select)}
#} # }
inlines = [AttachmentInline] inlines = [AttachmentInline]
actions = ['send_message'] actions = ["send_message"]
form = MessageForm form = MessageForm
filter_horizontal = ('to_members','reply_to') filter_horizontal = ("to_members", "reply_to")
def save_model(self, request, obj, form, change): 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 obj.created_by = request.user.member
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
def send_message(self, request, queryset): def send_message(self, request, queryset):
if request.POST.get('confirmed'): if request.POST.get("confirmed"):
for msg in queryset: for msg in queryset:
submit_message(msg, request) submit_message(msg, request)
else: else:
context = { context = {
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME,
'mails': queryset, "mails": queryset,
'ids': queryset.values_list("id"), "ids": queryset.values_list("id"),
'some_sent': any(m.sent for m in queryset)} "some_sent": any(m.sent for m in queryset),
return render(request, 'mailer/confirm_send.html', context) }
return render(
request,
"mailer/confirm_send.html",
context,
)
send_message.short_description = _("Send message") send_message.short_description = _("Send message")
def response_change(self, request, obj): def response_change(self, request, obj):
if "_send" in request.POST: if "_send" in request.POST:
submit_message(obj, request) submit_message(obj, request)
return super(MessageAdmin, self).response_change(request, obj) return super().response_change(request, obj)
def response_add(self, request, obj): def response_add(self, request, obj):
if "_send" in request.POST: if "_send" in request.POST:
submit_message(obj, request) 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): def get_form(self, request, obj=None, **kwargs):
form = super(MessageAdmin, self).get_form(request, obj, **kwargs) form = super().get_form(request, obj, **kwargs)
raw_members = request.GET.get('members', None) raw_members = request.GET.get("members", None)
if raw_members is not None: if raw_members is not None:
m_ids = json.loads(raw_members) m_ids = json.loads(raw_members)
if type(m_ids) != list: if type(m_ids) is not list:
return form return form
members = Member.objects.filter(pk__in=m_ids) members = Member.objects.filter(pk__in=m_ids)
form.base_fields['to_members'].initial = members form.base_fields["to_members"].initial = members
return form return form
def submit_message(msg, request): def submit_message(msg, request):
sender = None sender = None
if not hasattr(request.user, 'member'): if not hasattr(request.user, "member"):
messages.error(request, _("Your account is not connected to a member. Please contact your system administrator.")) messages.error(
request,
_(
"Your account is not connected to a member. Please contact your system administrator."
),
)
return return
sender = request.user.member sender = request.user.member
if not sender.has_internal_email(): if not sender.has_internal_email():
messages.error(request, messages.error(
_("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)}) 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 return
success = msg.submit(sender) success = msg.submit(sender)
if success == NOT_SENT: if success == NOT_SENT:
messages.error(request, _("Failed to send message")) messages.error(request, _("Failed to send message"))
elif success == PARTLY_SENT: elif success == PARTLY_SENT:
messages.warning(request, _("Failed to send some messages")) messages.warning(
request,
_("Failed to send some messages"),
)
else: else:
messages.success(request, _("Successfully sent message")) messages.success(
request,
_("Successfully sent message"),
)
admin.site.register(Message, MessageAdmin) admin.site.register(Message, MessageAdmin)

@ -3,5 +3,5 @@ from django.utils.translation import gettext_lazy as _
class MailerConfig(AppConfig): class MailerConfig(AppConfig):
name = 'mailer' name = "mailer"
verbose_name = _('mailer') verbose_name = _("mailer")

@ -1,8 +1,8 @@
import logging
from django.conf import settings
from django.core import mail from django.core import mail
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
from django.conf import settings
import logging
import os
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -10,14 +10,16 @@ logger = logging.getLogger(__name__)
NOT_SENT, SENT, PARTLY_SENT = 0, 1, 2 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 failed, succeeded = False, False
if type(recipients) != list: if type(recipients) is not list:
recipients = [recipients] recipients = [recipients]
if not cc: if not cc:
cc = [] cc = []
elif type(cc) != list: elif type(cc) is not list:
cc = [cc] cc = [cc]
if reply_to is not None: if reply_to is not None:
kwargs = {"reply_to": reply_to} 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: if sender == settings.DEFAULT_SENDING_MAIL:
sender = addr_with_name(settings.DEFAULT_SENDING_MAIL, settings.DEFAULT_SENDING_NAME) sender = addr_with_name(settings.DEFAULT_SENDING_MAIL, settings.DEFAULT_SENDING_NAME)
url = prepend_base_url("/newsletter/unsubscribe") 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: if message_id is not None:
headers['Message-ID'] = message_id headers["Message-ID"] = message_id
# construct mails # construct mails
mails = [] mails = []
for recipient in set(recipients): for recipient in set(recipients):
email = EmailMessage(subject, content, sender, [recipient], cc=cc, email = EmailMessage(
headers=headers, **kwargs) subject, content, sender, [recipient], cc=cc, headers=headers, **kwargs
)
if attachments is not None: if attachments is not None:
for attach in attachments: for attach in attachments:
email.attach_file(attach) email.attach_file(attach)
@ -50,15 +53,16 @@ def send(subject, content, sender, recipients, message_id=None, reply_to=None,
else: else:
succeeded = True succeeded = True
return NOT_SENT if failed and not succeeded else SENT if not failed\ return (
and succeeded else PARTLY_SENT NOT_SENT if failed and not succeeded else SENT if not failed and succeeded else PARTLY_SENT
)
def get_content(content, registration_complete=True): def get_content(content, registration_complete=True):
url = prepend_base_url("/newsletter/unsubscribe")
prepend = settings.PREPEND_INCOMPLETE_REGISTRATION_TEXT prepend = settings.PREPEND_INCOMPLETE_REGISTRATION_TEXT
text = "{prepend}{content}".format(prepend="" if registration_complete else prepend, text = "{prepend}{content}".format(
content=content) prepend="" if registration_complete else prepend, content=content
)
return text return text
@ -102,7 +106,9 @@ def get_invite_as_user_key(key):
def prepend_base_url(absolutelink): 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): def addr_with_name(addr, name):

@ -1,118 +1,140 @@
import logging import logging
from django.db import models import os
from django.core.exceptions import ValidationError
from contrib.models import CommonModel
from contrib.rules import has_global_perm
from django import forms 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 django.utils.translation import gettext
from .mailutils import send, get_content, NOT_SENT, SENT, PARTLY_SENT,\ from django.utils.translation import gettext_lazy as _
addr_with_name
from utils import RestrictedFileField 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 .mailutils import addr_with_name
from contrib.models import CommonModel 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 from .rules import is_creator
import os
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
alphanumeric = RegexValidator(r'^[0-9a-zA-Z._-]*$', alphanumeric = RegexValidator(
_('Only alphanumeric characters, ., - and _ are allowed')) r"^[0-9a-zA-Z._-]*$", _("Only alphanumeric characters, ., - and _ are allowed")
)
class EmailAddress(models.Model): class EmailAddress(models.Model):
"""Represents an email address, that is forwarded to specific members""" """Represents an email address, that is forwarded to specific members"""
name = models.CharField(_('name'), max_length=50, validators=[alphanumeric],
unique=True) name = models.CharField(_("name"), max_length=50, validators=[alphanumeric], unique=True)
to_members = models.ManyToManyField('members.Member', to_members = models.ManyToManyField(
verbose_name=_('Forward to participants'), "members.Member", verbose_name=_("Forward to participants"), blank=True
blank=True) )
to_groups = models.ManyToManyField('members.Group', to_groups = models.ManyToManyField(
verbose_name=_('Forward to group'), "members.Group", verbose_name=_("Forward to group"), blank=True
blank=True) )
internal_only = models.BooleanField(verbose_name=_('Restrict to internal email addresses'), internal_only = models.BooleanField(
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)}, verbose_name=_("Restrict to internal email addresses"),
default=False) help_text=_(
allowed_senders = models.ManyToManyField('members.Group', "Only allow forwarding to this e-mail address from one of the following domains: %(domains)s."
verbose_name=_('Allowed sender'), )
help_text=_('Only forward e-mails of members of selected groups. Leave empty to allow all senders.'), % {"domains": ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)},
blank=True, default=False,
related_name='allowed_sender_on_emailaddresses') )
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 @property
def email(self): def email(self):
return "{0}@{1}".format(self.name, settings.DOMAIN) return "{}@{}".format(self.name, settings.DOMAIN)
@property @property
def forwards(self): def forwards(self):
mails = set(member.email for member in self.to_members.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()]) mails.update(
[member.email for group in self.to_groups.all() for member in group.member_set.all()]
)
return mails return mails
def __str__(self): def __str__(self):
return self.email return self.email
class Meta: class Meta:
verbose_name = _('email address') verbose_name = _("email address")
verbose_name_plural = _('email addresses') verbose_name_plural = _("email addresses")
class EmailAddressForm(forms.ModelForm): class EmailAddressForm(forms.ModelForm):
class Meta: class Meta:
model = EmailAddress model = EmailAddress
exclude = [] exclude = []
def clean(self): def clean(self):
super(EmailAddressForm, self).clean() super().clean()
group = self.cleaned_data.get('to_groups') group = self.cleaned_data.get("to_groups")
members = self.cleaned_data.get('to_members') members = self.cleaned_data.get("to_members")
if not group and not members: if not group and not members:
raise ValidationError(_('Either a group or at least' raise ValidationError(
' one member is required as forward recipient.')) _("Either a group or at least one member is required as forward recipient.")
)
# Create your models here. # Create your models here.
class Message(CommonModel): class Message(CommonModel):
"""Represents a message that can be sent to some members""" """Represents a message that can be sent to some members"""
subject = models.CharField(_('subject'), max_length=50)
content = models.TextField(_('content')) subject = models.CharField(_("subject"), max_length=50)
to_groups = models.ManyToManyField('members.Group', content = models.TextField(_("content"))
verbose_name=_('to group'), to_groups = models.ManyToManyField("members.Group", verbose_name=_("to group"), blank=True)
blank=True) to_freizeit = models.ForeignKey(
to_freizeit = models.ForeignKey('members.Freizeit', "members.Freizeit",
verbose_name=_('to freizeit'), verbose_name=_("to freizeit"),
on_delete=models.CASCADE, on_delete=models.CASCADE,
blank=True, blank=True,
null=True) null=True,
to_notelist = models.ForeignKey('members.MemberNoteList', )
verbose_name=_('to notes list'), to_notelist = models.ForeignKey(
on_delete=models.CASCADE, "members.MemberNoteList",
blank=True, verbose_name=_("to notes list"),
null=True) on_delete=models.CASCADE,
to_members = models.ManyToManyField('members.Member', blank=True,
verbose_name=_('to member'), null=True,
blank=True) )
reply_to = models.ManyToManyField('members.Member', to_members = models.ManyToManyField("members.Member", verbose_name=_("to member"), blank=True)
verbose_name=_('reply to participant'), reply_to = models.ManyToManyField(
blank=True, "members.Member",
related_name='reply_to') verbose_name=_("reply to participant"),
reply_to_email_address = models.ManyToManyField('mailer.EmailAddress', blank=True,
verbose_name=_('reply to custom email address'), related_name="reply_to",
blank=True, )
related_name='reply_to_email_addr') reply_to_email_address = models.ManyToManyField(
sent = models.BooleanField(_('sent'), default=False) "mailer.EmailAddress",
created_by = models.ForeignKey('members.Member', verbose_name=_('Created by'), verbose_name=_("reply to custom email address"),
blank=True, blank=True,
null=True, related_name="reply_to_email_addr",
on_delete=models.SET_NULL, )
related_name='created_messages') 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): def __str__(self):
return self.subject return self.subject
@ -126,9 +148,10 @@ class Message(CommonModel):
if 3 > self.to_members.count() > 0: if 3 > self.to_members.count() > 0:
recipients.extend([m.name for m in self.to_members.all()]) recipients.extend([m.name for m in self.to_members.all()])
elif self.to_members.count() > 2: elif self.to_members.count() > 2:
recipients.append(gettext('Some other members')) recipients.append(gettext("Some other members"))
return ", ".join(recipients) return ", ".join(recipients)
get_recipients.short_description = _('recipients')
get_recipients.short_description = _("recipients")
def submit(self, sender=None): def submit(self, sender=None):
"""Sends the mail to the specified group of members""" """Sends the mail to the specified group of members"""
@ -141,24 +164,21 @@ class Message(CommonModel):
members.update(self.to_members.all()) members.update(self.to_members.all())
# get all the members of the selected freizeit # get all the members of the selected freizeit
if self.to_freizeit is not None: if self.to_freizeit is not None:
members.update([mol.member for mol in members.update([mol.member for mol in self.to_freizeit.membersonlist.all()])
self.to_freizeit.membersonlist.all()])
members.update(self.to_freizeit.jugendleiter.all()) members.update(self.to_freizeit.jugendleiter.all())
# get all the members of the selected notes list # get all the members of the selected notes list
if self.to_notelist is not None: if self.to_notelist is not None:
members.update([mol.member for mol in members.update([mol.member for mol in self.to_notelist.membersonlist.all()])
self.to_notelist.membersonlist.all()])
filtered = [m for m in members if m.gets_newsletter] filtered = [m for m in members if m.gets_newsletter]
logger.info(f"sending mail to {filtered}") logger.info(f"sending mail to {filtered}")
attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) if a.f.name]
if a.f.name]
emails = [member.email for member in filtered] emails = [member.email for member in filtered]
emails.extend([member.alternative_email for member in filtered if member.alternative_email]) emails.extend([member.alternative_email for member in filtered if member.alternative_email])
# remove any underscores from subject to prevent Arne from using # remove any underscores from subject to prevent Arne from using
# terrible looking underscores in subjects # terrible looking underscores in subjects
self.subject = self.subject.replace('_', ' ') self.subject = self.subject.replace("_", " ")
# generate message id # generate message id
message_id = "<{pk}@{domain}>".format(pk=self.pk, domain=settings.DOMAIN) message_id = "<{pk}@{domain}>".format(pk=self.pk, domain=settings.DOMAIN)
# reply to addresses # reply to addresses
@ -176,15 +196,23 @@ class Message(CommonModel):
# if sending from the association email has been disabled, # if sending from the association email has been disabled,
# a sender was supplied and the reply to is empty, add the sender's # a sender was supplied and the reply to is empty, add the sender's
# DAV360 email as reply to # 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)) reply_to.append(addr_with_name(sender.email, sender.name))
try: try:
success = send(self.subject, get_content(self.content, registration_complete=True), success = send(
from_addr, self.subject,
emails, get_content(self.content, registration_complete=True),
message_id=message_id, from_addr,
attachments=attach, emails,
reply_to=reply_to) message_id=message_id,
attachments=attach,
reply_to=reply_to,
)
if success == SENT or success == PARTLY_SENT: if success == SENT or success == PARTLY_SENT:
self.sent = True self.sent = True
for a in Attachment.objects.filter(msg__id=self.pk): for a in Attachment.objects.filter(msg__id=self.pk):
@ -200,51 +228,48 @@ class Message(CommonModel):
return success return success
class Meta(CommonModel.Meta): class Meta(CommonModel.Meta):
verbose_name = _('message') verbose_name = _("message")
verbose_name_plural = _('messages') verbose_name_plural = _("messages")
permissions = ( permissions = (("submit_mails", _("Can submit mails")),)
("submit_mails", _("Can submit mails")),
)
rules_permissions = { rules_permissions = {
"view_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'), "change_obj": is_creator | has_global_perm("mailer.change_global_message"),
"delete_obj": is_creator | has_global_perm('mailer.delete_global_message'), "delete_obj": is_creator | has_global_perm("mailer.delete_global_message"),
} }
class MessageForm(forms.ModelForm): class MessageForm(forms.ModelForm):
class Meta: class Meta:
model = Message model = Message
exclude = [] exclude = []
def clean(self): def clean(self):
group = self.cleaned_data.get('to_groups') group = self.cleaned_data.get("to_groups")
freizeit = self.cleaned_data.get('to_freizeit') freizeit = self.cleaned_data.get("to_freizeit")
notelist = self.cleaned_data.get('to_notelist') notelist = self.cleaned_data.get("to_notelist")
members = self.cleaned_data.get('to_members') members = self.cleaned_data.get("to_members")
if not group and freizeit is None and not members and notelist is None: if not group and freizeit is None and not members and notelist is None:
raise ValidationError(_('Either a group, a memberlist or at least' raise ValidationError(
' one member is required as recipient')) _("Either a group, a memberlist or at least one member is required as recipient")
)
class Attachment(CommonModel): class Attachment(CommonModel):
"""Represents an attachment to an email""" """Represents an attachment to an email"""
msg = models.ForeignKey(Message, on_delete=models.CASCADE) msg = models.ForeignKey(Message, on_delete=models.CASCADE)
# file (not naming it file because of builtin) # file (not naming it file because of builtin)
f = RestrictedFileField(_('file'), f = RestrictedFileField(_("file"), upload_to="attachments", max_upload_size=10)
upload_to='attachments',
max_upload_size=10)
def __str__(self): def __str__(self):
return os.path.basename(self.f.name) if self.f.name else str(_("Empty")) return os.path.basename(self.f.name) if self.f.name else str(_("Empty"))
class Meta: class Meta:
verbose_name = _('attachment') verbose_name = _("attachment")
verbose_name_plural = _('attachments') verbose_name_plural = _("attachments")
rules_permissions = { rules_permissions = {
"add_obj": is_creator | has_global_perm('mailer.view_global_message'), "add_obj": is_creator | has_global_perm("mailer.view_global_message"),
"view_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'), "change_obj": is_creator | has_global_perm("mailer.change_global_message"),
"delete_obj": is_creator | has_global_perm('mailer.delete_global_message'), "delete_obj": is_creator | has_global_perm("mailer.delete_global_message"),
} }

@ -1,6 +1,7 @@
from contrib.rules import memberize_user from contrib.rules import memberize_user
from rules import predicate from rules import predicate
@predicate @predicate
@memberize_user @memberize_user
def is_creator(self, message): def is_creator(self, message):

@ -4,6 +4,6 @@ from . import views
app_name = "mailer" app_name = "mailer"
urlpatterns = [ urlpatterns = [
re_path(r'^$', views.index, name='index'), re_path(r"^$", views.index, name="index"),
re_path(r'^unsubscribe', views.unsubscribe, name='unsubscribe'), re_path(r"^unsubscribe", views.unsubscribe, name="unsubscribe"),
] ]

@ -1,57 +1,59 @@
from django.conf import settings
from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from django import forms
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.http import HttpResponseRedirect from django.utils.translation import gettext_lazy as _
from .mailutils import send as send_mail, get_unsubscribe_link
from django.conf import settings
from members.models import Member from members.models import Member
from .mailutils import get_unsubscribe_link
from .mailutils import send as send_mail
def index(request): def index(request):
return HttpResponseRedirect(reverse('mailer:unsubscribe')) return HttpResponseRedirect(reverse("mailer:unsubscribe"))
def render_unsubscribe(request, error_message=""): def render_unsubscribe(request, error_message=""):
context = {} context = {}
if error_message: if error_message:
context['error_message'] = error_message context["error_message"] = error_message
return render(request, 'mailer/unsubscribe.html', context) return render(request, "mailer/unsubscribe.html", context)
def render_unsubscribed(request, email): def render_unsubscribed(request, email):
return render(request, 'mailer/unsubscribed.html', {'email': email}) return render(request, "mailer/unsubscribed.html", {"email": email})
def unsubscribe(request): def unsubscribe(request):
if request.method == 'GET' and 'key' in request.GET: if request.method == "GET" and "key" in request.GET:
try: try:
key = request.GET['key'] key = request.GET["key"]
member = Member.objects.get(unsubscribe_key=key) member = Member.objects.get(unsubscribe_key=key)
if not member.unsubscribe(key): if not member.unsubscribe(key):
raise KeyError raise KeyError
except (KeyError, Member.DoesNotExist): except (KeyError, Member.DoesNotExist):
return render_unsubscribe(request, return render_unsubscribe(request, _("Can't verify this link. Try again!"))
_("Can't verify this link. Try again!"))
else: else:
return render_unsubscribed(request, member.email) 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 # just calling up unsubscribe page
return render_unsubscribe(request) return render_unsubscribe(request)
try: try:
email = request.POST['email'] email = request.POST["email"]
member = Member.objects.filter(email=email).first() member = Member.objects.filter(email=email).first()
if not member: # member not found if not member: # member not found
raise KeyError raise KeyError
except (KeyError, Member.DoesNotExist): except (KeyError, Member.DoesNotExist):
return render_unsubscribe(request, _("Please fill in every field")) return render_unsubscribe(request, _("Please fill in every field"))
else: else:
send_mail(_("Unsubscription confirmation"), send_mail(
settings.UNSUBSCRIBE_CONFIRMATION_TEXT.format(link=get_unsubscribe_link(member)), _("Unsubscription confirmation"),
settings.DEFAULT_SENDING_MAIL, email) settings.UNSUBSCRIBE_CONFIRMATION_TEXT.format(link=get_unsubscribe_link(member)),
settings.DEFAULT_SENDING_MAIL,
email,
)
return render_confirmation_sent(request, email) return render_confirmation_sent(request, email)
def 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})

Loading…
Cancel
Save