nixspamsum
changeset 0 2d97e75f16cf
child 1 7d5cee19c20a
equal deleted inserted replaced
-1:000000000000 0:2d97e75f16cf
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 # Copyright 2009 Pascal Volk
       
     4 
       
     5 __author__ = 'Pascal Volk'
       
     6 __version__ = '0.1'
       
     7 __date__ = '2009-06-07'
       
     8 
       
     9 import os
       
    10 import re
       
    11 
       
    12 class NiXSpamPlot:
       
    13     """Do sth ..."""
       
    14 
       
    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.*$'''
       
    17 
       
    18     def __init__(self):
       
    19         self._doms = {}
       
    20         self._mxs  = {}
       
    21         self._repo = None
       
    22 
       
    23     def setLogFormat(self, format='postfix'):
       
    24         if format == 'postfix':
       
    25             self._repo = re.compile(NiXSpamPlot.RE_PF)
       
    26         else:
       
    27             raise Exception('MTA/Logformat not supported yet.')
       
    28 
       
    29     def parseLog(self, filehandle):
       
    30         for l in filehandle:
       
    31             mo = self._repo.match(l)
       
    32             if mo:
       
    33                 mx = mo.group(1)
       
    34                 try:
       
    35                     self._mxs[mx] += 1
       
    36                 except KeyError:
       
    37                     self._mxs[mx]  = 1
       
    38 
       
    39     def countByDom(self):
       
    40         for mx in self._mxs.keys():
       
    41             dom = '.'.join(mx.split('.')[-2:])
       
    42             try:
       
    43                 self._doms[dom] += self._mxs[mx]
       
    44             except KeyError:
       
    45                 self._doms[dom]  = self._mxs[mx]
       
    46 
       
    47     def getDomains(self):
       
    48         return self._doms
       
    49 
       
    50     def getMXs(self):
       
    51         return self._mxs
       
    52 
       
    53     def getTotal(self):
       
    54         return sum(self._mxs.values())
       
    55 
       
    56 def getOptionParser():
       
    57     from optparse import OptionParser
       
    58     usage  = 'usage: %prog [options] maillog [maillog [...]]'
       
    59     parser = OptionParser(usage=usage, description='do something ...')
       
    60     parser.add_option('-d', action='store_true', dest='countByDom',
       
    61             default=False, help='summarize all MX by domain')
       
    62     parser.add_option('-m', action='store_false', dest='countByDom',
       
    63             help='count per MX host [default]')
       
    64     parser.add_option('-o', dest='oFormat', default='table',metavar='FORMAT',
       
    65             help='the output format: table or csv [default: %default]')
       
    66     parser.add_option('-p', action='store_true', dest='percent', default=False,
       
    67             help='show also percentages in table output [default: %default]')
       
    68     parser.add_option('-s', dest='order', default='name', metavar='SORTBY',
       
    69             help='arrange output by: name or count [default: %default]')
       
    70     parser.add_option('-t', dest='format', default='postfix',metavar='MTA',
       
    71             help='MTA that generated the maillog [default: %default]')
       
    72     return parser
       
    73 
       
    74 def openLogFile(fname):
       
    75     try:
       
    76         fh = open(fname)
       
    77         return fh
       
    78     except IOError, e:
       
    79         os.sys.stderr.write('Warning: %s\nskipped file: %s\n' % (e.strerror,
       
    80             fname))
       
    81 
       
    82 def showResult(nixspamplot, options):
       
    83     if options.countByDom:
       
    84         nixspamplot.countByDom()
       
    85         domains = nixspamplot.getDomains()
       
    86     else:
       
    87         domains = nixspamplot.getMXs()
       
    88     if options.percent:
       
    89         total   = nixspamplot.getTotal()
       
    90     k = 0 if options.order == 'name' else 1
       
    91     doms = sorted(domains.items(), lambda d,c: cmp(d[k],c[k]), reverse=k)
       
    92     for d in doms:
       
    93         print "%s -> %d" % d
       
    94 
       
    95 def main():
       
    96     parser = getOptionParser()
       
    97     opts, args = parser.parse_args()
       
    98     if len(args) < 1:
       
    99         parser.error('No logfiles specified')
       
   100     nsp = NiXSpamPlot()
       
   101     nsp.setLogFormat(opts.format)
       
   102     for fn in args:
       
   103         fh = openLogFile(fn)
       
   104         if fh is not None:
       
   105             nsp.parseLog(fh)
       
   106             fh.close()
       
   107     showResult(nsp, opts)
       
   108 
       
   109 if __name__ == '__main__':
       
   110     main()