Add a helper to handle smtp errors in send_mass_mail

This commit is contained in:
Martin Pépin 2019-01-23 18:18:45 +01:00
parent be155f2f2d
commit 2c53344f1f

54
utils/mailutils.py Normal file
View file

@ -0,0 +1,54 @@
from custommail.shortcuts import send_mass_custom_mail
from smtplib import SMTPRecipientsRefused
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)