# HG changeset patch # User Brian Neal # Date 1337463825 18000 # Node ID 470bfed5411e16b7671c0eafae2f24535190e61d # Parent 2c88867c48756b78c1046375812237d23ed8132f First commit where it actually does what it is supposed to. diff -r 2c88867c4875 -r 470bfed5411e weighmail/core.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/weighmail/core.py Sat May 19 16:43:45 2012 -0500 @@ -0,0 +1,48 @@ + + +def weighmail(imap, folder, labels, observer=None): + """Applies labels to message that meet size criteria. + + imap - IMAPClient + folder - folder name to operate on + labels - list of Label tuples + observer - will call back to report progress + + """ + imap.select_folder(folder) + + for label in labels: + apply_label(imap, label, observer) + + if observer is not None: + observer.done() + + +def get_criteria(label): + """Returns the RFC 3501 criteria string for the given label""" + + l = 'LARGER %d' % label.min if label.min is not None else '' + s = 'SMALLER %d' % label.max if label.max is not None else '' + + return '{larger} {smaller}'.format(larger=l, smaller=s).strip() + + +def apply_label(imap, label, observer=None): + """Searches for messages that meet the label's criteria and applies the + label to them. + + """ + criteria = get_criteria(label) + + if observer is not None: + observer.searching(label.name) + + msgs = imap.search(criteria) + + if observer is not None: + observer.labeling(label.name, len(msgs)) + + imap.add_gmail_labels(msgs, [label.name]) + + if observer is not None: + observer.done_labeling(label.name, len(msgs)) diff -r 2c88867c4875 -r 470bfed5411e weighmail/main.py --- a/weighmail/main.py Sat May 19 13:57:38 2012 -0500 +++ b/weighmail/main.py Sat May 19 16:43:45 2012 -0500 @@ -2,8 +2,12 @@ import getpass import sys +import imapclient + import config from utils import make_label, AppError +from observers.console import ConsoleObserver +from core import weighmail PROG_DESC = "Adds labels to your Gmail according to message size" @@ -65,6 +69,18 @@ return args +def create_imap_client(host, port, ssl, user, password): + """Creates & returns an instance of an IMAPClient""" + + print "Connecting..." + + client = imapclient.IMAPClient(host=host, port=port, ssl=ssl) + client.login(username=user, password=password) + + print "Connected." + return client + + def main(): # Parse command-line arguments args = parse_args() @@ -89,14 +105,26 @@ if opt not in opts or opts[opt] is None: opts[opt] = getpass.getpass(opt + ': ') - print opts - if 'labels' not in opts or not opts['labels']: raise AppError("Please specify some label definitions") + imap_args = opts.copy() + del imap_args['folder'] + del imap_args['labels'] + + client = create_imap_client(**imap_args) + observer = ConsoleObserver() + + weighmail(client, opts['folder'], opts['labels'], observer) + client.logout() + if __name__ == '__main__': try: main() except (IOError, AppError), ex: sys.stderr.write("%s\n" % ex) + except imapclient.IMAPClient.Error, ex: + sys.stderr.write("IMAP Error: %s\n" % ex) + except KeyboardInterrupt: + sys.stderr.write('Interrupted\n') diff -r 2c88867c4875 -r 470bfed5411e weighmail/observers/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/weighmail/observers/__init__.py Sat May 19 16:43:45 2012 -0500 @@ -0,0 +1,32 @@ +"""Base observer class for weighmail operations. + +""" + +class BaseObserver(object): + """Base observer class; does nothing.""" + + def searching(self, label): + """Called when the search process has started for a label""" + pass + + def labeling(self, label, count): + """Called when the labelling process has started for a given label + + label - the label we are working on + count - number of messages to label + + """ + pass + + def done_labeling(self, label, count): + """Called when finished labelling for a given label + + label - the label we were working on + count - number of messages that were labelled + + """ + pass + + def done(self): + """Called when completely finished""" + pass diff -r 2c88867c4875 -r 470bfed5411e weighmail/observers/console.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/weighmail/observers/console.py Sat May 19 16:43:45 2012 -0500 @@ -0,0 +1,29 @@ +import datetime + +from observers import BaseObserver + +class ConsoleObserver(BaseObserver): + """Console observer class; outputs status to the console.""" + + def __init__(self, *args, **kwargs): + super(BaseObserver, self).__init__(*args, **kwargs) + self.first_callback = True + self.total_messages = 0 + + def searching(self, label): + if self.first_callback: + self.first_callback = False + self.start_time = datetime.datetime.now() + + print "Searching for %s messages..." % label + + def labeling(self, label, count): + print "Applying the label %s to %d messages..." % (label, count) + + def done_labeling(self, label, count): + self.total_messages += count + + def done(self): + duration = datetime.datetime.now() - self.start_time + print "Labeled %d messages in %s" % (self.total_messages, duration) + print "Done."