Makes sure BCC is provided to *every* e-mail. (#65)
* Replaces the monkey patch on send_mail, and replaces it with a monkey patch on EmailMessage’s constructor. * Removes spurious print statements. * Minimum viable changes to get schedule to display (#64) * All migrations are now in this tree * Replaces the monkey patch on send_mail, and replaces it with a monkey patch on EmailMessage’s constructor. * Removes spurious print statements.
This commit is contained in:
parent
fe31b1b7c4
commit
7a001e6228
1 changed files with 77 additions and 17 deletions
|
@ -12,7 +12,7 @@ class MonkeyPatchMiddleware(object):
|
||||||
|
|
||||||
def do_monkey_patch():
|
def do_monkey_patch():
|
||||||
patch_speaker_profile_form()
|
patch_speaker_profile_form()
|
||||||
patch_accounts_to_send_bcc()
|
patch_mail_to_send_bcc()
|
||||||
fix_sitetree_check_access_500s()
|
fix_sitetree_check_access_500s()
|
||||||
never_cache_login_page()
|
never_cache_login_page()
|
||||||
|
|
||||||
|
@ -33,31 +33,91 @@ def patch_speaker_profile_form():
|
||||||
fields["accessibility"].widget = widgets.AceMarkdownEditor()
|
fields["accessibility"].widget = widgets.AceMarkdownEditor()
|
||||||
|
|
||||||
|
|
||||||
def patch_accounts_to_send_bcc():
|
def patch_mail_to_send_bcc():
|
||||||
''' Patches django-user-accounts' email functions to send a BCC e-mail to
|
''' Patches django.core.mail's message classes to send a BCC e-mail to
|
||||||
the default BCC e-mail address. '''
|
the default BCC e-mail address. '''
|
||||||
|
|
||||||
from account import hooks
|
from django.core.mail import message
|
||||||
|
|
||||||
# django-user-accounts always uses send_mail like:
|
ARG = "bcc"
|
||||||
# send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, to)
|
|
||||||
|
|
||||||
if hasattr(settings, "ENVELOPE_BCC_LIST"):
|
if hasattr(settings, "ENVELOPE_BCC_LIST"):
|
||||||
bcc_email = settings.ENVELOPE_BCC_LIST
|
bcc_email = settings.ENVELOPE_BCC_LIST
|
||||||
else:
|
else:
|
||||||
bcc_email = None
|
return # We don't need to do this patch.
|
||||||
|
|
||||||
def send_mail(subject, message, from_email, to):
|
def bcc_arg_position(f):
|
||||||
email = EmailMultiAlternatives(
|
''' Returns the position of 'bcc' in the argument list to f, or None if
|
||||||
subject,
|
there is no such argument. '''
|
||||||
message,
|
co = f.__code__
|
||||||
from_email,
|
# The first co_argcount members of co_varnames are argument variables
|
||||||
to,
|
for i, argname in enumerate(co.co_varnames[:co.co_argcount]):
|
||||||
bcc=bcc_email,
|
if argname == ARG:
|
||||||
)
|
return i
|
||||||
email.send()
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
hooks.send_mail = send_mail
|
def bcc_is_provided_positionally(f, a):
|
||||||
|
''' Returns true if 'bcc' is provided as a positional argument to f,
|
||||||
|
when it is called with the argument list `a`. '''
|
||||||
|
|
||||||
|
return bcc_arg_position(f) < len(a)
|
||||||
|
|
||||||
|
def patch_bcc_positional(f, a):
|
||||||
|
''' Returns a copy of `a`, but with the bcc argument patched to include
|
||||||
|
our BCC list. '''
|
||||||
|
|
||||||
|
pos = bcc_arg_position(f)
|
||||||
|
bcc = a[pos]
|
||||||
|
|
||||||
|
if bcc is not None:
|
||||||
|
bcc = list(bcc)
|
||||||
|
else:
|
||||||
|
bcc = []
|
||||||
|
|
||||||
|
bcc += bcc_email
|
||||||
|
|
||||||
|
return tuple(a[:pos] + (bcc,) + a[pos + 1:])
|
||||||
|
|
||||||
|
|
||||||
|
def patch_bcc_keyword(f, k):
|
||||||
|
''' Adds our BCC list to the BCC list in the keyword arguments, and
|
||||||
|
returns the new version of the keyword arguments.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
f (callable): The function that we're patching. It should have an
|
||||||
|
argument called bcc.
|
||||||
|
k (dict): A dictionary of kwargs to be provided to EmailMessage.
|
||||||
|
It will be modified to add the BCC list specified in
|
||||||
|
settings.ENVELOPE_BCC_LIST, if provided.
|
||||||
|
'''
|
||||||
|
|
||||||
|
if ARG in k:
|
||||||
|
bcc = list(k[ARG])
|
||||||
|
del k[ARG]
|
||||||
|
else:
|
||||||
|
bcc = []
|
||||||
|
bcc += list(bcc_email)
|
||||||
|
k[ARG] = bcc
|
||||||
|
|
||||||
|
return k
|
||||||
|
|
||||||
|
to_wrap = message.EmailMessage.__init__
|
||||||
|
|
||||||
|
@wraps(to_wrap)
|
||||||
|
def email_message__init__(*a, **k):
|
||||||
|
|
||||||
|
if bcc_is_provided_positionally(to_wrap, a):
|
||||||
|
a = patch_bcc_positional(to_wrap, a)
|
||||||
|
else:
|
||||||
|
k = patch_bcc_keyword(to_wrap, k)
|
||||||
|
|
||||||
|
return to_wrap(*a, **k)
|
||||||
|
|
||||||
|
message.EmailMessage.__init__ = email_message__init__
|
||||||
|
|
||||||
|
# Do not need to wrap EmailMultiAlternatives because it is a subclass of
|
||||||
|
# EmailMessage.
|
||||||
|
|
||||||
|
|
||||||
def fix_sitetree_check_access_500s():
|
def fix_sitetree_check_access_500s():
|
||||||
|
|
Loading…
Reference in a new issue