From 9c6a3f3c96cdf1d22fecf372a0f9f188d2d13d11 Mon Sep 17 00:00:00 2001 From: Christophe Chauvet Date: Wed, 7 Jan 2026 17:52:47 +0100 Subject: [PATCH 1/5] fix(imap): issue when pattern is empty Problem appear with some FTS backend Ref #2336 --- modoboa/webmail/lib/imaputils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modoboa/webmail/lib/imaputils.py b/modoboa/webmail/lib/imaputils.py index cfc9adbd6..2284754ae 100644 --- a/modoboa/webmail/lib/imaputils.py +++ b/modoboa/webmail/lib/imaputils.py @@ -301,7 +301,10 @@ class IMAPconnector: key = "SUBJECT" else: continue - criterions = or_criterion(criterions, f'({key} "{pattern}")') + if pattern: + criterions = or_criterion(criterions, f'({key} "{pattern}")') + else: + criterions = "ALL" self.criterions = [bytearray(criterions, "utf8")] def messages_count(self, **kwargs) -> int: From bef732dfd8a7f3e1315bd70fcb66ebd1649d99a1 Mon Sep 17 00:00:00 2001 From: Christophe Chauvet Date: Tue, 13 Jan 2026 21:14:31 +0100 Subject: [PATCH 2/5] test: imap parse search parameters --- modoboa/webmail/tests/test_lib_imaputils.py | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 modoboa/webmail/tests/test_lib_imaputils.py diff --git a/modoboa/webmail/tests/test_lib_imaputils.py b/modoboa/webmail/tests/test_lib_imaputils.py new file mode 100644 index 000000000..6eab742e1 --- /dev/null +++ b/modoboa/webmail/tests/test_lib_imaputils.py @@ -0,0 +1,27 @@ +"""mailutils tests""" + +import io +import unittest + +from modoboa.webmail.lib.imaputils import IMAPconnector + + +class ImapUtilsTestCase(unittest.TestCase): + """Test mail utils library""" + + def setUp(self): + self.imap_connector = IMAPconnector(user="test", password="test") + + def test_criterions_one_criterion_with_pattern(self): + """Test with Criterion and pattern""" + self.imap_connector.criterions = [] + self.imap_connector.parse_search_parameters("from_addr", "bob") + result = [bytearray('FROM "bob"', "utf8")] + self.assertEqual(self.imap_connector.criterions, result) + + def test_criterions_one_criterion_without_pattern(self): + """Test with Criterion and pattern""" + self.imap_connector.criterions = [] + self.imap_connector.parse_search_parameters("SEEN", "") + result = [bytearray("ALL", "utf8")] + self.assertEqual(self.imap_connector.criterions, result) \ No newline at end of file From b92ebf1aa442375fc1961d8bc4bcebcdf958b2cc Mon Sep 17 00:00:00 2001 From: Christophe Chauvet Date: Tue, 13 Jan 2026 22:00:37 +0100 Subject: [PATCH 3/5] test: fix code and test --- modoboa/webmail/lib/imaputils.py | 9 +++++---- modoboa/webmail/tests/test_lib_imaputils.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modoboa/webmail/lib/imaputils.py b/modoboa/webmail/lib/imaputils.py index 2284754ae..71b32f510 100644 --- a/modoboa/webmail/lib/imaputils.py +++ b/modoboa/webmail/lib/imaputils.py @@ -301,10 +301,11 @@ class IMAPconnector: key = "SUBJECT" else: continue - if pattern: - criterions = or_criterion(criterions, f'({key} "{pattern}")') - else: - criterions = "ALL" + + criterions = or_criterion(criterions, f'({key} "{pattern}")') + + if not pattern: + criterions = "ALL" self.criterions = [bytearray(criterions, "utf8")] def messages_count(self, **kwargs) -> int: diff --git a/modoboa/webmail/tests/test_lib_imaputils.py b/modoboa/webmail/tests/test_lib_imaputils.py index 6eab742e1..1a7a1e03f 100644 --- a/modoboa/webmail/tests/test_lib_imaputils.py +++ b/modoboa/webmail/tests/test_lib_imaputils.py @@ -16,7 +16,7 @@ class ImapUtilsTestCase(unittest.TestCase): """Test with Criterion and pattern""" self.imap_connector.criterions = [] self.imap_connector.parse_search_parameters("from_addr", "bob") - result = [bytearray('FROM "bob"', "utf8")] + result = [bytearray('(FROM "bob")', "utf8")] self.assertEqual(self.imap_connector.criterions, result) def test_criterions_one_criterion_without_pattern(self): From 590c52d0fc385e360fbc9459485185c69c75d90b Mon Sep 17 00:00:00 2001 From: Christophe Chauvet Date: Tue, 13 Jan 2026 22:18:10 +0100 Subject: [PATCH 4/5] test: test both parameter --- modoboa/webmail/tests/test_lib_imaputils.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modoboa/webmail/tests/test_lib_imaputils.py b/modoboa/webmail/tests/test_lib_imaputils.py index 1a7a1e03f..b43391f2c 100644 --- a/modoboa/webmail/tests/test_lib_imaputils.py +++ b/modoboa/webmail/tests/test_lib_imaputils.py @@ -19,8 +19,15 @@ class ImapUtilsTestCase(unittest.TestCase): result = [bytearray('(FROM "bob")', "utf8")] self.assertEqual(self.imap_connector.criterions, result) + def test_criterions_both_criterion_with_pattern(self): + """Test with both Criterion and pattern""" + self.imap_connector.criterions = [] + self.imap_connector.parse_search_parameters("both", "bob") + result = [bytearray('(FROM "bob") OR (SUBJECT "bob")', "utf8")] + self.assertEqual(self.imap_connector.criterions, result) + def test_criterions_one_criterion_without_pattern(self): - """Test with Criterion and pattern""" + """Test with Criterion and empty pattern""" self.imap_connector.criterions = [] self.imap_connector.parse_search_parameters("SEEN", "") result = [bytearray("ALL", "utf8")] From 74d92199c35bd951af9ce87c458d3a272e755e0d Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 14 Jan 2026 13:59:49 +0100 Subject: [PATCH 5/5] Removed wrong space in criteria list --- modoboa/webmail/lib/imaputils.py | 25 +++++++++++---------- modoboa/webmail/tests/test_lib_imaputils.py | 5 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/modoboa/webmail/lib/imaputils.py b/modoboa/webmail/lib/imaputils.py index 71b32f510..d8eff0014 100644 --- a/modoboa/webmail/lib/imaputils.py +++ b/modoboa/webmail/lib/imaputils.py @@ -292,20 +292,21 @@ class IMAPconnector: return f"OR {old} {c}" if criterion == "both": - criterion = "from_addr, subject" - criterions = "" - for c in criterion.split(","): - if c == "from_addr": - key = "FROM" - elif c == "subject": - key = "SUBJECT" - else: - continue - - criterions = or_criterion(criterions, f'({key} "{pattern}")') - + criterion = "from_addr,subject" + if not pattern: criterions = "ALL" + else: + criterions = "" + for c in criterion.split(","): + if c == "from_addr": + key = "FROM" + elif c == "subject": + key = "SUBJECT" + else: + continue + criterions = or_criterion(criterions, f'({key} "{pattern}")') + self.criterions = [bytearray(criterions, "utf8")] def messages_count(self, **kwargs) -> int: diff --git a/modoboa/webmail/tests/test_lib_imaputils.py b/modoboa/webmail/tests/test_lib_imaputils.py index b43391f2c..a16f6231d 100644 --- a/modoboa/webmail/tests/test_lib_imaputils.py +++ b/modoboa/webmail/tests/test_lib_imaputils.py @@ -1,6 +1,5 @@ """mailutils tests""" -import io import unittest from modoboa.webmail.lib.imaputils import IMAPconnector @@ -23,7 +22,7 @@ class ImapUtilsTestCase(unittest.TestCase): """Test with both Criterion and pattern""" self.imap_connector.criterions = [] self.imap_connector.parse_search_parameters("both", "bob") - result = [bytearray('(FROM "bob") OR (SUBJECT "bob")', "utf8")] + result = [bytearray('OR (FROM "bob") (SUBJECT "bob")', "utf8")] self.assertEqual(self.imap_connector.criterions, result) def test_criterions_one_criterion_without_pattern(self): @@ -31,4 +30,4 @@ class ImapUtilsTestCase(unittest.TestCase): self.imap_connector.criterions = [] self.imap_connector.parse_search_parameters("SEEN", "") result = [bytearray("ALL", "utf8")] - self.assertEqual(self.imap_connector.criterions, result) \ No newline at end of file + self.assertEqual(self.imap_connector.criterions, result)