aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-02-27 17:14:38 -0700
committerMelody Horn <melody@boringcactus.com>2021-02-27 17:14:38 -0700
commit1cf5e68c25c0505194f23d4018e29767d3b519dd (patch)
tree63ec483c12e57ccbdea5e94ab82448cbff7b8753
parentbcb2b78eed508834192557e93f158f171f51f02d (diff)
downloadctec-1cf5e68c25c0505194f23d4018e29767d3b519dd.tar.gz
ctec-1cf5e68c25c0505194f23d4018e29767d3b519dd.zip
fetch inboxes
-rw-r--r--ctec/__init__.py17
-rw-r--r--ctec/__main__.py20
-rw-r--r--ctec/config.py18
-rw-r--r--ctec/logic.py49
4 files changed, 104 insertions, 0 deletions
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')