#!/usr/bin/python # Copyright (c) 2006 Brandon Sterne # Licensed under the MIT license. # http://brandon.sternefamily.net/files/mit-license.txt import urllib, string, sys, os, smtplib, time, MySQLdb from xml.dom import minidom ####################### START USER DEFINED VARIABLES ####################### feeds = ['http://rss.cnn.com/rss/cnn_topstories.rss', 'http://digg.com/rss/containertechnology.xml'] # strings to look for in the feeds # for a pattern to match, all words in each list must be present # in the search string patterns = [['your', 'full', 'name'], ['something', 'else']] # mailing list for the alerts tolist = ['you@mail.com', 'yourfriend@mail.com'] # email address that you want the alerts to come from fromaddr = 'feedmonitor@somewhere.com' # database variables myHost = "localhost" myUser = "username" myPasswd = "password" myDB = "dbName" # feedMonitor uses the following database schema # CREATE TABLE alerts( # aid int not null auto_increment, # subject varchar(256), # link varchar(512), # source varchar(512), # date_sent datetime, # PRIMARY KEY (aid)); ####################### END USER DEFINED VARIABLES ####################### # set up database connection db = MySQLdb.connect(host=myHost, user=myUser, passwd=myPasswd, db=myDB) c = db.cursor() # see if our filter matches a pattern, and if the record doesn't already exist # in the DB def filter(phrase, link): for pattern in patterns: alert = True postWords = string.split(string.lower(phrase)) for word in pattern: if word not in postWords: alert = False if alert: myQuery = "select * from alerts where link='" + link + "';" if(c.execute(myQuery) == 0L): if ("--console" in sys.argv) or ("-c" in sys.argv): print "New Link Found:",link return True return False # container for the items to monitor posts = [] # container for items to alert on alerts = [] for f in feeds: fp = open("tempfile","w") fp.write(urllib.urlopen(f).read()) fp.close() try: xmldoc = minidom.parse("tempfile") except: print "feedMonitor - unable to read feed:", f sys.exit() items = xmldoc.getElementsByTagName("item") for i in items: myTitle = i.getElementsByTagName("title") myLink = i.getElementsByTagName("link") # each post is a tuple containing the source, link, title, description # of the vuln try: posts.append((f, myLink[0].firstChild.toxml(), myTitle[0].firstChild.toxml())) except: pass # send each post to the keyword filter # any posts that match on one or more filters will be added to the list of # alerts to be mailed for post in posts: if filter(post[2],post[1]): alerts.append(post) # if there are any alerts found, mail them out if len(alerts): s = smtplib.SMTP("localhost") msg = 'To: ' for recipient in tolist[:-1]: msg += recipient+', ' msg += tolist[-1] if len(alerts) == 1: msg += '\nSubject: New Alert Found - Please Review\n\n' else: msg += '\nSubject: New Alerts Found - Please Review\n\n' for alert in alerts: msg += alert[2] + " - " + alert[1] + "\n\n" # log the alert in the database (if not in console mode) if "--console" not in sys.argv: myQuery = "insert into alerts(subject,link,source,date_sent) values('" + \ alert[2] + "','" + alert[1] + "','" + alert[0] + "','" + \ time.strftime('%Y-%m-%d %H:%M:%S') + "');" c.execute(myQuery) # if console is chosen, print only to the console if "--console" in sys.argv: print "\n",msg else: # send out the mail s.sendmail(fromaddr,tolist,msg) # a little housecleaning try: os.remove("tempfile") except: pass