#!/usr/bin/python ## biff-notify : v0.1 ## http://devsec.org/software/misc/biff-notify ## about: ## - monitor a list of Maildirs for new messages, and tell ## the Gnome notification-daemon to pop up a message when ## a new message arrives ## ## example usage: ## biff-notify ~/.Maildir/ ## ## changelog: ## - 2009-03-12 : v0.1 : initial release ## ## - Thor Kooda ## 2009-03-12 import os import re import sys import time from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent from rfc822 import Message import pynotify def bail( str, err = 1 ): print >>sys.stderr, str sys.exit( err ) class PTmp( ProcessEvent ): def process_IN_MOVED_TO( self, event ): global count global icons_from global icons_subject if event.is_dir != False: return ## open .. path_msg = os.path.join( event.path, event.name ) try: fp = open( path_msg, "r" ) except: print >>sys.stderr, "error: could not open: '%s'" % path_msg return ## parse .. m = Message(fp) str_date = time.strftime( "%I:%M %p", m.getdate( "Date" ) ) str_from_name, str_from_address = m.getaddr( "From" ) if str_from_name == "": str_from_name = str_from_address str_to_names = "" list = m.getaddrlist( "To" ) for realname, mailaddr in list: if str_to_names != "": str_to_names += ", " if realname != "": str_to_names += realname else: str_to_names += mailaddr str_subject = m.getheader( "Subject" ) or "" fp.close() ## print .. str_dir = "[ %s ]" % os.path.basename( os.path.dirname( event.path ) ) if len(sys.argv) > 2: print str_dir print "From:", str_from_name print "To:", str_to_names print "Subject:", str_subject print count += 1 title = "%s @ %s (#%d)" % ( str_from_name, str_date, count ) body = "" if len(sys.argv) > 2: body += "%s\n" % str_dir body += "To: %s\nSubject: %s" % ( str_to_names, str_subject ) icon = "mail-message-new" ## possibly change icon .. for r in icons_subject: if re.match( r, str_subject, re.I ): icon = icons_subject[ r ] for r in icons_from: if re.match( r, str_from_address, re.I ): icon = icons_from[ r ] ## notify .. pynotify.init( "biff-notify" ) n = pynotify.Notification( title, body, icon ) n.set_urgency( pynotify.URGENCY_NORMAL ) n.set_timeout( pynotify.EXPIRES_NEVER ) n.show() icons_subject = { "^fwd:": "mail-forward", "^re:": "mail-reply-sender", ".*other subject": "edit-paste", } icons_from = { "root@example\.com": "media-record", "postmaster@example\.com": "dialog-warning", ".*@.*\.net": "dialog-warning", "jdoe@": "document-new", } # other possibly decent icons: # "mail-forward" # "mail-mark-not-junk" # "mail-message-new" # "mail-reply-all" # "mail-reply-sender" # "mail-send-receive" # "contact-new" # "bookmark-new" # "document-new" # "edit-copy" count = 0 watches = [] if __name__ == '__main__': if len(sys.argv) < 2: bail( "usage: %s [maildir|mbox ...]" % sys.argv[0], 2 ) ## init .. wm = WatchManager() notifier = Notifier( wm, PTmp() ) for arg in sys.argv[1:]: new = os.path.join( arg, "new" ) if not os.path.isdir( new ): continue wdd = wm.add_watch( new, EventsCodes.IN_MOVED_TO, rec=True ) print >>sys.stderr, "watching: %s" % arg ## loop .. while True: try: notifier.process_events() if notifier.check_events(): notifier.read_events() except KeyboardInterrupt: notifier.stop() break