From 1cf5e68c25c0505194f23d4018e29767d3b519dd Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sat, 27 Feb 2021 17:14:38 -0700 Subject: fetch inboxes --- ctec/__init__.py | 17 +++++++++++++++++ ctec/__main__.py | 20 ++++++++++++++++++++ ctec/config.py | 18 ++++++++++++++++++ ctec/logic.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 ctec/config.py create mode 100644 ctec/logic.py (limited to 'ctec') diff --git a/ctec/__init__.py b/ctec/__init__.py index 9f109cb..4b91645 100644 --- a/ctec/__init__.py +++ b/ctec/__init__.py @@ -1 +1,18 @@ +import importlib +import subprocess +import sys + VERSION = (1,0,0) + +def import_or_install(name, pypi_name=None): + if pypi_name is None: + pypi_name = name + try: + return importlib.import_module(name) + except ImportError: + try: + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', pypi_name]) + except subprocess.CalledProcessError: + subprocess.check_call([sys.executable, '-m', 'ensurepip']) + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', pypi_name]) + return importlib.import_module(name) diff --git a/ctec/__main__.py b/ctec/__main__.py index eff6138..8d01960 100644 --- a/ctec/__main__.py +++ b/ctec/__main__.py @@ -1,8 +1,11 @@ +import threading from tkinter import * from tkinter import messagebox from tkinter import ttk from . import VERSION +from .config import get_config +from .logic import Account class CtecFrame: def __init__(self, root: Tk): @@ -14,6 +17,23 @@ class CtecFrame: root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) + config = get_config() + self.accounts = [Account(address=section, info=config[section]) for section in config.sections() if '@' in section] + self.accounts_tree = ttk.Treeview(mainframe, columns=('unread', 'all')) + self.accounts_tree.column('unread', width=50, anchor=E) + self.accounts_tree.heading('unread', text='Unread') + self.accounts_tree.column('all', width=50, anchor=E) + self.accounts_tree.heading('all', text='All') + self.accounts_tree.grid(column=0, row=0, sticky=(N, W, E, S)) + self.accounts_tree.insert('', 'end', 'all', text='All Accounts') + for account in self.accounts: + unread_count = sum(1 for message in account.inbox() if 'S' not in message.get_flags()) + all_count = sum(1 for message in account.inbox()) + self.accounts_tree.insert('', 'end', account.address, text=account.address, values=(unread_count, all_count)) + threading.Thread(target=lambda: account.fetch_inbox()).start() + + # self.messages = + # create a menu bar self.make_menu_bar(root) diff --git a/ctec/config.py b/ctec/config.py new file mode 100644 index 0000000..471a5c2 --- /dev/null +++ b/ctec/config.py @@ -0,0 +1,18 @@ +import configparser +import pathlib + +from . import import_or_install + +def get_config(): + appdirs = import_or_install('appdirs') + config_dir = pathlib.Path(appdirs.user_config_dir(appname='ctec', appauthor=False)) + config_file = config_dir / 'ctec.ini' + print(config_file) + config = configparser.ConfigParser() + config.read(config_file) + if len(config.sections()) == 0: + config['global'] = {'awesomeness': '69'} + config_dir.mkdir(parents=True, exist_ok=True) + with open(config_file, 'w') as config_file: + config.write(config_file) + return config diff --git a/ctec/logic.py b/ctec/logic.py new file mode 100644 index 0000000..7afd78a --- /dev/null +++ b/ctec/logic.py @@ -0,0 +1,49 @@ +import imaplib +import mailbox +import pathlib +import pprint +import re + +from . import import_or_install + +mailbox.Maildir.colon = '!' + +FLAGS = re.compile(rb'FLAGS \(([^)]+?)\)') + +class Account: + def __init__(self, address: str, info: dict): + appdirs = import_or_install('appdirs') + data_dir = pathlib.Path(appdirs.user_data_dir(appname='ctec', appauthor=False)) + self.address = address + self.mailbox = mailbox.Maildir(data_dir / address) + self.info = info + + def fetch_inbox(self): + with imaplib.IMAP4_SSL(self.info['imap host']) as M: + M.login(self.address, self.info['password']) + try: + inbox = self.mailbox.get_folder('Inbox') + except mailbox.NoSuchMailboxError: + inbox = self.mailbox.add_folder('Inbox') + M.select() + typ, data = M.search(None, 'ALL') + for num in data[0].split(): + typ, data = M.fetch(num, '(FLAGS RFC822)') + for prefix, message in data[:-1]: + flags = FLAGS.search(prefix).group(1).split() + print(flags) + message = mailbox.MaildirMessage(message) + if rb'\Seen' in flags: + message.add_flag('S') + message.set_subdir('cur') + if 'Message-ID' in message: + message_id = message['Message-ID'].strip() + else: + print(message) + raise KeyError('No message ID header') + if not any(x['Message-ID'].strip() == message_id for x in inbox): + inbox.add(message) + M.close() + + def inbox(self) -> mailbox.Maildir: + return self.mailbox.add_folder('Inbox') -- cgit v1.2.3