changeset 6:470bfed5411e

First commit where it actually does what it is supposed to.
author Brian Neal <bgneal@gmail.com>
date Sat, 19 May 2012 16:43:45 -0500
parents 2c88867c4875
children 1315e39fe059
files weighmail/core.py weighmail/main.py weighmail/observers/__init__.py weighmail/observers/console.py
diffstat 4 files changed, 139 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /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))
--- 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')
--- /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
--- /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."