summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorPatrick Maia <pmaia@thoughtworks.com>2014-09-17 02:02:28 -0300
committerPatrick Maia <pmaia@thoughtworks.com>2014-09-17 13:53:25 -0300
commit95b0e2e6f834804630bf9d091b156ac68ff20583 (patch)
tree9bff8ebac2134cf23fd2bcd92f1a9500d8dd5ebf /service
parentc272f64293bb0157eb7eb1ebba899935f8ed2c3a (diff)
74 - moves move_to_trash logic to PixelatedMailboxes and adds some tests
Diffstat (limited to 'service')
-rw-r--r--service/pixelated/adapter/mail_service.py11
-rw-r--r--service/pixelated/adapter/pixelated_mail.py42
-rw-r--r--service/pixelated/adapter/pixelated_mailbox.py19
-rw-r--r--service/pixelated/adapter/pixelated_mailboxes.py11
-rw-r--r--service/pixelated/user_agent.py2
-rw-r--r--service/test/adapter/mail_service_test.py8
-rw-r--r--service/test/adapter/pixelated_mail_test.py33
-rw-r--r--service/test/adapter/pixelated_mailbox_test.py21
-rw-r--r--service/test/adapter/test_tag_service.py4
9 files changed, 92 insertions, 59 deletions
diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py
index 5f651187..6906c431 100644
--- a/service/pixelated/adapter/mail_service.py
+++ b/service/pixelated/adapter/mail_service.py
@@ -14,7 +14,6 @@
# 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 pixelated.adapter.tag_service import TagService
-from pixelated.support.id_gen import gen_pixelated_uid
class MailService:
@@ -38,9 +37,7 @@ class MailService:
def update_tags(self, mail_id, new_tags):
mail = self.mail(mail_id)
- added, removed = mail.update_tags(set(new_tags))
- self.tag_service.notify_tags_updated(added, removed, mail_id)
- return new_tags
+ return mail.update_tags(set(new_tags))
def mail(self, mail_id):
return self.mailboxes.mail(mail_id)
@@ -73,10 +70,8 @@ class MailService:
raise NotImplementedError()
def delete_mail(self, mail_id):
- mail = self.mailboxes.mail(mail_id)
- new_mailbox_tag, old_mailbox_tag = mail.move_to(self.mailboxes.trash())
- self.tag_service.notify_tags_updated([], [old_mailbox_tag], mail_id)
- self.tag_service.notify_tags_updated([new_mailbox_tag], [], None)
+ _mail = self.mailboxes.mail(mail_id)
+ return self.mailboxes.move_to_trash(_mail)
def save_draft(self, draft):
raise NotImplementedError()
diff --git a/service/pixelated/adapter/pixelated_mail.py b/service/pixelated/adapter/pixelated_mail.py
index c732f5a0..af82eb7f 100644
--- a/service/pixelated/adapter/pixelated_mail.py
+++ b/service/pixelated/adapter/pixelated_mail.py
@@ -15,6 +15,7 @@
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
from pixelated.adapter.status import Status
from pixelated.support.id_gen import gen_pixelated_uid
+from pixelated.adapter.tag_service import TagService
import json
import pixelated.support.date
import dateutil.parser as dateparser
@@ -32,10 +33,12 @@ class PixelatedMail:
self.tags = []
@staticmethod
- def from_leap_mail(leap_mail, leap_mailbox=None):
+ def from_leap_mail(leap_mail, tag_service=TagService.get_instance()):
mail = PixelatedMail()
+ mail.tag_service = tag_service
mail.leap_mail = leap_mail
- mail.leap_mailbox = leap_mailbox
+ mail.mailbox_name = leap_mail._mbox
+ mail.ident = gen_pixelated_uid(leap_mail._mbox, leap_mail.getUID())
mail.body = leap_mail.bdoc.content['raw']
mail.headers = mail._extract_headers()
mail.headers['date'] = PixelatedMail._get_date(mail.headers)
@@ -48,10 +51,6 @@ class PixelatedMail:
def is_recent(self):
return Status('recent') in self.status
- @property
- def ident(self):
- return gen_pixelated_uid(self.leap_mailbox.mbox, self.leap_mail.getUID())
-
def set_from(self, _from):
self.headers['from'] = [_from]
@@ -87,13 +86,17 @@ class PixelatedMail:
return set(tags)
return set(json.loads(tags))
+ def remove_all_tags(self):
+ self.update_tags(set([]))
+
def update_tags(self, tags):
old_tags = self.tags
self.tags = tags
removed = old_tags.difference(tags)
added = tags.difference(old_tags)
self._persist_mail_tags(tags)
- return added, removed
+ self.tag_service.notify_tags_updated(added, removed, self.ident)
+ return self.tags
def mark_as_read(self):
self.leap_mail.setFlags((Status.PixelatedStatus.SEEN,), 1)
@@ -113,27 +116,12 @@ class PixelatedMail:
def has_tag(self, tag):
return tag in self.tags
- def move_to(self, destiny_mailbox):
- new_leap_mail = destiny_mailbox.add_mail(self)
- self._delete_from_leap_mailbox()
- old_mailbox_tag = self.leap_mailbox.mbox.lower()
- self._update_leap_references(destiny_mailbox.leap_mailbox, new_leap_mail)
-
- return destiny_mailbox.mailbox_tag, old_mailbox_tag
-
- def _delete_from_leap_mailbox(self):
- self.leap_mail.setFlags((Status.PixelatedStatus.DELETED,), 1)
- self.leap_mailbox.expunge()
-
- def _update_leap_references(self, new_leap_mailbox, new_leap_mail):
- self.leap_mailbox = new_leap_mailbox
- self.leap_mail = new_leap_mail
-
def raw_message(self):
- raw_message = ''.join("%s: %s\n" % (key, value) for key, value in self.leap_mail.hdoc.content['headers'].items())
- raw_message += '\n\n'
- raw_message += self.leap_mail.bdoc.content['raw']
- return raw_message
+ mime = MIMEMultipart()
+ for key, value in self.leap_mail.hdoc.content['headers'].items():
+ mime[key] = value
+ mime.attach(MIMEText(self.leap_mail.bdoc.content['raw'], 'plain'))
+ return mime.as_string()
def as_dict(self):
statuses = [status.name for status in self.status]
diff --git a/service/pixelated/adapter/pixelated_mailbox.py b/service/pixelated/adapter/pixelated_mailbox.py
index 7d2a1fa5..a6dc4116 100644
--- a/service/pixelated/adapter/pixelated_mailbox.py
+++ b/service/pixelated/adapter/pixelated_mailbox.py
@@ -14,7 +14,9 @@
# 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 pixelated.support.id_gen import gen_pixelated_uid
from pixelated.adapter.pixelated_mail import PixelatedMail
+from pixelated.adapter.status import Status
from pixelated.adapter.tag_service import TagService
from crochet import wait_for
@@ -45,7 +47,7 @@ class PixelatedMailbox:
result = []
for mail in mails:
mail._collection = mails
- pixelated_mail = PixelatedMail.from_leap_mail(mail, self.leap_mailbox)
+ pixelated_mail = PixelatedMail.from_leap_mail(mail)
self.add_mailbox_tag_if_not_there(pixelated_mail)
result.append(pixelated_mail)
return result
@@ -60,13 +62,18 @@ class PixelatedMailbox:
if message.ident == mail_id:
return message
- def add_mail(self, mail):
- original_flags = mail.leap_mail.getFlags()
- self.leap_mailbox.addMessage(mail.raw_message(), original_flags)
+ def add(self, mail):
+ leap_id = self._do_add_async(mail)
+ new_id = gen_pixelated_uid(self.leap_mailbox.mbox, leap_id)
+ return new_id
@wait_for(timeout=3.0)
- def add(self, mail):
- return self.leap_mailbox.messages.add_msg(mail.to_smtp_format())
+ def _do_add_async(self, mail):
+ return self.leap_mailbox.messages.add_msg(mail.raw_message())
+
+ def remove(self, mail):
+ mail.leap_mail.setFlags((Status.PixelatedStatus.DELETED,), 1)
+ self.leap_mailbox.expunge()
@classmethod
def create(cls, account, mailbox_name='INBOX'):
diff --git a/service/pixelated/adapter/pixelated_mailboxes.py b/service/pixelated/adapter/pixelated_mailboxes.py
index b5cac602..aa9015e5 100644
--- a/service/pixelated/adapter/pixelated_mailboxes.py
+++ b/service/pixelated/adapter/pixelated_mailboxes.py
@@ -7,6 +7,7 @@ class PixelatedMailBoxes():
self.account = account
def _create_or_get(self, mailbox_name):
+ mailbox_name = mailbox_name.upper()
if mailbox_name not in self.account.mailboxes:
self.account.addMailbox(mailbox_name)
return PixelatedMailbox.create(self.account, mailbox_name)
@@ -35,11 +36,15 @@ class PixelatedMailBoxes():
mail.set_ident(drafts.mailbox_name, draft_id)
return mail
+ def move_to_trash(self, mail):
+ mail.remove_all_tags()
+ origin_mailbox = mail.mailbox_name
+
+ self._create_or_get(origin_mailbox).remove(mail)
+ return self.trash().add(mail)
+
def mail(self, mail_id):
for mailbox in self.mailboxes:
mail = mailbox.mail(mail_id)
if mail:
return mail
-
- def mailbox_exists(self, name):
- return name.upper() in map(lambda x: x.upper(), self.account.mailboxes)
diff --git a/service/pixelated/user_agent.py b/service/pixelated/user_agent.py
index 54643255..c386c6e6 100644
--- a/service/pixelated/user_agent.py
+++ b/service/pixelated/user_agent.py
@@ -128,7 +128,7 @@ def mail(mail_id):
def mail_tags(mail_id):
new_tags = map(lambda tag: tag.lower(), request.get_json()['newtags'])
tags = mail_service.update_tags(mail_id, new_tags)
- return respond_json(tags)
+ return respond_json(list(tags))
@app.route('/mail/<mail_id>/read', methods=['POST'])
diff --git a/service/test/adapter/mail_service_test.py b/service/test/adapter/mail_service_test.py
index 782e891a..517368e2 100644
--- a/service/test/adapter/mail_service_test.py
+++ b/service/test/adapter/mail_service_test.py
@@ -45,3 +45,11 @@ class TestMailService(unittest.TestCase):
self.mail_service.create_draft(mail)
verify(self.mailboxes).add_draft(mail)
+
+ def test_delete_mail(self):
+ mail = mock()
+ when(self.mailboxes).mail(any()).thenReturn(mail)
+
+ self.mail_service.delete_mail(1)
+
+ verify(self.mailboxes).move_to_trash(mail)
diff --git a/service/test/adapter/pixelated_mail_test.py b/service/test/adapter/pixelated_mail_test.py
index 4292883c..3ba5e659 100644
--- a/service/test/adapter/pixelated_mail_test.py
+++ b/service/test/adapter/pixelated_mail_test.py
@@ -14,10 +14,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
import unittest
+import os
import pixelated.support.date
-from pixelated.adapter.pixelated_mail import PixelatedMail
import test_helper
+from pixelated.adapter.pixelated_mail import PixelatedMail
+from pixelated.adapter.tag_service import TagService
+from pixelated.adapter.tag_index import TagIndex
+from pixelated.adapter.tag import Tag
+from mock import Mock
class TestPixelatedMail(unittest.TestCase):
@@ -72,11 +77,10 @@ class TestPixelatedMail(unittest.TestCase):
self.assertEqual('date now', mail.headers['date'])
- def test_update_tags_return_a_set_for_added_tags_and_a_set_for_removed_ones(self):
- pixelated_mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-tags': '["custom_1", "custom_2"]'}))
- added, removed = pixelated_mail.update_tags(set(['custom_1', 'custom_3']))
- self.assertEquals(set(['custom_3']), added)
- self.assertEquals(set(['custom_2']), removed)
+ def test_update_tags_return_a_set_with_the_current_tags(self):
+ pixelated_mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-tags': '["custom_1", "custom_2"]'}), Mock())
+ current_tags = pixelated_mail.update_tags(set(['custom_1', 'custom_3']))
+ self.assertEquals(set(['custom_3', 'custom_1']), current_tags)
def test_to_mime_multipart(self):
pixelated.support.date.iso_now = lambda: 'date now'
@@ -126,3 +130,20 @@ class TestPixelatedMail(unittest.TestCase):
mail.mark_as_not_recent()
self.assertEquals(mail.leap_mail.setFlags.call_args[0], (('\\Recent',), -1))
+
+ def test_remove_all_tags(self):
+ mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-Tags': '["skinka", "altoids"]'}), Mock())
+ self.assertEquals(set(['skinka', 'altoids']), mail.tags)
+
+ mail.remove_all_tags()
+ self.assertEquals(set([]), mail.tags)
+
+ def test_update_tags_notifies_tag_service(self):
+ db_path = '/tmp/test_update_tags_notifies_tag_service'
+ tag_service = TagService(TagIndex(db_path))
+ mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(), tag_service)
+
+ mail.update_tags(set(['new_tag']))
+ self.assertIn(Tag('new_tag'), tag_service.all_tags())
+
+ os.remove(db_path + '.db')
diff --git a/service/test/adapter/pixelated_mailbox_test.py b/service/test/adapter/pixelated_mailbox_test.py
index b4ddb32d..ac9d3f34 100644
--- a/service/test/adapter/pixelated_mailbox_test.py
+++ b/service/test/adapter/pixelated_mailbox_test.py
@@ -14,10 +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/>.
import unittest
-from mockito import *
-import leap
-import os
from pixelated.adapter.pixelated_mail import PixelatedMail
+from pixelated.adapter.status import Status
import test_helper
from pixelated.adapter.pixelated_mailbox import PixelatedMailbox
from mockito import *
@@ -42,13 +40,24 @@ class TestPixelatedMailbox(unittest.TestCase):
self.assertNotIn('spam', mailbox.mails()[0].tags)
def test_add_message_to_mailbox(self):
- PixelatedMail.from_email_address = 'pixel@ted.org'
mail = PixelatedMail.from_dict(test_helper.mail_dict())
- mail.to_smtp_format = lambda: 'the mail in smtp format'
+ mail.raw_message = lambda: 'the mail in smtp format'
leap_mailbox_messages = mock()
self.mailbox.leap_mailbox.messages = leap_mailbox_messages
- self.mailbox.add.wrapped_function(self.mailbox, mail)
+ self.mailbox._do_add_async.wrapped_function(self.mailbox, mail)
verify(leap_mailbox_messages).add_msg('the mail in smtp format')
+
+ def test_remove_message_from_mailbox(self):
+ mail = PixelatedMail.from_dict(test_helper.mail_dict())
+ mail.raw_message = lambda: 'the mail in smtp format'
+
+ mail.leap_mail = mock()
+ self.mailbox.leap_mailbox = mock()
+
+ self.mailbox.remove(mail)
+
+ verify(mail.leap_mail).setFlags((Status.PixelatedStatus.DELETED,), 1)
+ verify(self.mailbox.leap_mailbox).expunge()
diff --git a/service/test/adapter/test_tag_service.py b/service/test/adapter/test_tag_service.py
index b3a68c2b..027e6113 100644
--- a/service/test/adapter/test_tag_service.py
+++ b/service/test/adapter/test_tag_service.py
@@ -30,8 +30,8 @@ class TagServiceTest(unittest.TestCase):
self.tag_service = TagService(tag_index=self.tag_index)
def test_index_is_initialized_with_mail_tags_if_empty(self):
- mail_one = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=0, extra_headers={'X-Tags': '["tag_1"]'}), test_helper.leap_mailbox())
- mail_two = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=1, extra_headers={'X-Tags': '["tag_2"]'}), test_helper.leap_mailbox())
+ mail_one = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=0, extra_headers={'X-Tags': '["tag_1"]'}))
+ mail_two = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=1, extra_headers={'X-Tags': '["tag_2"]'}))
mails = [mail_one, mail_two]
self.tag_service.load_index(mails)