From 11287b8f0a06b00f6db306b99181e5103d3bf00a Mon Sep 17 00:00:00 2001 From: midhlaj-nk Date: Thu, 18 Jun 2026 09:55:01 +0530 Subject: [PATCH] [18.0][FIX] fetchmail_attach_from_folder: case-insensitive email matching PostgreSQL = operator is case-sensitive, so partners stored with mixed-case emails (e.g. Name.SURNAME@Domain.com) were not matched against lowercased incoming addresses. Switch to =ilike for exact match and ilike for domain match to make comparisons case-insensitive. Closes #3402 --- .../match_algorithm/email_domain.py | 2 +- .../match_algorithm/email_exact.py | 2 +- .../tests/test_match_algorithms.py | 25 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/fetchmail_attach_from_folder/match_algorithm/email_domain.py b/fetchmail_attach_from_folder/match_algorithm/email_domain.py index e00436375c2..47babc16102 100644 --- a/fetchmail_attach_from_folder/match_algorithm/email_domain.py +++ b/fetchmail_attach_from_folder/match_algorithm/email_domain.py @@ -21,7 +21,7 @@ def search_matches(self, folder, message_dict): self._get_mailaddress_search_domain( folder, message_dict, - operator="like", + operator="ilike", values=["%@" + domain for domain in set(domains)], ), order=folder.model_order, diff --git a/fetchmail_attach_from_folder/match_algorithm/email_exact.py b/fetchmail_attach_from_folder/match_algorithm/email_exact.py index 899289407da..701a2d0ee27 100644 --- a/fetchmail_attach_from_folder/match_algorithm/email_exact.py +++ b/fetchmail_attach_from_folder/match_algorithm/email_exact.py @@ -16,7 +16,7 @@ def _get_mailaddresses(self, folder, message_dict): return [addr.lower() for addr in mailaddresses] def _get_mailaddress_search_domain( - self, folder, message_dict, operator="=", values=None + self, folder, message_dict, operator="=ilike", values=None ): mailaddresses = values or self._get_mailaddresses(folder, message_dict) if not mailaddresses: diff --git a/fetchmail_attach_from_folder/tests/test_match_algorithms.py b/fetchmail_attach_from_folder/tests/test_match_algorithms.py index 02969a4f4fd..bb40ea36f77 100644 --- a/fetchmail_attach_from_folder/tests/test_match_algorithms.py +++ b/fetchmail_attach_from_folder/tests/test_match_algorithms.py @@ -150,6 +150,31 @@ def test_email_exact(self): self._test_search_matches(email_domain.EmailDomain) self._test_apply_matching(email_domain.EmailDomain) + def test_email_exact_case_insensitive(self): + """Email matching must be case-insensitive regardless of stored casing.""" + from ..match_algorithm.email_exact import EmailExact + + mixed_case_email = TEST_EMAIL.replace("reynaert", "Reynaert").replace( + "dutchsagas", "DutchSagas" + ) + self.test_partner.write({"email": mixed_case_email}) + MAIL_MESSAGE["from"] = TEST_EMAIL + matcher = EmailExact() + matches = matcher.search_matches(self.folder, MAIL_MESSAGE) + self.assertEqual(matches, self.test_partner) + + def test_email_domain_case_insensitive(self): + """Domain matching must be case-insensitive regardless of stored casing.""" + mixed_case_email = TEST_EMAIL.replace("dutchsagas", "DutchSagas") + self.test_partner.write({"email": mixed_case_email}) + alternate_email = TEST_EMAIL.replace("reynaert@", "mariken@") + MAIL_MESSAGE["from"] = alternate_email + self.folder.match_algorithm = "email_domain" + self.folder.match_first = True + matcher = email_domain.EmailDomain() + matches = matcher.search_matches(self.folder, MAIL_MESSAGE) + self.assertEqual(matches, self.test_partner) + def test_email_domain(self): """Test with email in same domain, but different mailbox.""" ALTERNATE_EMAIL = TEST_EMAIL.replace("reynaert@", "mariken@")