def get_uids_in_db(self): """ Returns the UIDs of messages in this mailbox & stored in the DB """ uids = set() threads = Thread.objects(mailboxes=self.id) for t in threads: for m in t.messages: if self.id in m.mailboxes: uids.add(m.get_uid(self.id)) return uids
def handle_new_messages(self, messages): account_mailboxes = self.imap.directories.values_list("id", flat=True) for message in messages: if message.message_id is None and message.in_reply_to is None: message.assign_new_thread() continue qs = [] if message.message_id is not None: qs.append({"messages__in_reply_to": message.message_id}) if message.in_reply_to is not None: qs.append({"messages__message_id": message.in_reply_to}) qs.append({"messages__in_reply_to": message.in_reply_to}) threads = set() for query in qs: for t in Thread.objects(mailboxes__in=account_mailboxes).filter(**query): threads.add(t) if not threads: subject = clean_subject(message.subject) if subject != message.subject: # This is a Re: RE or whatever without any In-Reply-To. # Trying to guess which thread it's in. thrds = Thread.objects(mailboxes__in=account_mailboxes) thrds = thrds.filter(messages__subject=subject) for t in thrds.order_by("-date"): threads.add(t) break if not threads: message.assign_new_thread() continue current_thread = threads.pop() if len(threads) > 0: # Merge threads for thread in threads: current_thread.merge_with(thread, self.id) current_thread.add_message(message, self.id)
def update_messages(self, connection=None): if connection is None: m = self.imap.get_connection() else: m = connection db_uids = self.get_uids_in_db() imap_uids = set(self.get_uids(connection=m)) remove_from_db = list(db_uids - imap_uids) remove_from_db = [[self.id, uid] for uid in remove_from_db] threads_remove = Thread.objects(mailboxes=self.id, messages__uids__in=remove_from_db) for t in threads_remove: t.remove_message(self.id, remove_from_db) fetch_from_imap = map(str, list(imap_uids - db_uids)) messages = () if fetch_from_imap: print "Updating %s messages" % len(fetch_from_imap) while len(fetch_from_imap) > 1000: print "%s remaining" % len(fetch_from_imap) fetch_this = fetch_from_imap[:1000] fetch_from_imap = fetch_from_imap[1000:] messages = self.list_messages(force_uids=fetch_this, connection=m) self.handle_new_messages(messages) messages = self.list_messages(force_uids=fetch_from_imap, connection=m) self.handle_new_messages(messages) m.select_folder(self.name) unseen = m.search(["NOT SEEN"]) m.close_folder() if connection is None: m.logout() threads = Thread.objects(mailboxes=self.id) for t in threads: t.ensure_unread(self.id, unseen)
def unread_threads(self): if not hasattr(self, "_unread_threads"): self._unread_threads = Thread.objects(mailboxes=self.id, messages__read=False).count() return self._unread_threads