nixspamsum
changeset 1 7d5cee19c20a
parent 0 2d97e75f16cf
child 2 a72ea07394cc
equal deleted inserted replaced
0:2d97e75f16cf 1:7d5cee19c20a
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 # Copyright 2009 Pascal Volk
     3 # Copyright 2009 Pascal Volk
     4 
     4 
     5 __author__ = 'Pascal Volk'
     5 __author__ = 'Pascal Volk'
     6 __version__ = '0.1'
     6 __version__ = '0.1.1'
     7 __date__ = '2009-06-07'
     7 __date__ = '2009-06-07'
     8 
     8 
     9 import os
     9 import os
    10 import re
    10 import re
    11 
    11 
    12 class NiXSpamPlot:
    12 class NiXSapmSum:
    13     """Do sth ..."""
    13     """Do sth ..."""
    14 
    14 
    15     """Regular expression pattern for mail logs from Postfix"""
    15     """Regular expression pattern for mail logs from Postfix"""
    16     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.*$'''
    16     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.*$'''
    17 
    17 
    20         self._mxs  = {}
    20         self._mxs  = {}
    21         self._repo = None
    21         self._repo = None
    22 
    22 
    23     def setLogFormat(self, format='postfix'):
    23     def setLogFormat(self, format='postfix'):
    24         if format == 'postfix':
    24         if format == 'postfix':
    25             self._repo = re.compile(NiXSpamPlot.RE_PF)
    25             self._repo = re.compile(NiXSapmSum.RE_PF)
    26         else:
    26         else:
    27             raise Exception('MTA/Logformat not supported yet.')
    27             raise Exception('MTA/Logformat not supported yet.')
    28 
    28 
    29     def parseLog(self, filehandle):
    29     def parseLog(self, filehandle):
    30         for l in filehandle:
    30         for l in filehandle:
    53     def getTotal(self):
    53     def getTotal(self):
    54         return sum(self._mxs.values())
    54         return sum(self._mxs.values())
    55 
    55 
    56 def getOptionParser():
    56 def getOptionParser():
    57     from optparse import OptionParser
    57     from optparse import OptionParser
       
    58     description = 'do something ...'
    58     usage  = 'usage: %prog [options] maillog [maillog [...]]'
    59     usage  = 'usage: %prog [options] maillog [maillog [...]]'
    59     parser = OptionParser(usage=usage, description='do something ...')
    60     version = '%prog '+__version__
       
    61     parser = OptionParser(description=description,usage=usage,version=version)
    60     parser.add_option('-d', action='store_true', dest='countByDom',
    62     parser.add_option('-d', action='store_true', dest='countByDom',
    61             default=False, help='summarize all MX by domain')
    63             default=False, help='summarize all MX by domain')
    62     parser.add_option('-m', action='store_false', dest='countByDom',
    64     parser.add_option('-m', action='store_false', dest='countByDom',
    63             help='count per MX host [default]')
    65             help='count per MX host [default]')
    64     parser.add_option('-o', dest='oFormat', default='table',metavar='FORMAT',
    66     parser.add_option('-o', dest='oFormat', default='table',metavar='FORMAT',
    77         return fh
    79         return fh
    78     except IOError, e:
    80     except IOError, e:
    79         os.sys.stderr.write('Warning: %s\nskipped file: %s\n' % (e.strerror,
    81         os.sys.stderr.write('Warning: %s\nskipped file: %s\n' % (e.strerror,
    80             fname))
    82             fname))
    81 
    83 
    82 def showResult(nixspamplot, options):
    84 def getDomLen(domainnames):
       
    85     dlen = 0
       
    86     for d in domainnames:
       
    87         l = len(d)
       
    88         if l > dlen:
       
    89             dlen = l
       
    90     return dlen
       
    91 
       
    92 def showResult(nixspamsum, options):
    83     if options.countByDom:
    93     if options.countByDom:
    84         nixspamplot.countByDom()
    94         nixspamsum.countByDom()
    85         domains = nixspamplot.getDomains()
    95         domains = nixspamsum.getDomains()
    86     else:
    96     else:
    87         domains = nixspamplot.getMXs()
    97         domains = nixspamsum.getMXs()
    88     if options.percent:
       
    89         total   = nixspamplot.getTotal()
       
    90     k = 0 if options.order == 'name' else 1
    98     k = 0 if options.order == 'name' else 1
    91     doms = sorted(domains.items(), lambda d,c: cmp(d[k],c[k]), reverse=k)
    99     doms = sorted(domains.items(), lambda d,c: cmp(d[k],c[k]), reverse=k)
    92     for d in doms:
   100     # print table
    93         print "%s -> %d" % d
   101     if options.oFormat == 'table':
       
   102         dlen = getDomLen(domains.keys())+1
       
   103         clen = len(str(max(domains.values())))
       
   104         if options.percent:
       
   105             total = nixspamsum.getTotal()
       
   106             format = '%%%ds  %%%dd  %%5.2f %%%%' % (dlen, clen)
       
   107             for d, c in doms:
       
   108                 dfrac = 100./total*c
       
   109                 print format % (d, c, dfrac)
       
   110         else:
       
   111             format = '%%%ds: %%%dd' % (dlen, clen)
       
   112             for d in doms:
       
   113                 print format % d
       
   114     # print comma separated values
       
   115     elif options.oFormat == 'csv':
       
   116         for d in doms:
       
   117             print "'%s',%d" % d
       
   118     # print a hint ;-)
       
   119     else:
       
   120         print "Output format '%s' is not supported" % options.oFormat
    94 
   121 
    95 def main():
   122 def main():
    96     parser = getOptionParser()
   123     parser = getOptionParser()
    97     opts, args = parser.parse_args()
   124     opts, args = parser.parse_args()
    98     if len(args) < 1:
   125     if len(args) < 1:
    99         parser.error('No logfiles specified')
   126         parser.error('No logfiles specified')
   100     nsp = NiXSpamPlot()
   127     nixss = NiXSapmSum()
   101     nsp.setLogFormat(opts.format)
   128     nixss.setLogFormat(opts.format)
   102     for fn in args:
   129     for fn in args:
   103         fh = openLogFile(fn)
   130         fh = openLogFile(fn)
   104         if fh is not None:
   131         if fh is not None:
   105             nsp.parseLog(fh)
   132             nixss.parseLog(fh)
   106             fh.close()
   133             fh.close()
   107     showResult(nsp, opts)
   134     showResult(nixss, opts)
   108 
   135 
   109 if __name__ == '__main__':
   136 if __name__ == '__main__':
   110     main()
   137     main()