From 31a4cc15c9bb41950795b2cb79398d9f502a5bac Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Wed, 14 Feb 2018 14:35:16 +0000 Subject: [PATCH] validate email addresses in one-off flow previously we were just using the wtforms builtin email validator, which is much more relaxed than our own one. It'd catch bad emails when POSTing to the API, resulting in an ugly error message. It's easy work to make sure we validate email addresses as soon as they're entered. --- app/main/forms.py | 9 +++++---- app/main/validators.py | 16 ++++++++++++++++ tests/app/main/test_placeholder_form.py | 1 + 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index dd100c9b1..8023f40bf 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -26,7 +26,7 @@ from wtforms import ( DateField, ) from wtforms.fields.html5 import EmailField, TelField, SearchField -from wtforms.validators import (DataRequired, Email, Length, Regexp, Optional) +from wtforms.validators import (DataRequired, Length, Regexp, Optional) from flask_wtf.file import FileField as FileField_wtf, FileAllowed from app.main.validators import ( @@ -36,6 +36,7 @@ from app.main.validators import ( NoCommasInPlaceHolders, OnlyGSMCharacters, LettersNumbersAndFullStopsOnly, + ValidEmail ) @@ -98,7 +99,7 @@ def email_address(label='Email address', gov_user=True): validators = [ Length(min=5, max=255), DataRequired(message='Can’t be empty'), - Email(message='Enter a valid email address') + ValidEmail() ] if gov_user: @@ -196,7 +197,7 @@ class LoginForm(StripWhitespaceForm): email_address = StringField('Email address', validators=[ Length(min=5, max=255), DataRequired(message='Can’t be empty'), - Email(message='Enter a valid email address') + ValidEmail() ]) password = PasswordField('Password', validators=[ DataRequired(message='Enter your password') @@ -707,7 +708,7 @@ class Whitelist(StripWhitespaceForm): '', validators=[ Optional(), - Email(message='Enter valid email addresses') + ValidEmail() ], default='' ), diff --git a/app/main/validators.py b/app/main/validators.py index 92074b1d6..0cf7b4d94 100644 --- a/app/main/validators.py +++ b/app/main/validators.py @@ -1,7 +1,10 @@ import re + from wtforms import ValidationError +from wtforms.validators import Email from notifications_utils.field import Field from notifications_utils.gsm import get_non_gsm_compatible_characters +from notifications_utils.recipients import validate_email_address, InvalidEmailError from app import formatted_list from app.main._blacklisted_passwords import blacklisted_passwords @@ -44,6 +47,19 @@ class ValidGovEmail: raise ValidationError(message) +class ValidEmail(Email): + + def __init__(self): + super().__init__('Enter a valid email address') + + def __call__(self, form, field): + try: + validate_email_address(field.data) + except InvalidEmailError: + raise ValidationError(self.message) + return super().__call__(form, field) + + class NoCommasInPlaceHolders: def __init__(self, message='You can’t put commas between double brackets'): diff --git a/tests/app/main/test_placeholder_form.py b/tests/app/main/test_placeholder_form.py index af1a7b57b..bd49567ff 100644 --- a/tests/app/main/test_placeholder_form.py +++ b/tests/app/main/test_placeholder_form.py @@ -22,6 +22,7 @@ def test_form_class_not_mutated(app_): (False, 'email address', '', 'Can’t be empty'), (False, 'email address', '12345', 'Enter a valid email address'), + (False, 'email address', '“bad”@email-address.com', 'Enter a valid email address'), (False, 'email address', 'test@example.com', None), (False, 'email address', 'test@example.gov.uk', None),