From 5585ff784940dee267576d097076de66797f9188 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 2 Jan 2014 16:08:09 -0400 Subject: fix tests after rewrite --- src/leap/mail/imap/messages.py | 94 +++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 16 deletions(-) (limited to 'src/leap/mail/imap/messages.py') diff --git a/src/leap/mail/imap/messages.py b/src/leap/mail/imap/messages.py index 47c40d5..80411f9 100644 --- a/src/leap/mail/imap/messages.py +++ b/src/leap/mail/imap/messages.py @@ -20,9 +20,11 @@ LeapMessage and MessageCollection. import copy import logging import StringIO -from collections import namedtuple + +from collections import defaultdict, namedtuple from twisted.mail import imap4 +from twisted.internet import defer from twisted.python import log from u1db import errors as u1db_errors from zope.interface import implements @@ -182,6 +184,7 @@ class MessageAttachment(object): if not self._msg: return {} headers = dict(self._msg.items()) + names = map(lambda s: s.upper(), names) if negate: cond = lambda key: key.upper() not in names @@ -329,6 +332,7 @@ class LeapMessage(fields, MailParser, MBoxParser): doc.content[self.FLAGS_KEY] = flags doc.content[self.SEEN_KEY] = self.SEEN_FLAG in flags doc.content[self.RECENT_KEY] = self.RECENT_FLAG in flags + doc.content[self.DEL_KEY] = self.DELETED_FLAG in flags self._soledad.put_doc(doc) def addFlags(self, flags): @@ -455,6 +459,7 @@ class LeapMessage(fields, MailParser, MBoxParser): headers = self._get_headers() if not headers: return {'content-type': ''} + names = map(lambda s: s.upper(), names) if negate: cond = lambda key: key.upper() not in names @@ -465,8 +470,8 @@ class LeapMessage(fields, MailParser, MBoxParser): # twisted imap server expects headers to be lowercase head = dict( - map(str, (key, value)) if key.lower() != "content-type" - else map(str, (key.lower(), value)) + (str(key), map(str, value)) if key.lower() != "content-type" + else (str(key.lower(), map(str, value))) for (key, value) in head.items()) # unpack and filter original dict by negate-condition @@ -670,6 +675,9 @@ class LeapMessage(fields, MailParser, MBoxParser): # until we think about a good way of deorphaning. # Maybe a crawler of unreferenced docs. + uid = self._uid + print "removing...", uid + fd = self._get_flags_doc() hd = self._get_headers_doc() #bd = self._get_body_doc() @@ -682,7 +690,11 @@ class LeapMessage(fields, MailParser, MBoxParser): #docs.append(ad) for d in filter(None, docs): - self._soledad.delete_doc(d) + try: + self._soledad.delete_doc(d) + except Exception as exc: + logger.error(exc) + return uid def does_exist(self): """ @@ -849,6 +861,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): fields.SEEN_KEY: False, fields.RECENT_KEY: True, + fields.DEL_KEY: False, fields.FLAGS_KEY: [], fields.MULTIPART_KEY: False, fields.SIZE_KEY: 0 @@ -921,7 +934,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): self.soledad_writer = MessageProducer( SoledadDocWriter(soledad), - period=0.05) + period=0.02) def _get_empty_doc(self, _type=FLAGS_DOC): """ @@ -966,7 +979,9 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): (self.FLAGS_DOC, self.HEADERS_DOC, self.BODY_DOC)) msg = self._get_parsed_msg(raw) - headers = dict(msg) + headers = defaultdict(list) + for k, v in msg.items(): + headers[k].append(v) raw_str = msg.as_string() chash = self._get_hash(msg) multi = msg.is_multipart() @@ -987,7 +1002,8 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): inner_parts.append(p) else: body = msg.get_payload() - logger.debug("adding msg (multipart:%s)" % multi) + logger.debug("adding msg with uid %s (multipart:%s)" % ( + uid, multi)) # flags doc --------------------------------------- fd[self.MBOX_KEY] = self.mbox @@ -998,26 +1014,33 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): if flags: fd[self.FLAGS_KEY] = map(self._stringify, flags) fd[self.SEEN_KEY] = self.SEEN_FLAG in flags - fd[self.RECENT_KEY] = self.RECENT_FLAG in flags + fd[self.DEL_KEY] = self.DELETED_FLAG in flags + fd[self.RECENT_KEY] = True # set always by default # headers doc ---------------------------------------- hd[self.CONTENT_HASH_KEY] = chash hd[self.HEADERS_KEY] = headers + + print "headers" + import pprint + pprint.pprint(headers) + if not subject and self.SUBJECT_FIELD in headers: - hd[self.SUBJECT_KEY] = headers[self.SUBJECT_FIELD] + hd[self.SUBJECT_KEY] = first(headers[self.SUBJECT_FIELD]) else: hd[self.SUBJECT_KEY] = subject if not date and self.DATE_FIELD in headers: - hd[self.DATE_KEY] = headers[self.DATE_FIELD] + hd[self.DATE_KEY] = first(headers[self.DATE_FIELD]) else: hd[self.DATE_KEY] = date if multi: + # XXX fix for multipart nested case hd[self.NUM_PARTS_KEY] = len(msg.get_payload()) # body doc bd[self.CONTENT_HASH_KEY] = chash bd[self.BODY_KEY] = body - # in an ideal world, we would not need to save a copy of the + # XXX in an ideal world, we would not need to save a copy of the # raw message. But we'll keep it until we can be sure that # we can rebuild the original message from the parts. bd[self.RAW_KEY] = raw_str @@ -1062,14 +1085,29 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): self.soledad_writer.put(ptuple( mode=ptuple.ATTACHMENT_CREATE, payload=at)) - def remove(self, msg): + def _remove_cb(self, result): + return result + + def remove_all_deleted(self): + """ + Removes all messages flagged as deleted. """ - Removes a message. + delete_deferl = [] + for msg in self.get_deleted(): + delete_deferl.append(msg.remove()) + d1 = defer.gatherResults(delete_deferl, consumeErrors=True) + d1.addCallback(self._remove_cb) + return d1 - :param msg: a Leapmessage instance + def remove(self, msg): + """ + Remove a given msg. + :param msg: the message to be removed :type msg: LeapMessage """ - msg.remove() + d = msg.remove() + d.addCallback(self._remove_cb) + return d # getters @@ -1178,7 +1216,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): def recent_iter(self): """ - Get an iterator for the message docs with `recent` flag. + Get an iterator for the message UIDs with `recent` flag. :return: iterator through recent message docs :rtype: iterable @@ -1210,6 +1248,30 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser): fields.TYPE_FLAGS_VAL, self.mbox, '1') return count + # deleted messages + + def deleted_iter(self): + """ + Get an iterator for the message UIDs with `deleted` flag. + + :return: iterator through deleted message docs + :rtype: iterable + """ + return (doc.content[self.UID_KEY] for doc in + self._soledad.get_from_index( + fields.TYPE_MBOX_DEL_IDX, + fields.TYPE_FLAGS_VAL, self.mbox, '1')) + + def get_deleted(self): + """ + Get all messages with the `Deleted` flag. + + :returns: a generator of LeapMessages + :rtype: generator + """ + return (LeapMessage(self._soledad, docid, self.mbox) + for docid in self.deleted_iter()) + def __len__(self): """ Returns the number of messages on this mailbox. -- cgit v1.2.3