diff --git a/anymail/utils.py b/anymail/utils.py index 7c34249..080a1f9 100644 --- a/anymail/utils.py +++ b/anymail/utils.py @@ -212,6 +212,14 @@ class EmailAddress: display_name, addr_spec = display_name # unpack (name,addr) tuple except ValueError: pass + + # ESPs should clean or reject addresses containing newlines, but some + # extra protection can't hurt (and it seems to be a common oversight) + if '\n' in display_name or '\r' in display_name: + raise ValueError('EmailAddress display_name cannot contain newlines') + if '\n' in addr_spec or '\r' in addr_spec: + raise ValueError('EmailAddress addr_spec cannot contain newlines') + self.display_name = display_name self.addr_spec = addr_spec try: diff --git a/tests/test_utils.py b/tests/test_utils.py index 8cd4287..d8a3f9b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -159,6 +159,19 @@ class ParseAddressListTests(SimpleTestCase): with self.assertRaisesMessage(AnymailInvalidAddress, "Invalid email address"): parse_single_address(" ") + def test_no_newlines(self): + # (Parsing shouldn't even be able to even generate these cases, + # but in case anyone constructs an EmailAddress directly...) + for name, addr in [ + ("Potential\nInjection", "addr@example.com"), + ("Potential\rInjection", "addr@example.com"), + ("Name", "potential\ninjection@example.com"), + ("Name", "potential\rinjection@example.com"), + ]: + with self.subTest(name=name, addr=addr): + with self.assertRaisesMessage(ValueError, "cannot contain newlines"): + _ = EmailAddress(name, addr) + class NormalizedAttachmentTests(SimpleTestCase): """Test utils.Attachment"""