summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorPatrick Maia <pmaia@thoughtworks.com>2015-02-20 11:14:58 -0300
committerPatrick Maia <pmaia@thoughtworks.com>2015-02-20 11:17:01 -0300
commit2bd46a719b947b0839f47fd9e4bf5517f396fd29 (patch)
tree3f9acb994c118163fea8eeaafedf030a20022b15 /service
parentc5f29f136f293a51d2fd42fcfd8fc18a39f09cfa (diff)
Issue #174 - rejects bounced addresses on contacts suggestions
Diffstat (limited to 'service')
-rw-r--r--service/pixelated/adapter/search/__init__.py2
-rw-r--r--service/pixelated/adapter/search/contacts.py13
-rw-r--r--service/test/integration/test_contacts.py31
-rw-r--r--service/test/unit/adapter/test_mail.py2
-rw-r--r--service/test/unit/fixtures/bounced_mail_hdoc.json8
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": {