diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py index 07c893fdc..dff5fb950 100644 --- a/ietf/nomcom/tests.py +++ b/ietf/nomcom/tests.py @@ -99,6 +99,7 @@ class NomcomViewsTest(TestCase): self.private_nominate_newperson_url = reverse('ietf.nomcom.views.private_nominate_newperson', kwargs={'year': self.year}) self.add_questionnaire_url = reverse('ietf.nomcom.views.private_questionnaire', kwargs={'year': self.year}) self.private_feedback_url = reverse('ietf.nomcom.views.private_feedback', kwargs={'year': self.year}) + self.private_feedback_email_url = reverse('ietf.nomcom.views.private_feedback_email', kwargs={'year': self.year}) self.positions_url = reverse('ietf.nomcom.views.list_positions', kwargs={'year': self.year}) self.edit_position_url = reverse('ietf.nomcom.views.edit_position', kwargs={'year': self.year}) @@ -1012,6 +1013,43 @@ class NomcomViewsTest(TestCase): nominee_position.save() + def test_private_feedback_email(self): + self.access_chair_url(self.private_feedback_email_url) + + feedback_url = self.private_feedback_email_url + response = self.client.get(feedback_url) + self.assertEqual(response.status_code, 200) + + nomcom = get_nomcom_by_year(self.year) + if not nomcom.public_key: + self.assertNotContains(response, "paste-email-feedback-form") + + # save the cert file in tmp + with io.open(self.cert_file.name, 'r') as fd: + nomcom.public_key.save('cert', File(fd)) + + response = self.client.get(feedback_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "paste-email-feedback-form") + + headers = \ + "From: Zaphod Beeblebrox \n" \ + "Subject: Ford Prefect\n\n" + body = \ + "Hey, you sass that hoopy Ford Prefect?\n" \ + "There's a frood who really knows where his towel is.\n" + + test_data = {'email_text': body} + response = self.client.post(feedback_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Missing email headers') + + test_data = {'email_text': headers + body} + response = self.client.post(feedback_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'The feedback email has been registered.') + + class NomineePositionStateSaveTest(TestCase): """Tests for the NomineePosition save override method""" diff --git a/ietf/nomcom/utils.py b/ietf/nomcom/utils.py index 2fdbe1382..e009999e6 100644 --- a/ietf/nomcom/utils.py +++ b/ietf/nomcom/utils.py @@ -12,6 +12,7 @@ import tempfile from collections import defaultdict from email import message_from_string, message_from_bytes +from email.errors import HeaderParseError from email.header import decode_header from email.iterators import typed_subpart_iterator from email.utils import parseaddr @@ -442,7 +443,11 @@ def make_nomineeposition_for_newperson(nomcom, candidate_name, candidate_email, def getheader(header_text, default="utf-8"): """Decode the specified header""" - tuples = decode_header(header_text) + try: + tuples = decode_header(header_text) + except TypeError: + return "" + header_sections = [ text.decode(charset or default) if isinstance(text, bytes) else text for text, charset in tuples] return "".join(header_sections) @@ -491,6 +496,9 @@ def parse_email(text): body = get_body(msg) subject = getheader(msg['Subject']) __, addr = parseaddr(msg['From']) + if not addr: + raise HeaderParseError + return addr.lower(), subject, body diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index 77a3c3b76..c077afce4 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -20,6 +20,7 @@ from django.template.loader import render_to_string from django.urls import reverse from django.utils.encoding import force_bytes, force_str +from email.errors import HeaderParseError from ietf.dbtemplate.models import DBTemplate from ietf.dbtemplate.views import group_template_edit, group_template_show @@ -652,9 +653,12 @@ def private_feedback_email(request, year): form = FeedbackEmailForm(data=request.POST, nomcom=nomcom) if form.is_valid(): - form.save() - form = FeedbackEmailForm(nomcom=nomcom) - messages.success(request, 'The feedback email has been registered.') + try: + form.save() + form = FeedbackEmailForm(nomcom=nomcom) + messages.success(request, 'The feedback email has been registered.') + except HeaderParseError: + messages.error(request, 'Missing email headers') return render(request, template, {'form': form,