From f8cade61c0b57241e39a244943caa0e0865aff49 Mon Sep 17 00:00:00 2001 From: erichhasl Date: Sun, 12 Mar 2017 19:00:08 +0100 Subject: [PATCH 1/5] send mails to memberlist --- jdav_web/mailer/admin.py | 5 +++-- jdav_web/mailer/models.py | 41 +++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/jdav_web/mailer/admin.py b/jdav_web/mailer/admin.py index c12c4b1..db8a265 100644 --- a/jdav_web/mailer/admin.py +++ b/jdav_web/mailer/admin.py @@ -5,7 +5,7 @@ from django.shortcuts import render from django.db import models from django import forms -from .models import Message, Attachment +from .models import Message, Attachment, MessageForm class AttachmentInline(admin.StackedInline): @@ -15,7 +15,7 @@ class AttachmentInline(admin.StackedInline): class MessageAdmin(admin.ModelAdmin): """Message creation view""" - list_display = ('subject', 'from_addr', 'get_groups', 'sent') + list_display = ('subject', 'from_addr', 'get_recipients', 'sent') change_form_template = "mailer/change_form.html" formfield_overrides = { models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple} @@ -23,6 +23,7 @@ class MessageAdmin(admin.ModelAdmin): inlines = [AttachmentInline] actions = ['send_message'] + form = MessageForm def send_message(self, request, queryset): print("calling send_message") diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index d76ae5f..ceb619d 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -1,5 +1,6 @@ from django.db import models -from django.forms import forms +from django.core.exceptions import ValidationError +from django import forms from django.utils.translation import ugettext_lazy as _ from .mailutils import send, get_content @@ -35,15 +36,23 @@ class Message(models.Model): subject = models.CharField(_('subject'), max_length=50) content = models.TextField(_('content')) to_groups = models.ManyToManyField('members.Group', - verbose_name=_('to group')) + verbose_name=_('to group'), + blank=True) + to_memberlist = models.ForeignKey('members.MemberList', + verbose_name=_('to member list'), + blank=True, + null=True) sent = models.BooleanField(_('sent'), default=False) def __str__(self): return self.subject - def get_groups(self): - return ", ".join([g.name for g in self.to_groups.all()]) - get_groups.short_description = _('recipients') + def get_recipients(self): + recipients = [g.name for g in self.to_groups.all()] + if self.to_memberlist is not None: + recipients.append(self.to_memberlist.name) + return ", ".join(recipients) + get_recipients.short_description = _('recipients') def submit(self): """Sends the mail to the specified group of members""" @@ -54,10 +63,15 @@ class Message(models.Model): if not member.gets_newsletter: continue members.add(member) + if self.to_memberlist is not None: + for memberonlist in self.to_memberlist.memberonlist_set.all(): + if memberonlist.member.gets_newsletter: + members.add(memberonlist.member) attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) if a.f.name] success = send(self.subject, get_content(self.content), - self.from_addr, [member.email for member in members], + self.from_addr, + set([member.email for member in members]), attachments=attach) for a in Attachment.objects.filter(msg__id=self.pk): if a.f.name: @@ -78,6 +92,21 @@ class Message(models.Model): ) +class MessageForm(forms.ModelForm): + + class Meta: + model = Message + exclude = [] + + def clean(self): + group = self.cleaned_data.get('to_groups') + memberlist = self.cleaned_data.get('to_memberlist') + print("group", group, "memberlist", memberlist) + if not group and memberlist is None: + raise ValidationError(_('Either a group is required or a ' + 'memberlist as recipient')) + + class Attachment(models.Model): """Represents an attachment to an email""" msg = models.ForeignKey(Message, on_delete=models.CASCADE) From 14d7acc2f8c87a31ae556b74bf99c7db53dc81c5 Mon Sep 17 00:00:00 2001 From: erichhasl Date: Sun, 12 Mar 2017 19:30:20 +0100 Subject: [PATCH 2/5] fix bad recipient bug --- jdav_web/mailer/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index ceb619d..0d48049 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -71,7 +71,7 @@ class Message(models.Model): if a.f.name] success = send(self.subject, get_content(self.content), self.from_addr, - set([member.email for member in members]), + [member.email for member in members], attachments=attach) for a in Attachment.objects.filter(msg__id=self.pk): if a.f.name: From c56bec04f99060a94c49b2b8fd57764e87aee889 Mon Sep 17 00:00:00 2001 From: erichhasl Date: Sun, 12 Mar 2017 21:33:13 +0100 Subject: [PATCH 3/5] send mail to jugendleiter of member list --- jdav_web/mailer/admin.py | 24 ++++++++++++++---------- jdav_web/mailer/mailutils.py | 10 ++++++++-- jdav_web/mailer/models.py | 26 +++++++++++--------------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/jdav_web/mailer/admin.py b/jdav_web/mailer/admin.py index db8a265..003045d 100644 --- a/jdav_web/mailer/admin.py +++ b/jdav_web/mailer/admin.py @@ -6,6 +6,7 @@ from django.db import models from django import forms from .models import Message, Attachment, MessageForm +from .mailutils import NOT_SENT, PARTLY_SENT class AttachmentInline(admin.StackedInline): @@ -29,8 +30,7 @@ class MessageAdmin(admin.ModelAdmin): print("calling send_message") if request.POST.get('confirmed'): for msg in queryset: - msg.submit() - self.message_user(request, _("Message sent")) + submit_message(msg, request) else: context = { 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, @@ -42,19 +42,23 @@ class MessageAdmin(admin.ModelAdmin): def response_change(self, request, obj): if "_send" in request.POST: - if not obj.submit(): - messages.error(request, _("Failed to send message")) - else: - messages.info(request, _("Successfully sent message")) + submit_message(obj, request) return super(MessageAdmin, self).response_change(request, obj) def response_add(self, request, obj): if "_send" in request.POST: - if not obj.submit(): - messages.error(request, _("Failed to send message")) - else: - messages.info(request, _("Successfully sent message")) + submit_message(obj, request) return super(MessageAdmin, self).response_add(request, obj) +def submit_message(msg, request): + success = msg.submit() + if success == NOT_SENT: + messages.error(request, _("Failed to send message")) + elif success == PARTLY_SENT: + messages.warning(request, _("Failed to send some messages")) + else: + messages.info(request, _("Successfully sent message")) + + admin.site.register(Message, MessageAdmin) diff --git a/jdav_web/mailer/mailutils.py b/jdav_web/mailer/mailutils.py index 8878b81..cab4fa6 100644 --- a/jdav_web/mailer/mailutils.py +++ b/jdav_web/mailer/mailutils.py @@ -1,8 +1,12 @@ from django.core.mail import EmailMessage +NOT_SENT, SENT, PARTLY_SENT = 0, 1, 2 + + def send(subject, content, sender, recipients, reply_to=None, attachments=None): + failed, succeeded = False, False if type(recipients) != list: recipients = [recipients] if reply_to is not None: @@ -18,9 +22,11 @@ def send(subject, content, sender, recipients, reply_to=None, email.send() except Exception as e: print("Error when sending mail:", e) - return False + failed = True else: - return True + succeeded = True + return NOT_SENT if failed and not succeeded else SENT if not failed\ + and succeeded else PARTLY_SENT def get_content(content): diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index 0d48049..3c3e49b 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -2,7 +2,7 @@ from django.db import models from django.core.exceptions import ValidationError from django import forms from django.utils.translation import ugettext_lazy as _ -from .mailutils import send, get_content +from .mailutils import send, get_content, SENT, PARTLY_SENT import os @@ -57,32 +57,28 @@ class Message(models.Model): def submit(self): """Sends the mail to the specified group of members""" members = set() - for group in self.to_groups.all(): - group_members = group.member_set.all() - for member in group_members: - if not member.gets_newsletter: - continue - members.add(member) + groups = [gr.member_set.all() for gr in self.to_groups.all()] + members.update([m for gr in groups for m in gr]) if self.to_memberlist is not None: - for memberonlist in self.to_memberlist.memberonlist_set.all(): - if memberonlist.member.gets_newsletter: - members.add(memberonlist.member) + members.update([mol.member for mol in + self.to_memberlist.memberonlist_set.all()]) + members.update(self.to_memberlist.jugendleiter.all()) + filtered = [m for m in members if m.gets_newsletter] + print("sending mail to", filtered) attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) if a.f.name] success = send(self.subject, get_content(self.content), self.from_addr, - [member.email for member in members], + [member.email for member in filtered], attachments=attach) for a in Attachment.objects.filter(msg__id=self.pk): if a.f.name: os.remove(a.f.path) a.delete() - if success: + if success == SENT or success == PARTLY_SENT: self.sent = True self.save() - return True - else: - return False + return success class Meta: verbose_name = _('message') From eb54915f163acb44a0e2451e2bf5c6b101d9d27f Mon Sep 17 00:00:00 2001 From: erichhasl Date: Sun, 12 Mar 2017 21:41:40 +0100 Subject: [PATCH 4/5] reply to field --- jdav_web/mailer/models.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index 3c3e49b..3aa1033 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -42,6 +42,10 @@ class Message(models.Model): verbose_name=_('to member list'), blank=True, null=True) + reply_to = models.ForeignKey('members.Member', + verbose_name=_('reply to'), + blank=True, + null=True) sent = models.BooleanField(_('sent'), default=False) def __str__(self): @@ -70,7 +74,8 @@ class Message(models.Model): success = send(self.subject, get_content(self.content), self.from_addr, [member.email for member in filtered], - attachments=attach) + attachments=attach, + reply_to=self.reply_to.email if self.reply_to else None) for a in Attachment.objects.filter(msg__id=self.pk): if a.f.name: os.remove(a.f.path) From 3c01f835178f4a658e5f50d21232e6ce1e80bda9 Mon Sep 17 00:00:00 2001 From: erichhasl Date: Sun, 12 Mar 2017 22:16:00 +0100 Subject: [PATCH 5/5] send individual mails to some members --- jdav_web/mailer/admin.py | 2 +- jdav_web/mailer/models.py | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/jdav_web/mailer/admin.py b/jdav_web/mailer/admin.py index 003045d..d03a4ba 100644 --- a/jdav_web/mailer/admin.py +++ b/jdav_web/mailer/admin.py @@ -25,9 +25,9 @@ class MessageAdmin(admin.ModelAdmin): inlines = [AttachmentInline] actions = ['send_message'] form = MessageForm + filter_horizontal = ('to_members',) def send_message(self, request, queryset): - print("calling send_message") if request.POST.get('confirmed'): for msg in queryset: submit_message(msg, request) diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index 3aa1033..1f2a3a8 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -2,6 +2,7 @@ from django.db import models from django.core.exceptions import ValidationError from django import forms from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext from .mailutils import send, get_content, SENT, PARTLY_SENT import os @@ -42,10 +43,14 @@ class Message(models.Model): verbose_name=_('to member list'), blank=True, null=True) + to_members = models.ManyToManyField('members.Member', + verbose_name=_('to member'), + blank=True) reply_to = models.ForeignKey('members.Member', verbose_name=_('reply to'), blank=True, - null=True) + null=True, + related_name='reply_to') sent = models.BooleanField(_('sent'), default=False) def __str__(self): @@ -55,14 +60,23 @@ class Message(models.Model): recipients = [g.name for g in self.to_groups.all()] if self.to_memberlist is not None: recipients.append(self.to_memberlist.name) + 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(ugettext('Some other members')) return ", ".join(recipients) get_recipients.short_description = _('recipients') def submit(self): """Sends the mail to the specified group of members""" + # recipients members = set() + # get all the members of the selected groups groups = [gr.member_set.all() for gr in self.to_groups.all()] members.update([m for gr in groups for m in gr]) + # get all the individually picked members + members.update(self.to_members.all()) + # get all the members of the selected member list if self.to_memberlist is not None: members.update([mol.member for mol in self.to_memberlist.memberonlist_set.all()]) @@ -102,16 +116,15 @@ class MessageForm(forms.ModelForm): def clean(self): group = self.cleaned_data.get('to_groups') memberlist = self.cleaned_data.get('to_memberlist') - print("group", group, "memberlist", memberlist) - if not group and memberlist is None: - raise ValidationError(_('Either a group is required or a ' - 'memberlist as recipient')) + members = self.cleaned_data.get('to_members') + if not group and memberlist is None and not members: + raise ValidationError(_('Either a group, a memberlist or at least' + ' one member is required as recipient')) class Attachment(models.Model): """Represents an attachment to an email""" msg = models.ForeignKey(Message, on_delete=models.CASCADE) - print("attachment class") # file (not naming it file because of builtin) f = RestrictedFileField(_('file'), upload_to='attachments',