Add custom validator for multiple emails in a single text field. Change the widget of the email fields in the mailer app to avoid browser side email validation. Closes GitLab issue #530. Thanks to Mark Maglana @relaxdiego for the report.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2018-10-17 00:01:48 -04:00
parent cc79e75d35
commit 321b7ad5ae
7 changed files with 217 additions and 39 deletions

View File

@@ -8,6 +8,10 @@
* Add improvements to the metadata URL encoding and decoding to support
ampersand characters as part of the metadata value. GitLab issue
#529. Thanks to Mark Maglana @relaxdiego for the report.
* Add custom validator for multiple emails in a single text field.
Change the widget of the email fields in the mailer app to avoid
browser side email validation. Closes GitLab issue #530.
Thanks to Mark Maglana @relaxdiego for the report.
3.1.7 (2018-10-14)
==================

View File

@@ -18,6 +18,7 @@ from .settings import (
setting_document_body_template, setting_document_subject_template,
setting_link_body_template, setting_link_subject_template
)
from .validators import validate_email_multiple
class DocumentMailForm(forms.Form):
@@ -56,11 +57,11 @@ class DocumentMailForm(forms.Form):
except UserMailer.DoesNotExist:
pass
email = forms.EmailField(
email = forms.CharField(
help_text=_(
'Email address of the recipient. Can be multiple addresses '
'separated by comma or semicolon.'
), label=_('Email address')
), label=_('Email address'), validators=[validate_email_multiple]
)
subject = forms.CharField(label=_('Subject'), required=False)
body = forms.CharField(
@@ -117,4 +118,9 @@ class UserMailerDynamicForm(DynamicModelForm):
class UserMailerTestForm(forms.Form):
email = forms.EmailField(label=_('Email address'))
email = forms.CharField(
help_text=_(
'Email address of the recipient. Can be multiple addresses '
'separated by comma or semicolon.'
), label=_('Email address'), validators=[validate_email_multiple]
)

View File

@@ -3,10 +3,16 @@ from __future__ import unicode_literals
TEST_BODY_HTML = '<strong>test body</strong>'
TEST_EMAIL_ADDRESS = 'test@example.com'
TEST_RECIPIENTS_MULTIPLE_COMMA = 'test@example.com,test2@example.com'
TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT = [
'test@example.com', 'test2@example.com'
]
TEST_RECIPIENTS_MULTIPLE_SEMICOLON = 'test@example.com;test2@example.com'
TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT = [
'test@example.com', 'test2@example.com'
]
TEST_RECIPIENTS_MULTIPLE_MIXED = 'test@example.com,test2@example.com;test2@example.com'
TEST_RECIPIENTS_MULTIPLE_MIXED_LIST = (
'test@example.com', 'test2@example.com', 'test2@example.com',
)
TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT = [
'test@example.com', 'test2@example.com', 'test2@example.com'
]
TEST_USER_MAILER_BACKEND_PATH = 'mailer.tests.mailers.TestBackend'
TEST_USER_MAILER_LABEL = 'test user mailer label'

View File

@@ -0,0 +1,16 @@
from __future__ import unicode_literals
from ..models import UserMailer
from .literals import TEST_USER_MAILER_BACKEND_PATH, TEST_USER_MAILER_LABEL
class MailerTestMixin(object):
def _create_user_mailer(self):
self.user_mailer = UserMailer.objects.create(
default=True,
enabled=True,
label=TEST_USER_MAILER_LABEL,
backend_path=TEST_USER_MAILER_BACKEND_PATH,
backend_data='{}'
)

View File

@@ -4,26 +4,16 @@ from django.core import mail
from documents.tests.test_models import GenericDocumentTestCase
from ..models import UserMailer
from .literals import (
TEST_BODY_HTML, TEST_EMAIL_ADDRESS, TEST_RECIPIENTS_MULTIPLE_COMMA,
TEST_RECIPIENTS_MULTIPLE_SEMICOLON, TEST_RECIPIENTS_MULTIPLE_MIXED,
TEST_RECIPIENTS_MULTIPLE_MIXED_LIST, TEST_USER_MAILER_LABEL,
TEST_USER_MAILER_BACKEND_PATH
TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT, TEST_RECIPIENTS_MULTIPLE_SEMICOLON,
TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT, TEST_RECIPIENTS_MULTIPLE_MIXED,
TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT,
)
from .mixins import MailerTestMixin
class ModelTestCase(GenericDocumentTestCase):
def _create_user_mailer(self):
self.user_mailer = UserMailer.objects.create(
default=True,
enabled=True,
label=TEST_USER_MAILER_LABEL,
backend_path=TEST_USER_MAILER_BACKEND_PATH,
backend_data='{}'
)
class ModelTestCase(MailerTestMixin, GenericDocumentTestCase):
def test_send_simple(self):
self._create_user_mailer()
self.user_mailer.send(to=TEST_EMAIL_ADDRESS)
@@ -61,7 +51,7 @@ class ModelTestCase(GenericDocumentTestCase):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA.split(',')
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT
)
def test_send_multiple_recipients_semicolon(self):
@@ -70,7 +60,7 @@ class ModelTestCase(GenericDocumentTestCase):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON.split(';')
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT
)
def test_send_multiple_recipient_mixed(self):
@@ -79,5 +69,5 @@ class ModelTestCase(GenericDocumentTestCase):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
list(mail.outbox[0].to), list(TEST_RECIPIENTS_MULTIPLE_MIXED_LIST)
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT
)

