Example #1
0
    def _populate_headr(self, msg, chash, subject, date):
        """
        Return a headers doc.

        XXX Missing DOC -----------
        """
        headers = defaultdict(list)
        for k, v in msg.items():
            headers[k].append(v)

        # "fix" for repeated headers.
        for k, v in headers.items():
            newline = "\n%s: " % (k,)
            headers[k] = newline.join(v)

        lower_headers = lowerdict(headers)
        msgid = first(MSGID_RE.findall(
            lower_headers.get('message-id', '')))

        hd = self._get_empty_doc(self.HEADERS_DOC)
        hd[self.CONTENT_HASH_KEY] = chash
        hd[self.HEADERS_KEY] = headers
        hd[self.MSGID_KEY] = msgid

        if not subject and self.SUBJECT_FIELD in headers:
            hd[self.SUBJECT_KEY] = 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]
        else:
            hd[self.DATE_KEY] = date
        return hd
Example #2
0
 def unblock_pending_insert(result):
     if pending_inserts_dict:
         ci_headers = lowerdict(self.hdoc.headers)
         msgid = ci_headers.get('message-id', None)
         try:
             d = pending_inserts_dict[msgid]
             d.callback(msgid)
         except KeyError:
             pass
     return result
Example #3
0
 def unblock_pending_insert(result):
     if pending_inserts_dict:
         ci_headers = lowerdict(self.hdoc.headers)
         msgid = ci_headers.get('message-id', None)
         try:
             d = pending_inserts_dict[msgid]
             d.callback(msgid)
         except KeyError:
             pass
     return result
Example #4
0
def _build_headers_doc(msg, chash, body_phash, parts_map):
    """
    Assemble a headers document from the original parsed message, the
    content-hash, and the parts map.

    It takes into account possibly repeated headers.
    """
    headers = defaultdict(list)
    for k, v in msg.items():
        headers[k].append(v)
    # "fix" for repeated headers (as in "Received:"
    for k, v in headers.items():
        newline = "\n%s: " % (k.lower(),)
        headers[k] = newline.join(v)

    lower_headers = lowerdict(dict(headers))
    msgid = first(_MSGID_RE.findall(
        lower_headers.get('message-id', '')))

    _hdoc = HeaderDocWrapper(
        chash=chash, headers=headers, body=body_phash,
        msgid=msgid)

    def copy_attr(headers, key, doc):
        if key in headers:
            setattr(doc, key, headers[key])

    copy_attr(lower_headers, "subject", _hdoc)
    copy_attr(lower_headers, "date", _hdoc)

    hdoc = _hdoc.serialize()
    # add parts map to header doc
    # (body, multi, part_map)
    for key in parts_map:
        hdoc[key] = parts_map[key]
    return stringify_parts_map(hdoc)
Example #5
0
def _build_headers_doc(msg, chash, body_phash, parts_map):
    """
    Assemble a headers document from the original parsed message, the
    content-hash, and the parts map.

    It takes into account possibly repeated headers.
    """
    headers = defaultdict(list)
    for k, v in msg.items():
        headers[k].append(v)
    # "fix" for repeated headers (as in "Received:"
    for k, v in headers.items():
        newline = "\n%s: " % (k.lower(), )
        headers[k] = newline.join(v)

    lower_headers = lowerdict(dict(headers))
    msgid = first(_MSGID_RE.findall(lower_headers.get('message-id', '')))

    _hdoc = HeaderDocWrapper(chash=chash,
                             headers=headers,
                             body=body_phash,
                             msgid=msgid)

    def copy_attr(headers, key, doc):
        if key in headers:
            setattr(doc, key, headers[key])

    copy_attr(lower_headers, "subject", _hdoc)
    copy_attr(lower_headers, "date", _hdoc)

    hdoc = _hdoc.serialize()
    # add parts map to header doc
    # (body, multi, part_map)
    for key in parts_map:
        hdoc[key] = parts_map[key]
    return stringify_parts_map(hdoc)
