|
@@ -0,0 +1,133 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+
|
|
|
+from __future__ import unicode_literals
|
|
|
+
|
|
|
+import subprocess
|
|
|
+
|
|
|
+from django.conf import settings
|
|
|
+from django.db import models
|
|
|
+from django.db.models.signals import pre_save, post_save, post_delete
|
|
|
+from django.dispatch import receiver
|
|
|
+
|
|
|
+from coin.members.models import Member
|
|
|
+
|
|
|
+
|
|
|
+class SyncCommandError(SystemError):
|
|
|
+ pass
|
|
|
+
|
|
|
+class MaillingListSubscription(models.Model):
|
|
|
+ member = models.ForeignKey(Member, verbose_name='membre')
|
|
|
+ maillinglist = models.ForeignKey('MaillingList', verbose_name='liste mail')
|
|
|
+
|
|
|
+ class Meta:
|
|
|
+ verbose_name = 'abonnement à une liste mail'
|
|
|
+ verbose_name_plural = 'abonnements aux listes mail'
|
|
|
+ unique_together = ('member', 'maillinglist')
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ return str(self.maillinglist)
|
|
|
+
|
|
|
+class MaillingList(models.Model):
|
|
|
+ short_name = models.CharField(
|
|
|
+ 'identifiant technique', max_length=50,
|
|
|
+ help_text=(
|
|
|
+ "c'est l'identifiant qui servira à "
|
|
|
+ "communiquer avec le serveur de liste mail "
|
|
|
+ "(typiquement, la partie avant le \"@\" dans l'adress )"
|
|
|
+ )
|
|
|
+ )
|
|
|
+ email = models.EmailField("adresse mail d'envoi")
|
|
|
+ verbose_name = models.CharField(
|
|
|
+ 'nom complet', max_length=130,
|
|
|
+ help_text="Nom affiché dans l'interface membre"
|
|
|
+ )
|
|
|
+ description = models.TextField()
|
|
|
+ subscribers = models.ManyToManyField(
|
|
|
+ Member, related_name='subscribed_maillinglists',
|
|
|
+ through=MaillingListSubscription,
|
|
|
+ verbose_name='abonné·e·s', blank=True)
|
|
|
+
|
|
|
+ class Meta:
|
|
|
+ verbose_name = 'liste mail'
|
|
|
+ verbose_name_plural = 'listes mail'
|
|
|
+
|
|
|
+ def __unicode__(self):
|
|
|
+ return '{} ({})'.format(self.verbose_name, self.email)
|
|
|
+
|
|
|
+ def as_text_listing(self):
|
|
|
+ """ One subscriber email per line
|
|
|
+ """
|
|
|
+ return '\n'.join(
|
|
|
+ self.subscribers.values_list('email', flat=True))
|
|
|
+
|
|
|
+ def sync_to_list_server(self, force_clear=False):
|
|
|
+ if not settings.MAILLIST_SYNC_COMMAND:
|
|
|
+ raise ValueError('You should define MAILLIST_SYNC_COMMAND'
|
|
|
+ ' setting to use maillist module')
|
|
|
+ else:
|
|
|
+ cmd = settings.MAILLIST_SYNC_COMMAND.format(
|
|
|
+ email=self.email,
|
|
|
+ short_name=self.short_name,
|
|
|
+ )
|
|
|
+ p = subprocess.Popen(
|
|
|
+ cmd, shell=True,
|
|
|
+ stdin=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
+ if force_clear:
|
|
|
+ text_listing = ''
|
|
|
+ else:
|
|
|
+ text_listing = self.as_text_listing()
|
|
|
+
|
|
|
+ out_stdout, out_stderr = p.communicate(text_listing)
|
|
|
+ if p.returncode != 0:
|
|
|
+ raise SyncCommandError(
|
|
|
+ "Erreur à l'appel de la commande : \"{}\"".format(
|
|
|
+ out_stderr.decode('utf-8')))
|
|
|
+
|
|
|
+
|
|
|
+@receiver(post_save, sender=MaillingListSubscription)
|
|
|
+def push_new_subscription(sender, instance, created, raw, *args, **kwargs):
|
|
|
+ if raw:
|
|
|
+ print("The synchronization of mailling list with Coin was not performed, please launch it by hand in the admin interface.")
|
|
|
+ else:
|
|
|
+ instance.maillinglist.sync_to_list_server()
|
|
|
+
|
|
|
+@receiver(post_delete, sender=MaillingListSubscription)
|
|
|
+def push_remove_subscription(sender, instance, *args, **kwargs):
|
|
|
+ instance.maillinglist.sync_to_list_server()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+@receiver(pre_save, sender=Member)
|
|
|
+def store_previous_email(sender, instance, *args, **kwargs):
|
|
|
+ """Record the email address for post_save handler
|
|
|
+
|
|
|
+ update_an_email_address needs the old email address for comparison, but
|
|
|
+ this information is not available at post_save stage.
|
|
|
+ """
|
|
|
+ member = instance
|
|
|
+
|
|
|
+ # if not, this is a user creation, nothing to do
|
|
|
+ if member.pk:
|
|
|
+ old_member = Member.objects.get(pk=member.pk)
|
|
|
+ member._previous_email = old_member.email
|
|
|
+
|
|
|
+
|
|
|
+@receiver(post_save, sender=Member)
|
|
|
+def update_an_email_address(sender, instance, *args, **kwargs):
|
|
|
+ """Check if the member email has changed and sync mail lists if so.
|
|
|
+
|
|
|
+ We do that at post_save stage because we need the new information to be
|
|
|
+ recorded in database, otherwise, sync_list_to_server() would use the old
|
|
|
+ email.
|
|
|
+ """
|
|
|
+ member = instance
|
|
|
+ old_email = getattr(member, '_previous_email', None)
|
|
|
+
|
|
|
+ if old_email and (old_email != member.email):
|
|
|
+ for maillist in member.subscribed_maillinglists.all():
|
|
|
+ maillist.sync_to_list_server()
|
|
|
+ # Error handling ???
|
|
|
+ # try:
|
|
|
+ # except SyncCommandError as e:
|
|
|
+ # print("error", e)
|
|
|
+ # we cannot send a message because we don't have the request
|