Compare commits
3 commits
master
...
Kerl/mail_
Author | SHA1 | Date | |
---|---|---|---|
|
727626cadd | ||
|
12c10847e7 | ||
|
2c53344f1f |
3 changed files with 100 additions and 27 deletions
33
bda/admin.py
33
bda/admin.py
|
@ -1,6 +1,5 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from custommail.shortcuts import send_mass_custom_mail
|
|
||||||
from dal.autocomplete import ModelSelect2
|
from dal.autocomplete import ModelSelect2
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
@ -19,6 +18,7 @@ from bda.models import (
|
||||||
SpectacleRevente,
|
SpectacleRevente,
|
||||||
Tirage,
|
Tirage,
|
||||||
)
|
)
|
||||||
|
from utils.mailutils import SendMassMailRecipientRefused, send_mass_custom_mail_wrapper
|
||||||
|
|
||||||
|
|
||||||
class ReadOnlyMixin(object):
|
class ReadOnlyMixin(object):
|
||||||
|
@ -142,17 +142,28 @@ class ParticipantAdmin(ReadOnlyMixin, admin.ModelAdmin):
|
||||||
context["places"] = attribs
|
context["places"] = attribs
|
||||||
print(context)
|
print(context)
|
||||||
datatuple.append((shortname, context, "bda@ens.fr", [member.user.email]))
|
datatuple.append((shortname, context, "bda@ens.fr", [member.user.email]))
|
||||||
send_mass_custom_mail(datatuple)
|
|
||||||
count = len(queryset.all())
|
count = len(queryset.all())
|
||||||
if count == 1:
|
try:
|
||||||
message_bit = "1 membre a"
|
send_mass_custom_mail_wrapper(datatuple)
|
||||||
plural = ""
|
except SendMassMailRecipientRefused as exn:
|
||||||
else:
|
errors, = exn.args
|
||||||
message_bit = "%d membres ont" % count
|
faulty_emails = ", ".join(errors.keys())
|
||||||
plural = "s"
|
count -= len(errors)
|
||||||
self.message_user(
|
self.message_user(
|
||||||
request, "%s été informé%s avec succès." % (message_bit, plural)
|
request,
|
||||||
)
|
"Les emails suivant causent des erreurs: {}".format(faulty_emails),
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
if count == 1:
|
||||||
|
message_bit = "[1/{}] membre a".format(len(queryset.all()))
|
||||||
|
plural = ""
|
||||||
|
else:
|
||||||
|
message_bit = "[{}/{}] membres ont".format(count, queryset.all())
|
||||||
|
plural = "s"
|
||||||
|
self.message_user(
|
||||||
|
request, "%s été informé%s avec succès." % (message_bit, plural)
|
||||||
|
)
|
||||||
|
|
||||||
send_attribs.short_description = "Envoyer les résultats par mail"
|
send_attribs.short_description = "Envoyer les résultats par mail"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import random
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from custommail.models import CustomMail
|
from custommail.models import CustomMail
|
||||||
from custommail.shortcuts import send_mass_custom_mail
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
@ -12,6 +11,8 @@ from django.db import models
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.utils import formats, timezone
|
from django.utils import formats, timezone
|
||||||
|
|
||||||
|
from utils.mailutils import send_mass_custom_mail_wrapper
|
||||||
|
|
||||||
|
|
||||||
def get_generic_user():
|
def get_generic_user():
|
||||||
generic, _ = User.objects.get_or_create(
|
generic, _ = User.objects.get_or_create(
|
||||||
|
@ -125,10 +126,12 @@ class Spectacle(models.Model):
|
||||||
)
|
)
|
||||||
for member in members
|
for member in members
|
||||||
]
|
]
|
||||||
send_mass_custom_mail(datatuple)
|
try:
|
||||||
# On enregistre le fait que l'envoi a bien eu lieu
|
send_mass_custom_mail_wrapper(datatuple)
|
||||||
self.rappel_sent = timezone.now()
|
finally:
|
||||||
self.save()
|
# On enregistre le fait que l'envoi a bien eu lieu
|
||||||
|
self.rappel_sent = timezone.now()
|
||||||
|
self.save()
|
||||||
# On renvoie la liste des destinataires
|
# On renvoie la liste des destinataires
|
||||||
return members
|
return members
|
||||||
|
|
||||||
|
@ -343,10 +346,12 @@ class SpectacleRevente(models.Model):
|
||||||
)
|
)
|
||||||
for participant in inscrits
|
for participant in inscrits
|
||||||
]
|
]
|
||||||
send_mass_custom_mail(datatuple)
|
try:
|
||||||
self.notif_sent = True
|
send_mass_custom_mail_wrapper(datatuple)
|
||||||
self.notif_time = timezone.now()
|
finally:
|
||||||
self.save()
|
self.notif_sent = True
|
||||||
|
self.notif_time = timezone.now()
|
||||||
|
self.save()
|
||||||
|
|
||||||
def mail_shotgun(self):
|
def mail_shotgun(self):
|
||||||
"""
|
"""
|
||||||
|
@ -367,13 +372,15 @@ class SpectacleRevente(models.Model):
|
||||||
)
|
)
|
||||||
for participant in inscrits
|
for participant in inscrits
|
||||||
]
|
]
|
||||||
send_mass_custom_mail(datatuple)
|
try:
|
||||||
self.notif_sent = True
|
send_mass_custom_mail_wrapper(datatuple)
|
||||||
self.notif_time = timezone.now()
|
finally:
|
||||||
# Flag inutile, sauf si l'horloge interne merde
|
self.notif_sent = True
|
||||||
self.tirage_done = True
|
self.notif_time = timezone.now()
|
||||||
self.shotgun = True
|
# Flag inutile, sauf si l'horloge interne merde
|
||||||
self.save()
|
self.tirage_done = True
|
||||||
|
self.shotgun = True
|
||||||
|
self.save()
|
||||||
|
|
||||||
def tirage(self, send_mails=True):
|
def tirage(self, send_mails=True):
|
||||||
"""
|
"""
|
||||||
|
|
55
utils/mailutils.py
Normal file
55
utils/mailutils.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
from smtplib import SMTPRecipientsRefused
|
||||||
|
|
||||||
|
from custommail.shortcuts import send_mass_custom_mail
|
||||||
|
|
||||||
|
|
||||||
|
def drop_until(predicate, l):
|
||||||
|
"""
|
||||||
|
Drop the first elements of the list until we find the first element
|
||||||
|
satisfying the predicate, this element is also dropped.
|
||||||
|
"""
|
||||||
|
for i in range(len(l)):
|
||||||
|
if predicate(l[i]):
|
||||||
|
return l[i + 1 :]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def intersects(list1, list2):
|
||||||
|
""" Return True iff there is one element in common in the two lists """
|
||||||
|
return any(x in list2 for x in list1)
|
||||||
|
|
||||||
|
|
||||||
|
class SendMassMailRecipientRefused(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def send_mass_custom_mail_wrapper(datatuple, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Similar to custommail.shortcuts.send_mass_custom_mail but if an
|
||||||
|
SMTPRecipientsRefused exception is encountered, finish processing the datatuple
|
||||||
|
and only raise at the end of the list.
|
||||||
|
Thus, only the faulty emails won't be sent.
|
||||||
|
"""
|
||||||
|
to_be_sent = datatuple
|
||||||
|
in_error = []
|
||||||
|
|
||||||
|
while to_be_sent:
|
||||||
|
try:
|
||||||
|
send_mass_custom_mail(to_be_sent, *args, **kwargs)
|
||||||
|
to_be_sent = []
|
||||||
|
except SMTPRecipientsRefused as exn:
|
||||||
|
# A recipient error has been encountered:
|
||||||
|
# 1. drop already sent emails from the "to be sent" list
|
||||||
|
# 2. move the bogus email from the "to be sent" list to the "in error" list
|
||||||
|
# 3. try to send the remaining emails
|
||||||
|
refused_emails, = exn.args
|
||||||
|
|
||||||
|
def predicate(tuple):
|
||||||
|
__, __, __, recipients = tuple
|
||||||
|
return intersects(refused_emails.keys(), recipients)
|
||||||
|
|
||||||
|
to_be_sent = drop_until(predicate, to_be_sent)
|
||||||
|
in_error.append(refused_emails)
|
||||||
|
|
||||||
|
if in_error:
|
||||||
|
raise SendMassMailRecipientRefused(in_error)
|
Loading…
Add table
Reference in a new issue