I have a Django view with an email form. It allows the user to type a subject and message, and send that as an email to the site admin. I would like to write a unit test that ensures that this view can catch a <a href="https://docs.djangoproject.com/en/1.4/topics/email/#preventing-header-injection" rel="nofollow">BadHeaderError</a>.
subject = contact_form.cleaned_data['subject'] message = contact_form.cleaned_data['message'] try: mail_admins( subject=subject, message=message, ) except BadHeaderError: # I want to test this case. messages.error(request, "Sorry, the email could not be sent. An invalid header was found.") else: messages.success(request, "Your email was sent to the admins.")
How do I trigger a BadHeaderError in a unit test?
I know the canonical example of header injection is having a newline character in the subject. However, I wrote a unit test that fills out this form with a newline character in the subject, and it didn't trigger the invalid header message.
# This didn't trigger the invalid header message. So how do I do it? response = self.client.post(reverse('contact_us'), dict( subject="Subject goes here\ncc:email@example.com", message="Message goes here", ))
<a href="https://stackoverflow.com/a/12549859/859858" rel="nofollow">Hassek's suggestion</a> of using Mocker is an avenue of approach I hadn't originally considered, and will work for my purpose here. However, I'm curious as to what actually triggers a BadHeaderError in the mail functions - what kind of special character is needed in the subject, if a newline doesn't do it? Or is there another way to trigger the BadHeaderError? I don't know too much about web security, so I'd like to learn these things.
I was using Django 1.3.0.Answer1:
Use a <a href="http://labix.org/mocker" rel="nofollow">mocker</a> on the mail_admins function to raise the BadHeaderError when called. it would be something like this:
from mocker import Mocker, KWARGS mocker = Mocker() raise_error = mocker.replace('COMPLETE_PATH_TO_mail_admins_FUNCTION') # i.e django.contrib.emails.mail_admins raise_error(KWARGS) mocker.raise(BadHeaderException)
haven't test this yet but it should help you out :)Answer2:
This snippet is from Django's own tests; this is how they test that this error is raised
def test_header_injection(self): email = EmailMessage('Subject\nInjection Test', 'Content', 'firstname.lastname@example.org', ['email@example.com']) self.assertRaises(BadHeaderError, email.message)