use new participant lists in mailer application, allow custom email addresses as reply to

v1-0-stable
Christian Merten 5 years ago
parent f321cdf82e
commit 70a9d50da5

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-01-24 23:21+0100\n"
"POT-Creation-Date: 2020-09-24 17:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -22,26 +22,6 @@ msgstr ""
msgid "Startpage"
msgstr "Startseite"
#: templates/admin/base.html:32
msgid "Welcome,"
msgstr "Willkommen"
#: templates/admin/base.html:40
msgid "Documentation"
msgstr "Dokumentation"
#: templates/admin/base.html:44
msgid "Change password"
msgstr "Passwort ändern"
#: templates/admin/base.html:46
msgid "Log out"
msgstr "Abmelden"
#: templates/admin/base.html:56
msgid "Home"
msgstr "Start"
#: utils.py:26
msgid "Filetype not supported."
msgstr "Dateityp nicht unterstützt."
@ -50,6 +30,21 @@ msgstr "Dateityp nicht unterstützt."
msgid "Please keep filesize under {}. Current filesize: {}"
msgstr "Maximale Dateigröße {}. Aktuelle Dateigröße: {}."
#~ msgid "Welcome,"
#~ msgstr "Willkommen"
#~ msgid "Documentation"
#~ msgstr "Dokumentation"
#~ msgid "Change password"
#~ msgstr "Passwort ändern"
#~ msgid "Log out"
#~ msgstr "Abmelden"
#~ msgid "Home"
#~ msgstr "Start"
#~ msgid "View site"
#~ msgstr "Seite anzeigen"

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-01-24 23:21+0100\n"
"POT-Creation-Date: 2020-09-24 17:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -38,97 +38,105 @@ msgstr "Email wurde erfolgreich verschickt"
msgid "mailer"
msgstr "Verteiler"
#: mailer/models.py:21
#: mailer/models.py:18
msgid "Only alphanumeric characters are allowed"
msgstr "Nur Buchstaben und Zahlen erlaubt"
#: mailer/models.py:23
msgid "name"
msgstr "Name"
#: mailer/models.py:25
msgid "Forward to"
msgstr "Weiterleitung"
#: mailer/models.py:35
msgid "email address"
msgstr "Email-Adresse"
#: mailer/models.py:36
msgid "email addresses"
msgstr "Email-Adressen"
#: mailer/models.py:42
msgid "subject"
msgstr "Betreff"
#: mailer/models.py:22
#: mailer/models.py:43
msgid "content"
msgstr "Inhalt"
#: mailer/models.py:24
#: mailer/models.py:45
msgid "to group"
msgstr "An Gruppe"
#: mailer/models.py:27
msgid "to member list"
msgstr "An Teilnehmerliste"
#: mailer/models.py:48
msgid "to freizeit"
msgstr "An Freizeit"
#: mailer/models.py:52
msgid "to notes list"
msgstr "An Notizliste"
#: mailer/models.py:31
#: mailer/models.py:56
msgid "to member"
msgstr "An Teilnehmer"
#: mailer/models.py:34
msgid "reply to"
msgstr "Antwort an"
#: mailer/models.py:59
msgid "reply to participant"
msgstr "Antwort an Teilnehmer"
#: mailer/models.py:37
#: mailer/models.py:63
msgid "reply to custom email address"
msgstr "Antwort an Email-Adresse"
#: mailer/models.py:66
msgid "sent"
msgstr "Gesendet"
#: mailer/models.py:49
#: mailer/models.py:80
msgid "Some other members"
msgstr "Andere Teilnehmer"
#: mailer/models.py:51
#: mailer/models.py:82
msgid "recipients"
msgstr "Empfänger"
#: mailer/models.py:102
#: mailer/models.py:138
msgid "message"
msgstr "Nachricht"
#: mailer/models.py:103
#: mailer/models.py:139
msgid "messages"
msgstr "Nachrichten"
#: mailer/models.py:105
#: mailer/models.py:141
msgid "Can submit mails"
msgstr "Kann Mails verschicken"
#: mailer/models.py:120
#: mailer/models.py:157
msgid ""
"Either a group, a memberlist or at least one member is required as recipient"
msgstr ""
"Es muss entweder eine Gruppe, eine Teilnehmerliste oder mindestens ein "
"Teilnehmer als Empfänger ausgewählt werden."
#: mailer/models.py:127
#: mailer/models.py:164
msgid "file"
msgstr "Datei"
#: mailer/models.py:133
#: mailer/models.py:170
msgid "Empty"
msgstr "Leer"
#: mailer/models.py:136
#: mailer/models.py:173
msgid "attachment"
msgstr "Anhang"
#: mailer/models.py:137
#: mailer/models.py:174
msgid "attachments"
msgstr "Anhänge"
#: mailer/models.py:140
msgid "Only alphanumeric characters are allowed"
msgstr "Nur Buchstaben und Zahlen erlaubt"
#: mailer/models.py:145
msgid "name"
msgstr "Name"
#: mailer/models.py:147
msgid "Forward to"
msgstr "Weiterleitung"
#: mailer/models.py:157
msgid "email address"
msgstr "Email-Adresse"
#: mailer/models.py:158
msgid "email addresses"
msgstr "Email-Adressen"
#: mailer/templates/mailer/change_form.html:11
msgid "Save and send mail"
msgstr "Speichern und Email senden"
@ -247,6 +255,9 @@ msgstr "Bitte jedes Feld ausfüllen!"
msgid "Member already exists"
msgstr "Mitglied schon vorhanden"
#~ msgid "reply to"
#~ msgstr "Antwort an"
#~ msgid "Message sent"
#~ msgstr "Nachricht gesendet"

