#!/usr/bin/env python # -*- coding: iso-8859-1 -*- from optparse import OptionParser from emailinfo import EmailInfo from emailmap import EmailMap from locationverifier import LocationVerifier import os def main(): global options, parser parser = OptionParser(usage="usage: %prog [options] file|directory [file|directory] [file|directory] ...", description="Analyzes email headers and extracts geographic information.") parser.add_option("-p", "--print", action="store_true", help="Print geographic information about each encountered email.", dest="printinfo") parser.add_option("-d", "--debug", action="store_true", help="Display when email parser has to dig a little deeper to find the correct IP.") parser.add_option("-m", "--map", action="store", type="string", metavar="HTMLFILE", help="Generate visual representation of emails in a Google Map and write html to HTMLFILE. When combined with -v, --verify, only verified points are plotted.") parser.add_option("-v", "--verify", action="store", type="string", metavar="CSVFILE", help="Verify accuracy of algorithm by comparing to CSV table with the first column of the first row the default country, then in the next rows, the first column the start date (mm/dd/yyyy), the second column the end date, and the remaining columns the countries visited. When combined with -m, --map, only verified points are plotted.") (options, args) = parser.parse_args() if options.debug == None and options.map == None and options.printinfo == None and options.verify == None: options.printinfo = True if len(args) == 0: parser.error("at least one file or directory is required for analysis") if options.map != None: global mailmap mailmap = EmailMap() if options.verify != None: global verification locations = open(options.verify, "r") verification = LocationVerifier(locations) locations.close() for file in args: processPath(file) if options.map != None: outfile = open(options.map, "w") mailmap.writeMap(outfile) outfile.close() print "Map written to %s" % options.map if options.verify != None: print verification if len(verification.misses) > 0: print "Non-verified Locations:" verification.misses.sort() for email in verification.misses: print "\t%s sent %s from %s in %s" % (email.path, email.date.date(), email.ip, email.location()[1][2]) def traverseDirectory(directory): for file in os.listdir(directory): processPath(os.path.join(directory, file)) def processPath(path): if os.path.isfile(path): processFile(path) elif os.path.isdir(path): traverseDirectory(path) elif not os.path.exists(path): parser.error("%s does not exist" % path) def processFile(fileName): try: examine = EmailInfo.parseFile(fileName) except: if options.debug: print "unable to parse %s" % fileName return if options.debug and examine.debug: print fileName + ":", print examine.debug if options.map != None and options.verify != None: if verification.checkEmail(examine): mailmap.addEmail(examine) elif options.verify != None: verification.checkEmail(examine) elif options.map != None: mailmap.addEmail(examine) if options.printinfo: print fileName + ":" print "\tSent: %s at %s" % (examine.date.date(), examine.date.time()) print "\tIP: " + examine.ip location = examine.location() print ("\tCity: " + "%s, %s, %s" % location[1]).encode("utf-8") print "\tCoordinates: %s, %s" % location[0] if __name__ == '__main__': main()