Example #6
0
    def add_msg(self, raw_msg, flags=tuple(), tags=tuple(), date="",
                notify_just_mdoc=False):
        """
        Add a message to this collection.

        :param raw_msg: the raw message
        :param flags: tuple of flags for this message
        :param tags: tuple of tags for this message
        :param date:
            formatted date, it will be used to retrieve the internal
            date for this message.  According to the spec, this is NOT the date
            and time in the RFC-822 header, but rather a date and time that
            reflects when the message was received.
        :type date: str
        :param notify_just_mdoc:
            boolean passed to the wrapper.create method, to indicate whether
            we're insterested in being notified right after the mdoc has been
            written (as it's the first doc to be written, and quite small, this
            is faster, though potentially unsafe), or on the contrary we want
            to wait untill all the parts have been written.
            Used by the imap mailbox implementation to get faster responses.
            This will be ignored (and set to False) if a heuristic for a Draft
            message is met, which currently is a specific mozilla header.
        :type notify_just_mdoc: bool

        :returns: a deferred that will fire with the UID of the inserted
                  message.
        :rtype: deferred
        """
        # TODO watch out if the use of this method in IMAP COPY/APPEND is
        # passing the right date.
        # XXX mdoc ref is a leaky abstraction here. generalize.
        leap_assert_type(flags, tuple)
        leap_assert_type(date, str)

        msg = self.adaptor.get_msg_from_string(Message, raw_msg)
        wrapper = msg.get_wrapper()

        headers = lowerdict(msg.get_headers())
        moz_draft_hdr = "X-Mozilla-Draft-Info"
        if moz_draft_hdr.lower() in headers:
            log.msg("Setting fast notify to False, Draft detected")
            notify_just_mdoc = False

        if notify_just_mdoc:
            msgid = headers.get('message-id')
            if msgid:
                self._pending_inserts[msgid] = defer.Deferred()

        if not self.is_mailbox_collection():
            raise NotImplementedError()

        else:
            mbox_id = self.mbox_uuid
            wrapper.set_mbox_uuid(mbox_id)
            wrapper.set_flags(flags)
            wrapper.set_tags(tags)
            wrapper.set_date(date)

        def insert_mdoc_id(_, wrapper):
            doc_id = wrapper.mdoc.doc_id
            if not doc_id:
                # --- BUG -----------------------------------------
                # XXX watch out, sometimes mdoc doesn't have doc_id
                # but it has future_id. Should be solved already.
                logger.error("BUG: (please report) Null doc_id for "
                             "document %s" %
                             (wrapper.mdoc.serialize(),))
                return defer.succeed("mdoc_id not inserted")
                # XXX BUG -----------------------------------------

            # XXX BUG sometimes the table is not yet created,
            # so workaround is to make sure we always check for it before
            # inserting the doc. I should debug into the real cause.
            d = self.mbox_indexer.create_table(self.mbox_uuid)
            d.addBoth(lambda _: self.mbox_indexer.insert_doc(
                self.mbox_uuid, doc_id))
            return d

        d = wrapper.create(
            self.store,
            notify_just_mdoc=notify_just_mdoc,
            pending_inserts_dict=self._pending_inserts)
        d.addCallback(insert_mdoc_id, wrapper)
        d.addCallback(self.cb_signal_unread_to_ui)
        d.addCallback(self.notify_new_to_listeners)
        d.addErrback(lambda failure: log.err(failure))

        return d
Example #7
0
    def add_msg(self, raw_msg, flags=tuple(), tags=tuple(), date="",
                notify_just_mdoc=False):
        """
        Add a message to this collection.

        :param raw_msg: the raw message
        :param flags: tuple of flags for this message
        :param tags: tuple of tags for this message
        :param date:
            formatted date, it will be used to retrieve the internal
            date for this message.  According to the spec, this is NOT the date
            and time in the RFC-822 header, but rather a date and time that
            reflects when the message was received.
        :type date: str
        :param notify_just_mdoc:
            boolean passed to the wrapper.create method, to indicate whether
            we're insterested in being notified right after the mdoc has been
            written (as it's the first doc to be written, and quite small, this
            is faster, though potentially unsafe), or on the contrary we want
            to wait untill all the parts have been written.
            Used by the imap mailbox implementation to get faster responses.
            This will be ignored (and set to False) if a heuristic for a Draft
            message is met, which currently is a specific mozilla header.
        :type notify_just_mdoc: bool

        :returns: a deferred that will fire with the UID of the inserted
                  message.
        :rtype: deferred
        """
        # TODO watch out if the use of this method in IMAP COPY/APPEND is
        # passing the right date.
        # XXX mdoc ref is a leaky abstraction here. generalize.
        leap_assert_type(flags, tuple)
        leap_assert_type(date, str)

        msg = self.adaptor.get_msg_from_string(Message, raw_msg)
        wrapper = msg.get_wrapper()

        headers = lowerdict(msg.get_headers())
        moz_draft_hdr = "X-Mozilla-Draft-Info"
        if moz_draft_hdr.lower() in headers:
            log.msg("Setting fast notify to False, Draft detected")
            notify_just_mdoc = False

        if notify_just_mdoc:
            msgid = headers['message-id']
            self._pending_inserts[msgid] = defer.Deferred()

        if not self.is_mailbox_collection():
            raise NotImplementedError()

        else:
            mbox_id = self.mbox_uuid
            wrapper.set_mbox_uuid(mbox_id)
            wrapper.set_flags(flags)
            wrapper.set_tags(tags)
            wrapper.set_date(date)

        def insert_mdoc_id(_, wrapper):
            doc_id = wrapper.mdoc.doc_id
            if not doc_id:
                # --- BUG -----------------------------------------
                # XXX watch out, sometimes mdoc doesn't have doc_id
                # but it has future_id. Should be solved already.
                logger.error("BUG: (please report) Null doc_id for "
                             "document %s" %
                             (wrapper.mdoc.serialize(),))
                return defer.succeed("mdoc_id not inserted")
                # XXX BUG -----------------------------------------

            # XXX BUG sometimes the table is not yet created,
            # so workaround is to make sure we always check for it before
            # inserting the doc. I should debug into the real cause.
            d = self.mbox_indexer.create_table(self.mbox_uuid)
            d.addBoth(lambda _: self.mbox_indexer.insert_doc(
                self.mbox_uuid, doc_id))
            return d

        d = wrapper.create(
            self.store,
            notify_just_mdoc=notify_just_mdoc,
            pending_inserts_dict=self._pending_inserts)
        d.addCallback(insert_mdoc_id, wrapper)
        d.addCallback(self.cb_signal_unread_to_ui)
        d.addCallback(self.notify_new_to_listeners)
        d.addErrback(lambda failure: log.err(failure))

        return d