import_mailling_list.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import sys
  4. from django.core.management.base import BaseCommand, CommandError
  5. from django.db import transaction
  6. from coin.members.models import Member
  7. from maillists.models import (
  8. MaillingList,
  9. MaillingListSubscription,
  10. skip_maillist_sync,
  11. )
  12. """Import a text file of email addresses into mailling list subscription"
  13. Create a new mailling-list subscribing the provided addresses. The script will
  14. try to map email addresses to members, and stop if some addresses do not belong
  15. to any member.
  16. This command takes care to avoid triggering a sync per single subscription.
  17. """
  18. class Command(BaseCommand):
  19. help = __doc__
  20. def add_arguments(self, parser):
  21. parser.add_argument(
  22. 'subscribers_file',
  23. help="The text file with the subscribed email addresses, one per line",
  24. )
  25. parser.add_argument(
  26. '--email',
  27. help='Mail address of the list',
  28. required=True,
  29. )
  30. parser.add_argument(
  31. '--verbose-name',
  32. help='The full human-targeted name of the list',
  33. required=True,
  34. )
  35. parser.add_argument(
  36. '--force',
  37. help='Import email adresses skipping those who do not belong to any member',
  38. action='store_true',
  39. default=False
  40. )
  41. parser.add_argument(
  42. '--dry-run',
  43. help='Do not write anything to database, just parse the file and show unknown addresses',
  44. action='store_true',
  45. default=False
  46. )
  47. @staticmethod
  48. def _iter_emails(filename):
  49. with open(filename) as f:
  50. for l in f.readlines():
  51. email = l.strip()
  52. if len(email) > 0:
  53. yield l.strip()
  54. @staticmethod
  55. def _get_unknown_email(emails):
  56. for email in emails:
  57. try:
  58. Member.objects.get(email=email)
  59. except Member.DoesNotExist:
  60. yield email
  61. @transaction.atomic
  62. def handle(self, subscribers_file, email, verbose_name, force, dry_run, *args, **kwargs):
  63. ml = MaillingList.objects.create(
  64. short_name=email.split('@')[0],
  65. email=email,
  66. description='À RENSEIGNER',
  67. verbose_name=verbose_name,
  68. )
  69. unknown_emails = []
  70. with skip_maillist_sync():
  71. for email in self._iter_emails(subscribers_file):
  72. try:
  73. member = Member.objects.get(email=email)
  74. except Member.DoesNotExist:
  75. unknown_emails.append(email)
  76. else:
  77. mls_exists = MaillingListSubscription.objects.filter(
  78. member=member,
  79. maillinglist=ml,
  80. ).exists()
  81. # Not using get_or_create because we want to set skip_sync
  82. # before saving
  83. if not mls_exists:
  84. mls = MaillingListSubscription(
  85. member=member,
  86. maillinglist=ml,
  87. )
  88. mls.skip_sync = True
  89. mls.save()
  90. # Do it once… (db will be rollback if it fails)
  91. sys.stdout.write('Pousse la liste sur le serveur… ',)
  92. ml.sync_to_list_server()
  93. print('OK')
  94. if (len(unknown_emails) > 0) and not force:
  95. print('ERREUR : Ces adresses ne correspondent à aucun membre')
  96. for email in unknown_emails:
  97. print(email)
  98. raise CommandError(
  99. "Rien n'a été créé en base, utiliser --force au besoin.")
  100. elif force or len(unknown_emails) == 0:
  101. if dry_run:
  102. # exception triggers rollback
  103. raise CommandError(
  104. "--dry-run est utilisée, rien n'a été écrit en base")