@ -20,7 +20,8 @@ class Command(BaseCommand):
message_id = int(options['message_id'])
message = Message.objects.get(pk=message_id)
if message.reply_to:
replies = message.reply_to.all()
replies = list(message.reply_to.all())
replies.extend(message.reply_to_email_address.all())
except (Message.DoesNotExist, ValueError):
extracted = re.match("^([Ww][Gg]: *|[Ff][Ww]: *|[Rr][Ee]: *|[Aa][Ww]: *)* *(.*)$",
options['subject']).group(2)
@ -29,6 +30,7 @@ class Command(BaseCommand):
message = msgs.all()[0]
if message.reply_to:
replies = message.reply_to.all()
replies.extend(message.reply_to_email_address.all())
except (Message.DoesNotExist, ValueError, IndexError):
pass

@ -15,6 +15,27 @@ SENDING_ADDRESS = mail_root
HOST = os.environ.get('DJANGO_ALLOWED_HOST', 'localhost:8000').split(",")[0]
alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', _('Only alphanumeric characters 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])
to_members = models.ManyToManyField('members.Member',
verbose_name=_('Forward to'))
@property
def email(self):
return "{0}@{1}".format(self.name, HOST)
def __str__(self):
return self.email
class Meta:
verbose_name = _('email address')
verbose_name_plural = _('email addresses')
# Create your models here.
class Message(models.Model):
"""Represents a message that can be sent to some members"""
@ -23,17 +44,25 @@ class Message(models.Model):
to_groups = models.ManyToManyField('members.Group',
verbose_name=_('to group'),
blank=True)
to_memberlist = models.ForeignKey('members.Freizeit',
verbose_name=_('to member list'),
to_freizeit = models.ForeignKey('members.Freizeit',
verbose_name=_('to freizeit'),
blank=True,
null=True)
to_notelist = models.ForeignKey('members.MemberNoteList',
verbose_name=_('to notes list'),
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'),
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)
def __str__(self):
@ -41,8 +70,10 @@ class Message(models.Model):
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)
if self.to_freizeit is not None:
recipients.append(self.to_freizeit.name)
if self.to_notelist is not None:
recipients.append(self.to_notelist.title)
if 3 > self.to_members.count() > 0:
recipients.extend([m.name for m in self.to_members.all()])
elif self.to_members.count() > 2:
@ -59,11 +90,15 @@ class Message(models.Model):
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:
# 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(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_memberlist.memberonlist_set.all()])
members.update(self.to_memberlist.jugendleiter.all())
self.to_notelist.membersonlist.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)
@ -76,8 +111,9 @@ class Message(models.Model):
self.subject = self.subject.replace('_', ' ')
# generate message id
message_id = "<{}@jdav-ludwigsburg.de>".format(self.pk)
# reply to adresses
# reply to addresses
reply_to = [jl.association_email for jl in self.reply_to.all()]
reply_to.extend([ml.email for ml in self.reply_to_email_address.all()])
try:
success = send(self.subject, get_content(self.content),
SENDING_ADDRESS,
@ -114,9 +150,10 @@ class MessageForm(forms.ModelForm):
def clean(self):
group = self.cleaned_data.get('to_groups')
memberlist = self.cleaned_data.get('to_memberlist')
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 memberlist is None and not members:
if not group and memberlist 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'))
@ -135,24 +172,3 @@ class Attachment(models.Model):
class Meta:
verbose_name = _('attachment')
verbose_name_plural = _('attachments')
alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', _('Only alphanumeric characters 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])
to_members = models.ManyToManyField('members.Member',
verbose_name=_('Forward to'))
@property
def email(self):
return "{0}@{1}".format(self.name, HOST)
def __str__(self):
return self.email
class Meta:
verbose_name = _('email address')
verbose_name_plural = _('email addresses')

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-01-24 23:21+0100\n"
"POT-Creation-Date: 2020-09-24 17:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-01-24 23:21+0100\n"
"POT-Creation-Date: 2020-09-24 17:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,213 +18,218 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: members/admin.py:26 members/models.py:73
#: members/admin.py:27 members/models.py:75
msgid "Registration complete"
msgstr "Anmeldung vollständig"
#: members/admin.py:32
#: members/admin.py:33
msgid "True"
msgstr "Ja"
#: members/admin.py:33
#: members/admin.py:34
msgid "False"
msgstr "Nein"
#: members/admin.py:34
#: members/admin.py:35
msgid "All"
msgstr "Alle"
#: members/admin.py:94
#: members/admin.py:95
msgid "Compose new mail to selected members"
msgstr "Neue Nachricht an ausgewählte Teilnehmer verfassen"
#: members/admin.py:110
#: members/admin.py:111
msgid "Difficulty"
msgstr "Schwierigkeit"
#: members/admin.py:114
#: members/admin.py:115
msgid "Tour type"
msgstr "Art der Tour"
#: members/admin.py:257
#: members/admin.py:401
msgid "Convert to PDF"
msgstr "Kriseninterventionsliste erstellen"
#: members/admin.py:366
#: members/admin.py:510
msgid "Generate overview"
msgstr "Hinweise für Jugendleiter erstellen"
#: members/apps.py:7 members/models.py:129
#: members/apps.py:7 members/models.py:157
msgid "members"
msgstr "Teilnehmer"
#: members/models.py:20
#: members/models.py:22
msgid "Name"
msgstr "Name"
#: members/models.py:21
#: members/models.py:23
msgid "Description"
msgstr "Beschreibung"
#: members/models.py:27 members/models.py:150
#: members/models.py:29 members/models.py:178 members/models.py:257
#: members/templates/members/change_member.html:17
msgid "Activity"
msgstr "Aktivität"
#: members/models.py:28
#: members/models.py:30
msgid "Activities"
msgstr "Aktivitäten"
#: members/models.py:36
#: members/models.py:38
msgid "name"
msgstr "Name"
#: members/models.py:38
#: members/models.py:40
msgid "minimum age (years)"
msgstr "Mindestalter (Jahre)"
#: members/models.py:45 members/models.py:66
#: members/models.py:47 members/models.py:68
msgid "group"
msgstr "Gruppe"
#: members/models.py:46
#: members/models.py:48
msgid "groups"
msgstr "Gruppen"
#: members/models.py:54
#: members/models.py:56
msgid "prename"
msgstr "Vorname"
#: members/models.py:55
#: members/models.py:57
msgid "last name"
msgstr "Nachname"
#: members/models.py:56
#: members/models.py:58
msgid "street"
msgstr "Straße"
#: members/models.py:57
#: members/models.py:59
msgid "Postcode"
msgstr "PLZ"
#: members/models.py:59
#: members/models.py:61
msgid "town"
msgstr "Stadt"
#: members/models.py:60
#: members/models.py:62
msgid "phone number"
msgstr "Telefonnummer"
#: members/models.py:61
#: members/models.py:63
msgid "parents phone number"
msgstr "Telefonnummer der Eltern"
#: members/models.py:64
#: members/models.py:66
msgid "Parents' Email"
msgstr "Email der Eltern"
#: members/models.py:65
#: members/models.py:67
msgid "birth date"
msgstr "Geburtsdatum"
#: members/models.py:67
#: members/models.py:69
msgid "receives newsletter"
msgstr "Erhält den Newsletter"
#: members/models.py:71
#: members/models.py:73
msgid "comments"
msgstr "Kommentare"
#: members/models.py:72
#: members/models.py:74
msgid "created"
msgstr "erstellt"
#: members/models.py:74
#: members/models.py:76
msgid "registration form"
msgstr "Anmeldeformular"
#: members/models.py:125 members/models.py:217
#: members/models.py:153 members/models.py:326
msgid "Group"
msgstr "Gruppe"
#: members/models.py:128
#: members/models.py:156
msgid "member"
msgstr "Teilnehmer"
#: members/models.py:152
#: members/models.py:180 members/models.py:259
msgid "Place"
msgstr "Ort"
#: members/models.py:153
#: members/models.py:181 members/models.py:260
msgid "Destination (optional)"
msgstr "Ziel (optional)"
#: members/models.py:155 members/models.py:213
#: members/models.py:183 members/models.py:262 members/models.py:304
#: members/models.py:322
msgid "Date"
msgstr "Datum"
#: members/models.py:156
#: members/models.py:184 members/models.py:263
msgid "End (optional)"
msgstr "Ende"
#: members/models.py:158
#: members/models.py:186 members/models.py:265
msgid "Groups"
msgstr "Gruppen"
#: members/models.py:166
#: members/models.py:194 members/models.py:273
msgid "Categories"
msgstr "Kategorien"
#: members/models.py:167
#: members/models.py:195 members/models.py:274
msgid "easy"
msgstr "leicht"
#: members/models.py:167
#: members/models.py:195 members/models.py:274
msgid "medium"
msgstr "mittel"
#: members/models.py:167
#: members/models.py:195 members/models.py:274
msgid "hard"
msgstr "schwer"
#: members/models.py:176
#: members/models.py:204
msgid "Memberlist"
msgstr "Teilnehmerliste"
#: members/models.py:177
#: members/models.py:205
msgid "Memberlists"
msgstr "Teilnehmerlisten"
#: members/models.py:195 members/models.py:203 members/models.py:248
#: members/models.py:255
#: members/models.py:223 members/models.py:231 members/models.py:239
#: members/models.py:250 members/models.py:357 members/models.py:364
msgid "Member"
msgstr "Teilnehmer"
#: members/models.py:197
#: members/models.py:225 members/models.py:244
msgid "Comment"
msgstr "Kommentar"
#: members/models.py:204 members/models.py:256
#: members/models.py:232 members/models.py:251 members/models.py:365
msgid "Members"
msgstr "Teilnehmer"
#: members/models.py:214
#: members/models.py:303
msgid "Title"
msgstr ""
#: members/models.py:323
msgid "Location"
msgstr "Ort"
#: members/models.py:215
#: members/models.py:324
msgid "Topic"
msgstr "Thema"
#: members/models.py:239
#: members/models.py:348
msgid "Jugendleiter"
msgstr "Jugendleiter"
#: members/models.py:242
#: members/models.py:351
msgid "Klettertreff"
msgstr "Klettertreff"
#: members/models.py:243
#: members/models.py:352
msgid "Klettertreffs"
msgstr "Klettertreffs"

@ -161,15 +161,15 @@ class Member(models.Model):
# get skills by summing up all the activities taken part in
skills = {}
for kind in ActivityCategory.objects.all():
lists = MemberList.objects.filter(activity=kind,
oldmemberonlist__member=self)
lists = Freizeit.objects.filter(activity=kind,
membersonlist__member=self)
skills[kind.name] = sum([l.difficulty * 3 for l in lists
if l.date < datetime.now().date()])
return skills
def get_activities(self):
# get activity overview
return MemberList.objects.filter(oldmemberonlist__member=self)
return Freizeit.objects.filter(membersonlist__member=self)
class MemberList(models.Model):
@ -293,7 +293,7 @@ class Freizeit(models.Model):
return "Gemeinschaftstour"
def get_absolute_url(self):
return reverse('admin:members_memberlist_change', args=[str(self.id)])
return reverse('admin:members_freizeit_change', args=[str(self.id)])
class MemberNoteList(models.Model):

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-01-24 23:21+0100\n"
"POT-Creation-Date: 2020-09-24 17:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

Loading…
Cancel
Save