From 9c40103a3c3dcdb3e4c4edae9f466f1701e022fc Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 Jan 2015 12:12:24 -0400 Subject: Complete IMAP implementation, update tests --- src/leap/mail/mail.py | 114 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 21 deletions(-) (limited to 'src/leap/mail/mail.py') diff --git a/src/leap/mail/mail.py b/src/leap/mail/mail.py index b2caa33..8137f97 100644 --- a/src/leap/mail/mail.py +++ b/src/leap/mail/mail.py @@ -172,7 +172,7 @@ class Message(object): :return: An RFC822-formatted date string. :rtype: str """ - return self._wrapper.fdoc.date + return self._wrapper.hdoc.date # imap.IMessageParts @@ -271,9 +271,10 @@ class MessageCollection(object): store = None messageklass = Message - def __init__(self, adaptor, store, mbox_indexer=None, mbox_wrapper=None): + def __init__(self, adaptor, store, mbox_indexer=None, mbox_wrapper=None, + count=None): """ - Constructore for a MessageCollection. + Constructor for a MessageCollection. """ self.adaptor = adaptor self.store = store @@ -317,7 +318,7 @@ class MessageCollection(object): wrapper = getattr(self, "mbox_wrapper", None) if not wrapper: return None - return wrapper.mbox_uuid + return wrapper.uuid def get_mbox_attr(self, attr): return getattr(self.mbox_wrapper, attr) @@ -364,10 +365,18 @@ class MessageCollection(object): self.messageklass, self.store, doc_id, uid=uid, get_cdocs=get_cdocs) - d = self.mbox_indexer.get_doc_id_from_uid(self.mbox_name, uid) + d = self.mbox_indexer.get_doc_id_from_uid(self.mbox_uuid, uid) d.addCallback(get_msg_from_mdoc_id) return d + # TODO deprecate ??? --- + def _prime_count(self): + def update_count(count): + self._count = count + d = self.mbox_indexer.count(self.mbox_name) + d.addCallback(update_count) + return d + def count(self): """ Count the messages in this collection. @@ -376,7 +385,17 @@ class MessageCollection(object): """ if not self.is_mailbox_collection(): raise NotImplementedError() - return self.mbox_indexer.count(self.mbox_name) + + d = self.mbox_indexer.count(self.mbox_uuid) + return d + + def count_recent(self): + # FIXME HACK + return 0 + + def count_unseen(self): + # FIXME hack + return 0 def get_uid_next(self): """ @@ -385,7 +404,13 @@ class MessageCollection(object): :return: a Deferred that will fire with the integer for the next uid. :rtype: Deferred """ - return self.mbox_indexer.get_next_uid(self.mbox_name) + return self.mbox_indexer.get_next_uid(self.mbox_uuid) + + def all_uid_iter(self): + """ + Iterator through all the uids for this collection. + """ + return self.mbox_indexer.all_uid_iter(self.mbox_uuid) # Manipulate messages @@ -397,6 +422,7 @@ class MessageCollection(object): flags = tuple() if not tags: tags = tuple() + leap_assert_type(flags, tuple) leap_assert_type(date, str) @@ -408,10 +434,10 @@ class MessageCollection(object): else: mbox_id = self.mbox_uuid + wrapper.set_mbox_uuid(mbox_id) wrapper.set_flags(flags) wrapper.set_tags(tags) wrapper.set_date(date) - wrapper.set_mbox_uuid(mbox_id) def insert_mdoc_id(_, wrapper): doc_id = wrapper.mdoc.doc_id @@ -420,6 +446,8 @@ class MessageCollection(object): d = wrapper.create(self.store) d.addCallback(insert_mdoc_id, wrapper) + d.addErrback(lambda f: f.printTraceback()) + return d def copy_msg(self, msg, newmailbox): @@ -453,8 +481,47 @@ class MessageCollection(object): d.addCallback(delete_mdoc_id, wrapper) return d + def delete_all_flagged(self): + """ + Delete all messages flagged as \\Deleted. + Used from IMAPMailbox.expunge() + """ + def get_uid_list(hashes): + d = [] + for h in hashes: + d.append(self.mbox_indexer.get_uid_from_doc_id( + self.mbox_uuid, h)) + return defer.gatherResults(d), hashes + + def delete_uid_entries((uids, hashes)): + d = [] + for h in hashes: + d.append(self.mbox_indexer.delete_doc_by_hash( + self.mbox_uuid, h)) + return defer.gatherResults(d).addCallback( + lambda _: uids) + + mdocs_deleted = self.adaptor.del_all_flagged_messages( + self.store, self.mbox_uuid) + mdocs_deleted.addCallback(get_uid_list) + mdocs_deleted.addCallback(delete_uid_entries) + return mdocs_deleted + # TODO should add a delete-by-uid to collection? + def delete_all_docs(self): + def del_all_uid(uid_list): + deferreds = [] + for uid in uid_list: + d = self.get_message_by_uid(uid) + d.addCallback(lambda msg: msg.delete()) + deferreds.append(d) + return defer.gatherResults(deferreds) + + d = self.all_uid_iter() + d.addCallback(del_all_uid) + return d + def _update_flags_or_tags(self, old, new, mode): if mode == Flagsmode.APPEND: final = list((set(tuple(old) + new))) @@ -509,45 +576,49 @@ class Account(object): adaptor_class = SoledadMailAdaptor store = None - def __init__(self, store): + def __init__(self, store, ready_cb=None): self.store = store self.adaptor = self.adaptor_class() self.mbox_indexer = MailboxIndexer(self.store) + self.deferred_initialization = defer.Deferred() self._initialized = False - self._deferred_initialization = defer.Deferred() + self._ready_cb = ready_cb - self._initialize_storage() + self._init_d = self._initialize_storage() def _initialize_storage(self): def add_mailbox_if_none(mboxes): if not mboxes: - self.add_mailbox(INBOX_NAME) + return self.add_mailbox(INBOX_NAME) def finish_initialization(result): self._initialized = True - self._deferred_initialization.callback(None) + self.deferred_initialization.callback(None) + if self._ready_cb is not None: + self._ready_cb() d = self.adaptor.initialize_store(self.store) d.addCallback(lambda _: self.list_all_mailbox_names()) d.addCallback(add_mailbox_if_none) d.addCallback(finish_initialization) + return d def callWhenReady(self, cb, *args, **kw): - # use adaptor.store_ready instead? if self._initialized: cb(self, *args, **kw) return defer.succeed(None) else: - self._deferred_initialization.addCallback(cb, *args, **kw) - return self._deferred_initialization + self.deferred_initialization.addCallback(cb, *args, **kw) + return self.deferred_initialization # # Public API Starts # def list_all_mailbox_names(self): + def filter_names(mboxes): return [m.mbox for m in mboxes] @@ -563,8 +634,11 @@ class Account(object): def create_uuid(wrapper): if not wrapper.uuid: - wrapper.uuid = uuid.uuid4() - return wrapper.update(self.store) + wrapper.uuid = str(uuid.uuid4()) + d = wrapper.update(self.store) + d.addCallback(lambda _: wrapper) + return d + return wrapper def create_uid_table_cb(wrapper): d = self.mbox_indexer.create_table(wrapper.uuid) @@ -599,7 +673,7 @@ class Account(object): def _rename_mbox(wrapper): wrapper.mbox = newname - return wrapper.update(self.store) + return wrapper, wrapper.update(self.store) d = self.adaptor.get_or_create_mbox(self.store, oldname) d.addCallback(_rename_mbox) @@ -616,8 +690,6 @@ class Account(object): return MessageCollection( self.adaptor, self.store, self.mbox_indexer, mbox_wrapper) - mboxwrapper_klass = self.adaptor.mboxwrapper_klass - #d = mboxwrapper_klass.get_or_create(name) d = self.adaptor.get_or_create_mbox(self.store, name) d.addCallback(get_collection_for_mailbox) return d -- cgit v1.2.3