From 2bd46a719b947b0839f47fd9e4bf5517f396fd29 Mon Sep 17 00:00:00 2001 From: Patrick Maia Date: Fri, 20 Feb 2015 11:14:58 -0300 Subject: Issue #174 - rejects bounced addresses on contacts suggestions --- service/pixelated/adapter/search/__init__.py | 2 ++ service/pixelated/adapter/search/contacts.py | 13 +++++++--- service/test/integration/test_contacts.py | 31 ++++++++++++++++++++++- service/test/unit/adapter/test_mail.py | 2 +- service/test/unit/fixtures/bounced_mail_hdoc.json | 8 +++--- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/service/pixelated/adapter/search/__init__.py b/service/pixelated/adapter/search/__init__.py index eedeaa45..e9301278 100644 --- a/service/pixelated/adapter/search/__init__.py +++ b/service/pixelated/adapter/search/__init__.py @@ -102,6 +102,7 @@ class SearchEngine(object): to=KEYWORD(stored=False, commas=True), cc=KEYWORD(stored=False, commas=True), bcc=KEYWORD(stored=False, commas=True), + bounced=KEYWORD(stored=False, commas=True), subject=TEXT(stored=False), date=NUMERIC(stored=False, sortable=True, bits=64, signed=False), body=TEXT(stored=False), @@ -131,6 +132,7 @@ class SearchEngine(object): 'cc': u','.join(header.get('cc', [''])), 'bcc': u','.join(header.get('bcc', [''])), 'tag': u','.join(unique(tags)), + 'bounced': unicode(mail.bounced), 'body': unicode(mdict['textPlainBody']), 'ident': unicode(mdict['ident']), 'flags': unicode(','.join(unique(mail.flags))), diff --git a/service/pixelated/adapter/search/contacts.py b/service/pixelated/adapter/search/contacts.py index afef6ad0..0dfeb15b 100644 --- a/service/pixelated/adapter/search/contacts.py +++ b/service/pixelated/adapter/search/contacts.py @@ -31,14 +31,21 @@ def address_duplication_filter(contacts): return contacts_by_mail.values() +def bounced_addresses_filter(searcher, contacts): + query = QueryParser('bounced', searcher.schema).parse('*') + bounced_addresses = searcher.search(query, + limit=None, + groupedby=sorting.FieldFacet('bounced', + allow_overlap=True)).groups() + return set(contacts) - set(flatten([bounced_addresses])) + + def extract_mail_address(text): return parseaddr(text)[1] def contacts_suggestions(query, searcher): - if query: - return address_duplication_filter(search_addresses(searcher, query)) - return [] + return address_duplication_filter(bounced_addresses_filter(searcher, search_addresses(searcher, query))) if query else [] def search_addresses(searcher, query): diff --git a/service/test/integration/test_contacts.py b/service/test/integration/test_contacts.py index c5baa094..d96abd14 100644 --- a/service/test/integration/test_contacts.py +++ b/service/test/integration/test_contacts.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . from test.support.integration import SoledadTestBase, MailBuilder +import os +import json class ContactsTest(SoledadTestBase): @@ -73,10 +75,37 @@ class ContactsTest(SoledadTestBase): d = self.get_contacts(query='Recipient') def _assert(contacts): - print contacts self.assertEquals(3, len(contacts)) self.assertTrue('Recipient Principal ' in contacts) self.assertTrue('Recipient Copied ' in contacts) self.assertTrue('Recipient Carbon ' in contacts) d.addCallback(_assert) return d + + def test_bounced_addresses_are_ignored(self): + to_be_bounced = MailBuilder().with_to('this_mail_was_bounced@domain.com').build_input_mail() + self.client.add_mail_to_inbox(to_be_bounced) + + bounced_mail_template = MailBuilder().build_input_mail() + bounced_mail = self.client.mailboxes.inbox().add(bounced_mail_template) + bounced_mail.hdoc.content = self._bounced_mail_hdoc_content() + bounced_mail.save() + self.client.search_engine.index_mail(bounced_mail) + + not_bounced_mail = MailBuilder( + ).with_tags(['important']).with_to('this_mail_was_not@bounced.com').build_input_mail() + self.client.add_mail_to_inbox(not_bounced_mail) + + d = self.get_contacts(query='this') + + def _assert(contacts): + self.assertNotIn('this_mail_was_bounced@domain.com', contacts) + self.assertIn('this_mail_was_not@bounced.com', contacts) + d.addCallback(_assert) + return d + + def _bounced_mail_hdoc_content(self): + hdoc_file = os.path.join(os.path.dirname(__file__), '..', 'unit', 'fixtures', 'bounced_mail_hdoc.json') + with open(hdoc_file) as f: + hdoc = json.loads(f.read()) + return hdoc diff --git a/service/test/unit/adapter/test_mail.py b/service/test/unit/adapter/test_mail.py index a5d4fe24..9a99e450 100644 --- a/service/test/unit/adapter/test_mail.py +++ b/service/test/unit/adapter/test_mail.py @@ -224,7 +224,7 @@ class TestPixelatedMail(unittest.TestCase): not_bounced_mail = PixelatedMail.from_soledad(*not_bounced_leap_mail, soledad_querier=self.querier) self.assertTrue(bounced_mail.bounced) - self.assertEquals('inexistentaccount@domain.com', bounced_mail.bounced) + self.assertEquals('this_mail_was_bounced@domain.com', bounced_mail.bounced) self.assertFalse(not_bounced_mail.bounced) def _create_bdoc(self, raw): diff --git a/service/test/unit/fixtures/bounced_mail_hdoc.json b/service/test/unit/fixtures/bounced_mail_hdoc.json index 5a0f9700..2cc5997c 100644 --- a/service/test/unit/fixtures/bounced_mail_hdoc.json +++ b/service/test/unit/fixtures/bounced_mail_hdoc.json @@ -82,11 +82,11 @@ "headers": [ [ "Final-Recipient", - "rfc822; inexistentaccount@domain.com" + "rfc822; this_mail_was_bounced@domain.com" ], [ "Original-Recipient", - "rfc822;inexistentaccount@domain.com" + "rfc822;this_mail_was_bounced@domain.com" ], [ "Action", @@ -135,10 +135,10 @@ "MIME-Version": "1.0", "Message-Id": "<20150211194857.19888.1605637474.0@host>", "OpenPGP": "id=E2F104EE8B01F675;\n url=\"https://domain.org/key/cuzcuz2\"; preference=\"signencrypt\"", - "Received": "from 0.3.9-1-gc1f9c92 (unknown [127.0.0.1])\n (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))\n (Client CN \"UNLIMITEDdbe63unx9tfxa286ol3che4vx\",\n Issuer \"LEAP_Example Root CA (client certificates only!)\" (verified OK))\n by domain.org (Postfix) with ESMTPS id 499F57FF7C\n for ; Wed, 11 Feb 2015 20:49:10 +0100 (CET)", + "Received": "from 0.3.9-1-gc1f9c92 (unknown [127.0.0.1])\n (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))\n (Client CN \"UNLIMITEDdbe63unx9tfxa286ol3che4vx\",\n Issuer \"LEAP_Example Root CA (client certificates only!)\" (verified OK))\n by domain.org (Postfix) with ESMTPS id 499F57FF7C\n for ; Wed, 11 Feb 2015 20:49:10 +0100 (CET)", "Return-Path": "", "Subject": "volte", - "To": "inexistentaccount@domain.com" + "To": "this_mail_was_bounced@domain.com" }, "multi": true, "part_map": { -- cgit v1.2.3