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
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 some of the attr from the parts map to header doc for key in parts_map: if key in ('body', 'multi', 'part_map'): hdoc[key] = parts_map[key] return stringify_parts_map(hdoc)
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: logger.debug("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(logger.error) return d