showResult(): count matches; break if no matches were found
sort by domain name if the output format is CSV
#!/usr/bin/env python# -*- coding: utf-8 -*-# Copyright 2009 Pascal Volk__author__='Pascal Volk'__version__='0.1.2'__date__='2009-07-03'importosimportreclassNiXSapmSum:"""Do sth ...""""""Regular expression pattern for mail logs from Postfix"""RE_PF='''^[\w\s:-]{17,80}\spostfix\/smtpd\[[\d]{3,5}\]: NOQUEUE: reject:.*blocked using ix.dnsbl.manitu.net; Spam sent to the mailhost ((?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}) was detected by NiX Spam.*$'''def__init__(self):self._doms={}self._mxs={}self._repo=NonedefsetLogFormat(self,format='postfix'):ifformat=='postfix':self._repo=re.compile(NiXSapmSum.RE_PF)else:raiseException('MTA/Logformat not supported yet.')defparseLog(self,filehandle):forlinfilehandle:mo=self._repo.match(l)ifmo:mx=mo.group(1)try:self._mxs[mx]+=1exceptKeyError:self._mxs[mx]=1defcountByDom(self):formxinself._mxs.keys():dom='.'.join(mx.split('.')[-2:])try:self._doms[dom]+=self._mxs[mx]exceptKeyError:self._doms[dom]=self._mxs[mx]defgetDomains(self):returnself._domsdefgetMXs(self):returnself._mxsdefgetOptionParser():fromoptparseimportOptionParserdescription='do something ...'usage='usage: %prog [options] maillog [maillog [...]]'version='%prog '+__version__parser=OptionParser(description=description,usage=usage,version=version)parser.add_option('-d',action='store_true',dest='countByDom',default=False,help='summarize all MX by domain')parser.add_option('-m',action='store_false',dest='countByDom',help='count per MX host [default]')parser.add_option('-o',dest='oFormat',default='table',metavar='FORMAT',help='the output format: table or csv [default: %default]')parser.add_option('-p',action='store_true',dest='percent',default=False,help='show also percentages in table output [default: %default]')parser.add_option('-s',dest='order',default='name',metavar='SORTBY',help='arrange output by: name or count [default: %default]')parser.add_option('-t',dest='format',default='postfix',metavar='MTA',help='MTA that generated the maillog [default: %default]')returnparserdefopenLogFile(fname):try:fh=open(fname)returnfhexceptIOError,e:os.sys.stderr.write('Warning: %s\nskipped file: %s\n'%(e.strerror,fname))defgetDomLen(domainnames):dlen=0fordindomainnames:l=len(d)ifl>dlen:dlen=lreturndlendefbuildTable(output,domains,percent,orderBy):k=0iforderBy=='name'else1doms=sorted(domains.items(),lambdad,c:cmp(d[k],c[k]),reverse=k)dlen=getDomLen(domains.keys())+1clen=len(str(max(domains.values())))total=sum(domains.values())ifpercent:format=' %%%ds %%%dd %%6.2f %%%%\n'%(-dlen,clen)ford,cindoms:dfrac=100./total*coutput.write(format%(d,c,dfrac))output.write('%s\n'%((clen+dlen+14)*'-'))output.write(format%('total',total,100))else:format=' %%%ds %%%dd\n'%(-dlen,clen)fordindoms:output.write(format%d)output.write('%s\n'%((clen+dlen+4)*'-'))output.write(format%('total',total))defshowResult(nixspamsum,options):ifoptions.countByDom:nixspamsum.countByDom()domains=nixspamsum.getDomains()else:domains=nixspamsum.getMXs()ifnotlen(domains):print"No Nix Spam RBL rejects found"returnfromcStringIOimportStringIOoutput=StringIO()# build the tableifoptions.oFormat=='table':buildTable(output,domains,options.percent,options.order)# generate comma separated valueselifoptions.oFormat=='csv':order=domains.keys()order.sort()fordinorder:output.write("'%s',%d\n"%(d,domains[d]))# should never be reachedelse:print"Oops, error in function showResult() happend"# show the resultprintoutput.getvalue()defmain():parser=getOptionParser()opts,args=parser.parse_args()ifopts.oFormatnotin('csv','table'):parser.error("Output format '%s' is not supported"%opts.oFormat)iflen(args)<1:parser.error('No logfiles specified')nixss=NiXSapmSum()nixss.setLogFormat(opts.format)forfninargs:fh=openLogFile(fn)iffhisnotNone:nixss.parseLog(fh)fh.close()showResult(nixss,opts)if__name__=='__main__':main()