def _mark_read(self): self.unread_timer = None with open_db_rw() as db: msg = db.find_message(self.message_id) msg.remove_tag('unread', True) self.message_filename = msg.get_filename() WATCHER.tagMailRemoved.emit('unread', self.message_id)
def dropMimeData(self, mime, action, row, column, parent_qidx): data = bytes(mime.data('text/x-lierre-threads')).decode('ascii') if not data: return False try: ids = json.loads(data) except ValueError: logging.warning('failed to decode dropped data') return False if row == column == -1: qidx = parent_qidx.siblingAtColumn(0) else: qidx = parent_qidx.child(row, 0) tag = qidx.data() with open_db_rw() as db: for id in ids: thread = get_thread_by_id(db, id) for message in iter_thread_messages(thread): message.add_tag(tag) return True
def _archiveThreads(self): with open_db_rw() as db: for thread in self._iter_selected_threads(db): for msg in iter_thread_messages(thread): LOGGER.debug('archiving message %r', msg.get_message_id()) msg.remove_tag('inbox') WATCHER.tagMailRemoved.emit('inbox', msg.get_message_id())
def _deleteSelectedMessages(self): msg_ids = self._getSelectedMessages() with open_db_rw() as db: for msg_id in msg_ids: msg = db.find_message(msg_id) msg.add_tag('deleted') WATCHER.tagMailAdded.emit('deleted', msg_id)
def _deleteSelectedThreads(self): with open_db_rw() as db: for thread in self._iter_selected_threads(db): for msg in iter_thread_messages(thread): LOGGER.debug('marking message deleted %r', msg.get_message_id()) msg.add_tag('deleted') WATCHER.tagMailAdded.emit('deleted', msg.get_message_id())
def _toggleTag(self, tag): msg_ids = self._getSelectedMessages() with open_db_rw() as db: for msg_id in msg_ids: msg = db.find_message(msg_id) if tag in msg.get_tags(): msg.remove_tag(tag) WATCHER.tagMailRemoved.emit(tag, msg_id) else: msg.add_tag(tag) WATCHER.tagMailAdded.emit(tag, msg_id)
def tagMailRemoved(self, tag, msg_id): if tag != TAG_DELETED: return processor = self.build_processor() with open_db_rw() as db: for msg_path in db.find_message(msg_id).get_filenames(): msg_path = Path(msg_path) LOGGER.info('undeleting message %r with path %r', msg_id, msg_path) if not self.config['dry_run']: processor.undelete_message(db, msg_path)
def openTagEditor(self): with open_db() as db: union_tags = set() common_tags = None for thread in self._iter_selected_threads(db): for msg in iter_thread_messages(thread): msg_tags = set(msg.get_tags()) union_tags |= msg_tags if common_tags is None: common_tags = msg_tags else: common_tags &= msg_tags union_tags -= common_tags w = TagEditor(parent=self) w.setCheckedTags(common_tags, union_tags) if not w.exec_(): return checked, partially = w.checkedTags() with open_db_rw() as db: for thread in self._iter_selected_threads(db): for msg in iter_thread_messages(thread): msg_tags = set(msg.get_tags()) to_remove = msg_tags - (checked | partially ) # unchecked tags to_add = checked - msg_tags # newly checked tags LOGGER.debug('changing tags for message %r: +(%s) -(%s)', msg.get_message_id(), to_add, to_remove) msg.freeze() for tag in to_remove: msg.remove_tag(tag) for tag in to_add: msg.add_tag(tag) msg.thaw() msg.tags_to_maildir_flags() LOGGER.debug('changed tags for message %r', msg.get_message_id()) for tag in to_remove: WATCHER.tagMailRemoved.emit(tag, msg.get_message_id()) for tag in to_add: WATCHER.tagMailAdded.emit(tag, msg.get_message_id())
def _send(self): idt = self._prepareMessage() if not idt: return send_email(idt, self.msg) self.sent.emit() with open_db_rw() as db: if self.msg.get('In-reply-to', ''): replied_to = db.find_message(self.msg['In-reply-to']) if replied_to: replied_to.add_tag('replied', True) WATCHER.tagMailAdded.emit('replied', self.reply_to)
def _setMessagesTag(self): action = self.sender() add = action.isChecked() tag = action.data() msg_ids = self._getSelectedMessages() with open_db_rw() as db: for msg_id in msg_ids: msg = db.find_message(msg_id) if add: msg.add_tag(tag) WATCHER.tagMailAdded.emit(tag, msg_id) else: msg.remove_tag(tag) WATCHER.tagMailRemoved.emit(tag, msg_id)
def _saveDraft(self): idt = self._prepareMessage() if not idt: return box = MaildirPP() with open_db_rw() as db: msg_path = box.add_message(self.msg, box.get_root()) nmsg = db.add_message(str(msg_path)) nmsg.add_tag('draft', True) old_draft, self.draft_id = self.draft_id, nmsg.get_message_id() if old_draft: old_msg = db.find_message(old_draft) old_file = old_msg.get_filename() Path(old_file).unlink() db.remove_message(old_file)
def run(self): with open_db_rw() as db: for msg in self.processor.find_messages_to_delete(db): for msg_path in msg.get_filenames(): msg_path = Path(msg_path) LOGGER.info('deleting message %r with path %r', msg.get_message_id(), msg_path) if not self.dry_run: self.processor.delete_message(db, msg_path) for msg in self.processor.find_messages_to_undelete(db): for msg_path in msg.get_filenames(): msg_path = Path(msg_path) LOGGER.info('undeleting message %r with path %r', msg.get_message_id(), msg_path) if not self.dry_run: self.processor.undelete_message(db, msg_path)
def openTagEditor(self): selected = self._getSelectedMessages() assert selected w = TagEditor(parent=self) with open_db() as db: msgs = [db.find_message(msg_id) for msg_id in selected] common_tags = reduce(set.__and__, (set(msg.get_tags()) for msg in msgs), set(msgs[0].get_tags())) union_tags = reduce(set.__or__, (set(msg.get_tags()) for msg in msgs), set()) union_tags -= common_tags w.setCheckedTags(common_tags, union_tags) if not w.exec_(): return checked, partially = w.checkedTags() with open_db_rw() as db: msgs = [db.find_message(sel) for sel in selected] for msg in msgs: msg_tags = set(msg.get_tags()) to_remove = msg_tags - (checked | partially) # unchecked tags to_add = checked - msg_tags # newly checked tags msg.freeze() for tag in to_remove: msg.remove_tag(tag) for tag in to_add: msg.add_tag(tag) msg.thaw() msg.tags_to_maildir_flags() for tag in to_remove: WATCHER.tagMailRemoved.emit(tag, msg.get_message_id()) for tag in to_add: WATCHER.tagMailAdded.emit(tag, msg.get_message_id())
def start(self): now = time() mailroot = get_db_path() box = mailbox.Maildir(mailroot) # TODO: folder:"" and thread:{not folder:""}? with open_db_rw() as db: for msgname in box.iterkeys(): msg_path = Path(mailroot).joinpath(box._lookup(msgname)) if now - msg_path.stat().st_mtime >= THRESHOLD: continue if 'deleted' in set( db.find_message_by_filename(str(msg_path)).get_tags()): continue try_place_in_folder(db, msg_path) self.finished.emit(0)
def send_email(identity, msg): assert isinstance(msg, EmailMessage) # prepare to add to mailbox box = MaildirPP() folder = box.get_root() # really send plugin = PLUGINS['senders'][identity.sender_plugin] plugin.send(msg) # save in folder msg_path = box.add_message(msg, folder) # TODO: add in cur? LOGGER.info('sent message saved to %r', msg_path) with open_db_rw() as db: nmsg, status = db.add_message(str(msg_path)) nmsg.add_tag('sent', sync_maildir_flags=True) WATCHER.mailAdded.emit(msg['Message-ID'][1:-1])