#!/usr/bin/env python3 """ Meh mail client """ import notmuch import logging import coloredlogs import colorama import datetime import os import progressbar import time colorama.init() coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s') log = logging.getLogger() log.debug("Loading database") db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) # TODO Open read-only when needed log.debug("Database loaded") def get_location(msg): path = msg.get_filename() path = os.path.dirname(path) base = db.get_path() assert path.startswith(base) path = path[len(base):] _, mailbox, folder, state = path.split('/') assert state in {'cur', 'tmp', 'new'} return (mailbox, folder, state) MAILBOX_COLORS = dict() def get_mailbox_color(mailbox): if mailbox not in MAILBOX_COLORS: colorfile = os.path.join(db.get_path(), mailbox, 'color') assert os.path.isfile(colorfile) with open(colorfile, 'r') as f: colorStr = f.read() colorStr = colorStr[1:] if colorStr[0] == '#' else colorStr R = int(colorStr[0:2], 16) G = int(colorStr[2:4], 16) B = int(colorStr[4:6], 16) MAILBOX_COLORS[mailbox] = '\x1b[38;2;{};{};{}m'.format(R, G, B) return MAILBOX_COLORS[mailbox] def format_date(date): now = datetime.datetime.now() midnight = datetime.datetime(year=now.year, month=now.month, day=now.day) if date > midnight: return date.strftime('%H:%M:%S') else: return date.strftime('%d/%m/%y') def print_msg(msg): line = "" tags = set(msg.get_tags()) mailbox, folder, state = get_location(msg) line += get_mailbox_color(mailbox) # Date date = datetime.datetime.fromtimestamp(msg.get_date()) line += format_date(date) # Icons line += " " def tags2col1(tag1, tag2, both, first, second, none): nonlocal line if tag1 in tags: if tag2 in tags: line += both else: line += first else: if tag2 in tags: line += second else: line += none tags2col1('spam', 'draft', '??', '💥', '📝', ' ') tags2col1('attachment', 'encrypted', '🔐', '📎', '🔑', ' ') tags2col1('unread', 'flagged', '🏁', '🏳 ', '🏴', ' ') tags2col1('sent', 'replied', '?', '↑', '↪', ' ') # TODO To: / From: # Subject line += " " line += msg.get_header("subject") line += colorama.Style.RESET_ALL print(line) def retag_msg(msg): msg.freeze() mailbox, folder, state = get_location(msg) # Search-friendly folder name if folder.startswith('INBOX.'): folder = folder[6:] folder = folder.upper() msg.remove_all_tags() if folder.startswith('JUNK') or folder.startswith('SPAM'): msg.add_tag('spam') if folder.startswith('DRAFT'): msg.add_tag('draft') if folder.startswith('INBOX'): msg.add_tag('inbox') # TODO 'sent' tag # Save msg.thaw() msg.tags_to_maildir_flags() def applyMsgs(queryStr, function, useProgressbar=False): query = notmuch.Query(db, queryStr) query.set_sort(notmuch.Query.SORT.OLDEST_FIRST) msgs = query.search_messages() if useProgressbar: nbMsgs = query.count_messages() iterator = progressbar.progressbar(msgs, max_value=nbMsgs) else: iterator = msgs for msg in iterator: function(msg) applyMsgs('tag:inbox', print_msg) # applyMsgs('tag:spam', print_msg) # applyMsgs('tag:unread', print_msg) # applyMsgs('from:geoffrey@frogeye.fr', print_msg) # applyMsgs('*', retag_msg, useProgressbar=True)