From 5b04ae30f2e79f0c88e1e33c43b09b175b548576 Mon Sep 17 00:00:00 2001 From: medmunds Date: Thu, 10 Sep 2020 15:05:10 -0700 Subject: [PATCH] Ensure EmailAddress can't contain newlines --- anymail/utils.py | 8 ++++++++ tests/test_utils.py | 13 +++++++++++++ 2 files changed, 21 insertions(+) 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"""