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)