From 5798e5f8c0329bd2e603a4c8a3404a7a6dd7afd1 Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Sun, 22 Apr 2018 23:20:20 +0200 Subject: Recover listFolder.py script --- archive_folder.py | 18 ++++- imapArchive.py | 215 ------------------------------------------------------ listFolders.py | 54 -------------- playWithImap.py | 67 ----------------- 4 files changed, 16 insertions(+), 338 deletions(-) delete mode 100755 imapArchive.py delete mode 100755 listFolders.py delete mode 100755 playWithImap.py diff --git a/archive_folder.py b/archive_folder.py index 4b86707..3d52918 100755 --- a/archive_folder.py +++ b/archive_folder.py @@ -31,6 +31,7 @@ class MessageError(IOError): Capas = collections.namedtuple('Capas', ['MOVE', 'UIDPLUS']) SEP_RE = re.compile(r'\s+"([/.])"\s+') +FOLDER_RE = re.compile(r'\s+"[/.]"\s+') class Message(object): @@ -231,6 +232,14 @@ class EmailServer(object): dir = Folder(self.box, arch_dir, create=True) # dir.move_messages(msg_ids) + def list_folders(self): + ok, data = self.box.list() + if ok != 'OK': + raise IOError('Cannot list folders!') + + return sorted([FOLDER_RE.split(x.decode())[1] for x in data], + key=str.lower) + def __enter__(self): return self @@ -244,11 +253,12 @@ if __name__ == '__main__': locale.setlocale(locale.LC_ALL, 'en_US') argp = argparse.ArgumentParser() subps = argp.add_subparsers(dest='cmd') - subp_list = subps.add_parser('servers', help='List available servers (by keywords)') + subp_servers = subps.add_parser('servers', help='List available servers (by keywords)') + subp_list = subps.add_parser('list', help='List all folders') subp_arc = subps.add_parser('archive', help='Archive folder[s]') subp_arc.add_argument('-d', type=int, default=14, dest='days', help='How old messages we should keep') - subp_arc.add_argument('-s', '--server', default='localhost', + subp_arc.add_argument('-s', '--server', help='Symbolic name of the server to be used') subp_arc.add_argument('folder', help='Folder which should be archived') subp_arc.add_argument('archive', help='Root folder to store annual archives to') @@ -259,6 +269,10 @@ if __name__ == '__main__': config = EmailServer.get_config() sects = set(config.keys()) - {'DEFAULT', 'general'} print('Available servers:\n%s' % tuple(sects)) + elif args.cmd == 'list': + myStore = EmailServer() + folders = myStore.list_folders() + print('\n'.join(folders)) else: before = date.today() - timedelta(days=args.days) with EmailServer(args.server, args.archive) as myStore: diff --git a/imapArchive.py b/imapArchive.py deleted file mode 100755 index 2354342..0000000 --- a/imapArchive.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python3.6 -# note http://docs.python.org/lib/module-doctest.html -# resp. file:///usr/share/doc/python-docs-*/html/lib/module-doctest.html -# FIXME -# read https://www.toptal.com/python/an-introduction-to-mocking-in-python -# & https://blog.fugue.co/2016-02-11-python-mocking-101.html -# for unittest.mock tutorials -# for testing -# FIXME TODO FIXME DON'T DO THIS! Active Work is on archive_folder -import argparse -import configparser -import email -import logging -import os -import sys -from datetime import date - -logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', - stream=sys.stdout, level=logging.DEBUG) -log = logging.getLogger('imapArch') - -# from java.util import Properties, Date -# from java.lang import System -# from javax.mail import * -# from jarray import array - - -class FolderNotFoundError(IOError): - pass - - -def __getMessageDate(msg): - """ - Return the date of the message - - @param msg analyzed message - @return GregorianCalendar of the messages date - @throws MessagingException - """ - dateMS = msg.getReceivedDate().getTime() // 1000 - dateStruct = date.fromtimestamp(dateMS) - return dateStruct - - -class ArchivableFolder(list): - - def __init__(self, source, year): - """ - Constructor for the folder. - - @param source folder from the messages should be archived - @param year int of the year for which the messages are - archived - """ - self.sourceFolder = source - targetName = self.__getArchiveFolderName(source.getFullName(), year) - self.targetFolder = self.sourceFolder.getFolder(targetName) - - def __getArchiveFolderName(self, srcFldName, year): - """ - @param folder string with the folder name - @param year int - @return - """ - archFolder = "INBOX/Archiv/" - rootLen = len("INBOX/") - if not(srcFldName[:rootLen] == "/INBOX/"): - raise FolderNotFoundError( - "We expect all folders to be under INBOX folder.") - baseName = srcFldName[rootLen:] - archFolder = "/" + archFolder + year + "/" + baseName - return archFolder - - def add(self, msg): - self.append(msg) - - def doArchive(self): - for message in self: - log.debug("Moving %s from %s to %s.", - message, self.sourceFolder.getFullName(), - self.targetFolder.getFullName()) - # self.sourceFolder.copyMessages(array(self, Message), - # self.targetFolder) - # for message in self: - # message.setFlag(Flags.Flag.DELETED, true) - # self.sourceFolder.expunge() - - -class Archives(dict): - """Collects archivable folders indexed by tuple of - folderName and year - """ - - def __init__(self): - pass - - def add(self, msg): - """ - Check whether the ArchivableFolder (@see ArchivableFolder) - for the particular year actually exists, and if not then create - it. In any event add - @param msg - """ - fld = msg.getFolder() - msgDate = __getMessageDate(msg) - year = msgDate.year - - if not(self.search(fld, year)): - archfld = ArchivableFolder(fld, year) - self[self.__createKey(fld, year)] = archfld - - def __createKey(self, name, year): - """ - Create a key for the list - @param fldName String with the full name of the folder - @param year int of the year of the messages to be stored - there - @return tuple consisting from the both parameters of - this function. - """ - return(name, year) - - def search(self, fld, year): - """ - Find out whether the object with the key consisting of - the folder name and year exists in this object. - - @param fld Folder where the message is stored - @param year int year of the message date - @return boolean saying whether the folder for this message - has been already added to this object. - """ - key = self.__createKey(fld.getFullName(), year) - return key in self - - def archive(self): - for key in self: - self.doArchive() - - -class ArchivedStore(object): - """ - TODO Make Archive store into context manager. - """ - - def __init__(self, serverKey=None): - config = configparser.ConfigParser() - config.read(os.path.expanduser('~/.config/imap_archiver.cfg')) - acc_name = serverKey if serverKey is not None \ - else config['general']['account'] - self.cfg = dict(config.items(acc_name)) - # if debug: - # self.session.setDebug(True) - # try: - # self.store = self.session.getStore("imaps") - # except: - # print >> sys.stderr, "Cannot get Store" - # raise - - self._threeMonthAgo = date.today() - newmonth = self._threeMonthAgo.month - 3 - self._threeMonthAgo = self._threeMonthAgo.replace(month=newmonth) - - log.debug("host = %s, user = %s, password = %s", - self.cfg['host'], self.cfg['username'], - self.cfg['password']) - - self.__login(host, user, password) - - def __login(self, server, user, password): - try: - self.store.connect(server, user, password) - except: - log.debug("Cannot connect to %s as %s with password %s", - server, user, password) - raise - - def archive(self): - inboxfolder = self.store.getDefaultFolder().getFolder("INBOX") - folderList = inboxfolder.list('*') - - for folder in folderList: - if folder.getFullName()[:len("INBOX/Archiv")] != "INBOX/Archiv": - archMsgsCnt = self.__archiveFolder(folder) - # folder.close(False) - print("Processed messages = %d" % archMsgsCnt) - - def __archiveFolder(self, fld): - fld.open(Folder.READ_WRITE) - for msg in fld.getMessages(): - msgDate = __getMessageDate(msg) - print >>sys.stderr, str(msgDate), str(self._threeMonthAgo) - if msgDate < self._threeMonthAgo: - archFolder = self.__getArchiveFolderName(msg) -# print >> sys.stderr, archFolder -# fld.copyMessages(array([msg],type(msg)), archFolder) -# msg.setFlag(Flags.Flag.DELETED, true) - print("%s -> %s : %s" % (fld.getFullName(), - archFolder.getFullName(), msgDate)) - folderLen = len(fld.getMessages()) - fld.close(False) - return(folderLen) - -if __name__ == '__main__': - argp = argparse.ArgumentParser() - argp.add_argument('server', - help='Symbolic name of the server to be used') - argp.add_argument('folder', - help='Folder which should be archived') - argp.add_argument('archive', - help='Root folder to store annual archives to') - args = argp.parse_args() - - with ArchivedStore() as myStore: - myStore.archive() diff --git a/listFolders.py b/listFolders.py deleted file mode 100755 index 741ae41..0000000 --- a/listFolders.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3.6 - -import configparser -import logging -import os.path - -import imaplib - -logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', - level=logging.DEBUG) -log = logging.getLogger('listFolders') - -def list_folder(name, wildcards='*'): - ok, data = box.list(name, wildcards) - if ok != 'OK': - raise ServerError('Cannot list folder %s' % name) - return data[0] - -def get_separator(): - data = list_folder('pumpa') - - log.debug('data = %s (%s)', data, type(data)) - - if data is None: - data = list_folder('""', '""') - - data = data.decode().split(' ') - if len(data) == 3: - return data[1].strip(' "') - else: - raise ServerError('Cannot find folder separator from %s' % data) - -config = configparser.ConfigParser() -config.read(os.path.expanduser('~/.config/imap_archiver.cfg')) -acc_name = config['general']['account'] -cfg = dict(config.items(acc_name)) - -box = imaplib.IMAP4_SSL(host=cfg['host']) -ok, data = box.login(cfg['username'], cfg['password']) -if ok != 'OK': - raise IOError('Cannot login with credentials %s' % str(cfg)) - -sep = get_separator() -print('sep = %s' % sep) -# data = list_folder('""', '""') -# log.debug('data = %s', data) -# sep = data.split()[1].decode() -# -# data = list_folder('Work/punk') -# log.debug('ok = %s, data = %s (type %s)', ok, data, type(data)) - -# for fld in data: -# spl_fld = fld.decode().split(sep) -# print(spl_fld[1].strip()) diff --git a/playWithImap.py b/playWithImap.py deleted file mode 100755 index dd68fb6..0000000 --- a/playWithImap.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3.6 - -import configparser -import os.path - -import imapy - -config = configparser.ConfigParser() -config.read(os.path.expanduser('~/.config/imap_archiver.cfg')) -cfg = dict(config.items(config['general']['account'])) -print(cfg) - - -# my $msg; -# -# my $imap = Mail::IMAPClient->new(); -# $imap = Mail::IMAPClient->new( -# Server => "localhost", -# User => "matej", -# Password => "lubdkc", -# UID => 1 -# ) or die "Cannot connect to localhost as matej: $@"; -# -# $imap->select('INBOX'); -# my $hash = $imap->fetch_hash("RFC822.SIZE","INTERNALDATE","FLAGS","ENVELOPE"); -# #print Data::Dumper->Dumpxs([$hash],['$hash']); -# -# #print "\n===============================\n"; -# my @folders = $imap->folders; -# #print join("\n",@folders),".\n"; -# -# #print "\n===============================\n"; -# # or s/folders/subscribed/ -# @folders = $imap->folders("INBOX" . $imap->separator . "Pratele" . $imap->separator); -# print join("\n",@folders),".\n"; -# -# print "\n===============================\n"; -# my $msgID; -# my $headers; -# foreach $msg (keys(%$hash)) { -# $msgID = $imap->get_header($msg,"Message-Id"); -# print "\$msg ID = $msg\nMESSAGE-ID = $msgID\n"; -# $headers = $imap->parse_headers($msg,"Date","Received","Subject","To"); -# print "Headers = " . Data::Dumper->Dumpxs([$headers],['$headers']) . "\n"; -# } -# -# ## Get a list of messages in the current folder: -# #my @msgs = $imap->messages or die "Could not messages: $@\n"; -# ## Get a reference to an array of messages in the current folder: -# #my $msgs = $imap->messages or die "Could not messages: $@\n"; -# -# #use Mail::IMAPClient; -# # my $imap = Mail::IMAPClient->new( Server => $imaphost, -# # User => $login, -# # Password=> $pass, -# # Uid => 1, # optional -# # ); -# # -# # $imap->select("World Domination"); -# # # get the flags for every message in my 'World Domination' folder -# # $flaghash = $imap->flags( scalar($imap->search("ALL"))) ; -# # -# # # pump through sorted hash keys to print results: -# # for my $k (sort { $flaghash->{$a} <=> $flaghash->{$b} } keys %$flaghash) { -# # # print: Message 1: \Flag1, \Flag2, \Flag3 -# # print "Message $k:\t",join(", ",@{$flaghash->{$k}}),"\n"; -# # } -- cgit