View File

@@ -12,20 +12,14 @@ from ..permissions import (
)
from .literals import (
TEST_EMAIL_ADDRESS, TEST_USER_MAILER_BACKEND_PATH, TEST_USER_MAILER_LABEL
TEST_EMAIL_ADDRESS, TEST_USER_MAILER_BACKEND_PATH, TEST_USER_MAILER_LABEL,
TEST_RECIPIENTS_MULTIPLE_COMMA, TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT,
TEST_RECIPIENTS_MULTIPLE_MIXED, TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT,
TEST_RECIPIENTS_MULTIPLE_SEMICOLON,
TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT
)
from .mailers import TestBackend
class MailerTestMixin(object):
def _create_user_mailer(self):
self.user_mailer = UserMailer.objects.create(
default=True,
enabled=True,
label=TEST_USER_MAILER_LABEL,
backend_path=TEST_USER_MAILER_BACKEND_PATH,
backend_data='{}'
)
from .mixins import MailerTestMixin
class MailerViewsTestCase(MailerTestMixin, GenericDocumentViewTestCase):
@@ -33,7 +27,9 @@ class MailerViewsTestCase(MailerTestMixin, GenericDocumentViewTestCase):
return self.post(
'mailer:send_document_link', args=(self.document.pk,),
data={
'email': TEST_EMAIL_ADDRESS,
'email': getattr(
self, 'test_email_address', TEST_EMAIL_ADDRESS
),
'user_mailer': self.user_mailer.pk
},
)
@@ -42,7 +38,9 @@ class MailerViewsTestCase(MailerTestMixin, GenericDocumentViewTestCase):
return self.post(
'mailer:send_document', args=(self.document.pk,),
data={
'email': TEST_EMAIL_ADDRESS,
'email': getattr(
self, 'test_email_address', TEST_EMAIL_ADDRESS
),
'user_mailer': self.user_mailer.pk
},
)
@@ -66,7 +64,9 @@ class MailerViewsTestCase(MailerTestMixin, GenericDocumentViewTestCase):
def _request_user_mailer_test(self):
return self.post(
'mailer:user_mailer_test', args=(self.user_mailer.pk,), data={
'email': TEST_EMAIL_ADDRESS
'email': getattr(
self, 'test_email_address', TEST_EMAIL_ADDRESS
)
}, follow=True
)
@@ -207,3 +207,141 @@ class MailerViewsTestCase(MailerTestMixin, GenericDocumentViewTestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
def test_send_multiple_recipients_comma(self):
self._create_user_mailer()
self.login_user()
self.grant_access(
obj=self.user_mailer, permission=permission_user_mailer_use
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
response = self._request_user_mailer_test()
self.assertEqual(response.status_code, 200)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT
)
def test_send_multiple_recipients_mixed(self):
self._create_user_mailer()
self.login_user()
self.grant_access(
obj=self.user_mailer, permission=permission_user_mailer_use
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
response = self._request_user_mailer_test()
self.assertEqual(response.status_code, 200)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT
)
def test_send_multiple_recipients_semicolon(self):
self._create_user_mailer()
self.login_user()
self.grant_access(
obj=self.user_mailer, permission=permission_user_mailer_use
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
response = self._request_user_mailer_test()
self.assertEqual(response.status_code, 200)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT
)
def test_mail_link_view_recipients_comma(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_link)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
self._request_document_link_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT
)
def test_mail_link_view_recipients_mixed(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_link)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
self._request_document_link_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT
)
def test_mail_link_view_recipients_semicolon(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_link)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
self._request_document_link_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT
)
def test_mail_document_view_recipients_comma(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_send_document)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
self._request_document_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA_RESULT
)
def test_mail_document_view_recipients_mixed(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_send_document)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
self._request_document_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_MIXED_RESULT
)
def test_mail_document_view_recipients_semicolon(self):
self._create_user_mailer()
self.login_user()
self.grant_permission(permission=permission_mailing_send_document)
self.grant_permission(permission=permission_user_mailer_use)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
self._request_document_send()
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON_RESULT
)

View File

@@ -0,0 +1,18 @@
from __future__ import unicode_literals
from django.core import validators
from django.utils.translation import ugettext_lazy as _
from .utils import split_recipient_list
def validate_email_multiple(value):
recipient_list = split_recipient_list(recipients=[value])
for recipient in recipient_list:
validate_email = validators.EmailValidator(
message=_('%(email)s is not a valid email address.') % {
'email': recipient
}
)
validate_email(value=recipient)