diff options
Diffstat (limited to 'service')
| -rw-r--r-- | service/pixelated/adapter/search/__init__.py | 2 | ||||
| -rw-r--r-- | service/pixelated/adapter/search/contacts.py | 13 | ||||
| -rw-r--r-- | service/test/integration/test_contacts.py | 31 | ||||
| -rw-r--r-- | service/test/unit/adapter/test_mail.py | 2 | ||||
| -rw-r--r-- | 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 <http://www.gnu.org/licenses/>.  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 <recipient@to.com>' in contacts)              self.assertTrue('Recipient Copied <recipient@cc.com>' in contacts)              self.assertTrue('Recipient Carbon <recipient@bcc.com>' 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 <inexistentaccount@domain.com>; 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 <this_mail_was_bounced@domain.com>; Wed, 11 Feb 2015 20:49:10 +0100 (CET)",                          "Return-Path": "<cuzcuz2@domain.org>",                          "Subject": "volte", -                        "To": "inexistentaccount@domain.com" +                        "To": "this_mail_was_bounced@domain.com"                      },                      "multi": true,                      "part_map": { | 
