fix: Improve validation for form that accepts pasted email feedback (#5761)
* test: Test paste-email-feedback-form with missing headers and/or body * fix: Don't crash if paste-email-feedback-form doesn't contain a Subject line * test: Test that paste-email-feedback-form requires headers * fix: If email headers are missing, prompt the user to try again * chore: retrigger PR checks
This commit is contained in:
parent
cc35a2d678
commit
2ca4f7beaf
|
@ -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 <president@galaxy>\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"""
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue