diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index 3e7e4ff12..a7a8be166 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -455,6 +455,12 @@ def dao_get_notifications_by_to_field(service_id, search_term, notification_type else: raise InvalidRequest("Only email and SMS can use search by recipient", 400) + for special_character in {'_', '%', '/'}: + normalised = normalised.replace( + special_character, + '\\{}'.format(special_character) + ) + filters = [ Notification.service_id == service_id, Notification.normalised_to.like("%{}%".format(normalised)), diff --git a/tests/app/dao/notification_dao/test_notification_dao.py b/tests/app/dao/notification_dao/test_notification_dao.py index db9d999a3..0d5756897 100644 --- a/tests/app/dao/notification_dao/test_notification_dao.py +++ b/tests/app/dao/notification_dao/test_notification_dao.py @@ -1769,6 +1769,45 @@ def test_dao_get_notifications_by_to_field_matches_partial_emails(sample_email_t assert notification_2.id not in notification_ids +@pytest.mark.parametrize('search_term, expected_result_count', [ + ('foobar', 1), + ('foo', 2), + ('bar', 2), + ('foo%', 1), + ('%%bar', 1), + ('%_', 1), + ('%', 2), + ('_', 1), + ('/', 1), + ('%foo', 0), + ('%_%', 0), + ('example.com', 4), +]) +def test_dao_get_notifications_by_to_field_escapes( + sample_email_template, + search_term, + expected_result_count, +): + + for email_address in { + 'foo%_@example.com', + '%%bar@example.com', + 'foobar@example.com', + '/@example.com', + }: + create_notification( + template=sample_email_template, + to_field=email_address, + normalised_to=email_address, + ) + + assert len(dao_get_notifications_by_to_field( + sample_email_template.service_id, + search_term, + notification_type='email', + )) == expected_result_count + + @pytest.mark.parametrize('search_term', [ '001', '100',