summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2015-01-26 23:41:52 -0400
committerKali Kaneko <kali@leap.se>2015-01-26 23:41:52 -0400
commitaa7c770e6a88b7d9dc43e7446ea79e5e705586b8 (patch)
treec22bc9dfc375a8a9d23c33caa9f1fe73ba50cbfd
parent26e208c23d8996e8babfe74fdc8b8ccc7c8b1a2e (diff)
save drafts: search by msg-id
-rw-r--r--src/leap/mail/adaptors/soledad.py24
-rw-r--r--src/leap/mail/imap/mailbox.py13
-rw-r--r--src/leap/mail/imap/server.py57
-rw-r--r--src/leap/mail/mail.py19
-rw-r--r--src/leap/mail/mailbox_indexer.py2
5 files changed, 100 insertions, 15 deletions
diff --git a/src/leap/mail/adaptors/soledad.py b/src/leap/mail/adaptors/soledad.py
index 542ad94..4dc02a1 100644
--- a/src/leap/mail/adaptors/soledad.py
+++ b/src/leap/mail/adaptors/soledad.py
@@ -966,6 +966,30 @@ class SoledadMailAdaptor(SoledadIndexMixin):
d.addErrback(self._errback)
return d
+ # search api
+
+ def get_mdoc_id_from_msgid(self, store, mbox_uuid, msgid):
+ """
+ Get the UID for a message with the passed msgid (the one in the headers
+ msg-id).
+ This is used by the MUA to retrieve the recently saved draft.
+ """
+ type_ = HeaderDocWrapper.model.type_
+ uuid = mbox_uuid.replace('-', '_')
+
+ msgid_index = indexes.TYPE_MSGID_IDX
+
+ def get_mdoc_id(hdoc):
+ if not hdoc:
+ return None
+ hdoc = hdoc[0]
+ mdoc_id = hdoc.doc_id.replace("H-", "M-%s-" % uuid)
+ return mdoc_id
+
+ d = store.get_from_index(msgid_index, type_, msgid)
+ d.addCallback(get_mdoc_id)
+ return d
+
# Mailbox handling
def get_or_create_mbox(self, store, name):
diff --git a/src/leap/mail/imap/mailbox.py b/src/leap/mail/imap/mailbox.py
index c826e86..be7f70c 100644
--- a/src/leap/mail/imap/mailbox.py
+++ b/src/leap/mail/imap/mailbox.py
@@ -842,18 +842,17 @@ class IMAPMailbox(object):
# '52D44F11.9060107@dev.bitmask.net']
# TODO hardcoding for now! -- we'll support generic queries later on
- # but doing a quickfix for avoiding duplicat saves in the draft folder.
- # See issue #4209
+ # but doing a quickfix for avoiding duplicate saves in the draft
+ # folder. # See issue #4209
if len(query) > 2:
if query[1] == 'HEADER' and query[2].lower() == "message-id":
msgid = str(query[3]).strip()
logger.debug("Searching for %s" % (msgid,))
- d = self.messages._get_uid_from_msgid(str(msgid))
- # XXX remove gatherResults
- d1 = defer.gatherResults([d])
- # we want a list, so return it all the same
- return d1
+
+ d = self.collection.get_uid_from_msgid(str(msgid))
+ d.addCallback(lambda result: [result])
+ return d
# nothing implemented for any other query
logger.warning("Cannot process query: %s" % (query,))
diff --git a/src/leap/mail/imap/server.py b/src/leap/mail/imap/server.py
index 027fd7a..abe16be 100644
--- a/src/leap/mail/imap/server.py
+++ b/src/leap/mail/imap/server.py
@@ -199,8 +199,7 @@ class LEAPIMAPServer(imap4.IMAP4Server):
a deferred, the client will only be informed of success (or failure)
when the deferred's callback (or errback) is invoked.
"""
- # TODO return the output of _memstore.is_writing
- # XXX and that should return a deferred!
+ # TODO implement a collection of ongoing deferreds?
return None
#############################################################
@@ -499,6 +498,50 @@ class LEAPIMAPServer(imap4.IMAP4Server):
auth_DELETE = (do_DELETE, arg_astring)
select_DELETE = auth_DELETE
+ # -----------------------------------------------------------------------
+ # Patched just to allow __cbAppend to receive a deferred from messageCount
+ # TODO format and send upstream.
+ def do_APPEND(self, tag, mailbox, flags, date, message):
+ mailbox = self._parseMbox(mailbox)
+ maybeDeferred(self.account.select, mailbox).addCallback(
+ self._cbAppendGotMailbox, tag, flags, date, message).addErrback(
+ self._ebAppendGotMailbox, tag)
+
+ def __ebAppend(self, failure, tag):
+ self.sendBadResponse(tag, 'APPEND failed: ' + str(failure.value))
+
+ def _cbAppendGotMailbox(self, mbox, tag, flags, date, message):
+ if not mbox:
+ self.sendNegativeResponse(tag, '[TRYCREATE] No such mailbox')
+ return
+
+ d = mbox.addMessage(message, flags, date)
+ d.addCallback(self.__cbAppend, tag, mbox)
+ d.addErrback(self.__ebAppend, tag)
+
+ def _ebAppendGotMailbox(self, failure, tag):
+ self.sendBadResponse(
+ tag, "Server error encountered while opening mailbox.")
+ log.err(failure)
+
+ def __cbAppend(self, result, tag, mbox):
+
+ # XXX patched ---------------------------------
+ def send_response(count):
+ self.sendUntaggedResponse('%d EXISTS' % count)
+ self.sendPositiveResponse(tag, 'APPEND complete')
+
+ d = mbox.getMessageCount()
+ d.addCallback(send_response)
+ return d
+ # XXX patched ---------------------------------
+
+ # -----------------------------------------------------------------------
+
+ auth_APPEND = (do_APPEND, arg_astring, imap4.IMAP4Server.opt_plist,
+ imap4.IMAP4Server.opt_datetime, arg_literal)
+ select_APPEND = auth_APPEND
+
# Need to override the command table after patching
# arg_astring and arg_literal, except on the methods that we are already
# overriding.
@@ -511,10 +554,10 @@ class LEAPIMAPServer(imap4.IMAP4Server):
# do_RENAME = imap4.IMAP4Server.do_RENAME
# do_SUBSCRIBE = imap4.IMAP4Server.do_SUBSCRIBE
# do_UNSUBSCRIBE = imap4.IMAP4Server.do_UNSUBSCRIBE
+ # do_APPEND = imap4.IMAP4Server.do_APPEND
# -------------------------------------------------
do_LOGIN = imap4.IMAP4Server.do_LOGIN
do_STATUS = imap4.IMAP4Server.do_STATUS
- do_APPEND = imap4.IMAP4Server.do_APPEND
do_COPY = imap4.IMAP4Server.do_COPY
_selectWork = imap4.IMAP4Server._selectWork
@@ -539,6 +582,10 @@ class LEAPIMAPServer(imap4.IMAP4Server):
# re-add if we stop overriding DELETE
# auth_DELETE = (do_DELETE, arg_astring)
# select_DELETE = auth_DELETE
+ # auth_APPEND = (do_APPEND, arg_astring, opt_plist, opt_datetime,
+ # arg_literal)
+ # select_APPEND = auth_APPEND
+
# ----------------------------------------------------
auth_RENAME = (do_RENAME, arg_astring, arg_astring)
@@ -559,10 +606,6 @@ class LEAPIMAPServer(imap4.IMAP4Server):
auth_STATUS = (do_STATUS, arg_astring, arg_plist)
select_STATUS = auth_STATUS
- auth_APPEND = (do_APPEND, arg_astring, opt_plist, opt_datetime,
- arg_literal)
- select_APPEND = auth_APPEND
-
select_COPY = (do_COPY, arg_seqset, arg_astring)
#############################################################
diff --git a/src/leap/mail/mail.py b/src/leap/mail/mail.py
index d986f59..2766524 100644
--- a/src/leap/mail/mail.py
+++ b/src/leap/mail/mail.py
@@ -460,6 +460,25 @@ class MessageCollection(object):
"""
return self.mbox_indexer.all_uid_iter(self.mbox_uuid)
+ def get_uid_from_msgid(self, msgid):
+ """
+ Return the UID(s) of the matching msg-ids for this mailbox collection.
+ """
+ if not self.is_mailbox_collection():
+ raise NotImplementedError()
+
+ def get_uid(mdoc_id):
+ if not mdoc_id:
+ return None
+ d = self.mbox_indexer.get_uid_from_doc_id(
+ self.mbox_uuid, mdoc_id)
+ return d
+
+ d = self.adaptor.get_mdoc_id_from_msgid(
+ self.store, self.mbox_uuid, msgid)
+ d.addCallback(get_uid)
+ return d
+
# Manipulate messages
def add_msg(self, raw_msg, flags=tuple(), tags=tuple(), date=""):
diff --git a/src/leap/mail/mailbox_indexer.py b/src/leap/mail/mailbox_indexer.py
index 4eb0fa8..3bec41e 100644
--- a/src/leap/mail/mailbox_indexer.py
+++ b/src/leap/mail/mailbox_indexer.py
@@ -120,7 +120,7 @@ class MailboxIndexer(object):
The doc_id must be in the format:
- M+<mailbox>+<content-hash-of-the-message>
+ M-<mailbox>-<content-hash-of-the-message>
:param mailbox: the mailbox name
:type mailbox: str