summaryrefslogtreecommitdiff
path: root/src/leap/mail/imap
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2015-01-22 03:16:32 -0400
committerKali Kaneko <kali@leap.se>2015-02-11 14:05:43 -0400
commit4c02942472be00486d04d854e987d6eda8c7df12 (patch)
treeb4a7d95c3cadcccfdf4cee4eae9134b1e613e833 /src/leap/mail/imap
parentf8c07f66bfcd97e3ae7085071c1f1efbd80e0286 (diff)
re-add support for basic multipart messages
Diffstat (limited to 'src/leap/mail/imap')
-rw-r--r--src/leap/mail/imap/mailbox.py6
-rw-r--r--src/leap/mail/imap/messages.py144
2 files changed, 81 insertions, 69 deletions
diff --git a/src/leap/mail/imap/mailbox.py b/src/leap/mail/imap/mailbox.py
index 52f4dd5..045636e 100644
--- a/src/leap/mail/imap/mailbox.py
+++ b/src/leap/mail/imap/mailbox.py
@@ -540,7 +540,11 @@ class IMAPMailbox(object):
d_msg = []
for msgid in msg_sequence:
- d_msg.append(getmsg(msgid))
+ # XXX We want cdocs because we "probably" are asked for the
+ # body. We should be smarted at do_FETCH and pass a parameter
+ # to this method in order not to prefetch cdocs if they're not
+ # going to be used.
+ d_msg.append(getmsg(msgid, get_cdocs=True))
d = defer.gatherResults(d_msg)
d.addCallback(_get_imap_msg)
diff --git a/src/leap/mail/imap/messages.py b/src/leap/mail/imap/messages.py
index 8f4c953..b7bb6ee 100644
--- a/src/leap/mail/imap/messages.py
+++ b/src/leap/mail/imap/messages.py
@@ -115,13 +115,6 @@ class IMAPMessage(object):
#
# IMessagePart
#
- def __prefetch_body_file(self):
- def assign_body_fd(fd):
- self.__body_fd = fd
- return fd
- d = self.getBodyFile()
- d.addCallback(assign_body_fd)
- return d
def getBodyFile(self, store=None):
"""
@@ -139,25 +132,6 @@ class IMAPMessage(object):
store = self.store
return self.message.get_body_file(store)
- # TODO refactor with getBodyFile in MessagePart
-
- #body = bdoc_content.get(self.RAW_KEY, "")
- #content_type = bdoc_content.get('content-type', "")
- #charset = find_charset(content_type)
- #if charset is None:
- #charset = self._get_charset(body)
- #try:
- #if isinstance(body, unicode):
- #body = body.encode(charset)
- #except UnicodeError as exc:
- #logger.error(
- #"Unicode error, using 'replace'. {0!r}".format(exc))
- #logger.debug("Attempted to encode with: %s" % charset)
- #body = body.encode(charset, 'replace')
- #finally:
- #return write_fd(body)
-
-
def getSize(self):
"""
Return the total size, in octets, of this message.
@@ -182,48 +156,8 @@ class IMAPMessage(object):
:return: A mapping of header field names to header field values
:rtype: dict
"""
- # TODO split in smaller methods -- format_headers()?
- # XXX refactor together with MessagePart method
-
headers = self.message.get_headers()
-
- # XXX keep this in the imap imessage implementation,
- # because the server impl. expects content-type to be present.
- if not headers:
- logger.warning("No headers found")
- return {str('content-type'): str('')}
-
- names = map(lambda s: s.upper(), names)
- if negate:
- cond = lambda key: key.upper() not in names
- else:
- cond = lambda key: key.upper() in names
-
- if isinstance(headers, list):
- headers = dict(headers)
-
- # default to most likely standard
- charset = find_charset(headers, "utf-8")
- headers2 = dict()
- for key, value in headers.items():
- # twisted imap server expects *some* headers to be lowercase
- # We could use a CaseInsensitiveDict here...
- if key.lower() == "content-type":
- key = key.lower()
-
- if not isinstance(key, str):
- key = key.encode(charset, 'replace')
- if not isinstance(value, str):
- value = value.encode(charset, 'replace')
-
- if value.endswith(";"):
- # bastards
- value = value[:-1]
-
- # filter original dict by negate-condition
- if cond(key):
- headers2[key] = value
- return headers2
+ return _format_headers(headers, negate, *names)
def isMultipart(self):
"""
@@ -242,7 +176,81 @@ class IMAPMessage(object):
:rtype: Any object implementing C{IMessagePart}.
:return: The specified sub-part.
"""
- return self.message.get_subpart(part)
+ subpart = self.message.get_subpart(part)
+ return IMAPMessagePart(subpart)
+
+ def __prefetch_body_file(self):
+ def assign_body_fd(fd):
+ self.__body_fd = fd
+ return fd
+ d = self.getBodyFile()
+ d.addCallback(assign_body_fd)
+ return d
+
+
+class IMAPMessagePart(object):
+
+ def __init__(self, message_part):
+ self.message_part = message_part
+
+ def getBodyFile(self, store=None):
+ return self.message_part.get_body_file()
+
+ def getSize(self):
+ return self.message_part.get_size()
+
+ def getHeaders(self, negate, *names):
+ headers = self.message_part.get_headers()
+ return _format_headers(headers, negate, *names)
+
+ def isMultipart(self):
+ return self.message_part.is_multipart()
+
+ def getSubPart(self, part):
+ subpart = self.message_part.get_subpart(part)
+ return IMAPMessagePart(subpart)
+
+
+def _format_headers(headers, negate, *names):
+ # current server impl. expects content-type to be present, so if for
+ # some reason we do not have headers, we have to return at least that
+ # one
+ if not headers:
+ logger.warning("No headers found")
+ return {str('content-type'): str('')}
+
+ names = map(lambda s: s.upper(), names)
+ if negate:
+ cond = lambda key: key.upper() not in names
+ else:
+ cond = lambda key: key.upper() in names
+
+ if isinstance(headers, list):
+ headers = dict(headers)
+
+ # default to most likely standard
+ charset = find_charset(headers, "utf-8")
+
+ _headers = dict()
+ for key, value in headers.items():
+ # twisted imap server expects *some* headers to be lowercase
+ # We could use a CaseInsensitiveDict here...
+ if key.lower() == "content-type":
+ key = key.lower()
+
+ if not isinstance(key, str):
+ key = key.encode(charset, 'replace')
+ if not isinstance(value, str):
+ value = value.encode(charset, 'replace')
+
+ if value.endswith(";"):
+ # bastards
+ value = value[:-1]
+
+ # filter original dict by negate-condition
+ if cond(key):
+ _headers[key] = value
+ return _headers
class IMAPMessageCollection(object):