2 # -*- coding: utf-8 -*- |
2 # -*- coding: utf-8 -*- |
3 # Copyright 2009 - 2010 Pascal Volk |
3 # Copyright 2009 - 2010 Pascal Volk |
4 # See COPYING for distribution information. |
4 # See COPYING for distribution information. |
5 |
5 |
6 __author__ = 'Pascal Volk' |
6 __author__ = 'Pascal Volk' |
7 __version__ = '0.1.2' |
7 __version__ = '0.1.3' |
8 __date__ = '2009-07-03' |
8 __date__ = '2010-04-11' |
9 |
9 |
10 import os |
10 import os |
11 import re |
11 import re |
12 import fileinput |
12 import fileinput |
|
13 |
13 |
14 |
14 class NiXSapmSum(object): |
15 class NiXSapmSum(object): |
15 """ |
16 """ |
16 Small log parser class to parse and summarize NiX Spam DNSBL lookup |
17 Small log parser class to parse and summarize NiX Spam DNSBL lookup |
17 based rejects from a mail log file. |
18 based rejects from a mail log file. |
24 RE_PF = r'''^[\w\s:-]{17,80}\spostfix\/smtpd\[[\d]{1,5}\]:\sNOQUEUE: |
25 RE_PF = r'''^[\w\s:-]{17,80}\spostfix\/smtpd\[[\d]{1,5}\]:\sNOQUEUE: |
25 \sreject:.*blocked\susing\six.dnsbl.manitu.net; |
26 \sreject:.*blocked\susing\six.dnsbl.manitu.net; |
26 \sSpam\ssent\sto\sthe\smailhost\s(%s|%s) |
27 \sSpam\ssent\sto\sthe\smailhost\s(%s|%s) |
27 \swas\sdetected\sby\sNiX\sSpam.*$''' % (RE_FQDN, RE_IPv4) |
28 \swas\sdetected\sby\sNiX\sSpam.*$''' % (RE_FQDN, RE_IPv4) |
28 |
29 |
29 |
|
30 def __init__(self): |
30 def __init__(self): |
31 self._doms = {} |
31 self._doms = {} |
32 self._mxs = {} |
32 self._mxs = {} |
33 self._repo = None |
33 self._repo = None |
34 |
34 |
35 def setLogFormat(self, format='postfix'): |
35 def setLogFormat(self, format='postfix'): |
36 if format == 'postfix': |
36 if format == 'postfix': |
37 self._repo = re.compile(NiXSapmSum.RE_PF, re.VERBOSE) |
37 self._repo = re.compile(NiXSapmSum.RE_PF, re.VERBOSE) |
69 |
69 |
70 |
70 |
71 def getOptionParser(): |
71 def getOptionParser(): |
72 from optparse import OptionParser |
72 from optparse import OptionParser |
73 description = 'NiX Spam DNSBL lookup based rejects summarizer' |
73 description = 'NiX Spam DNSBL lookup based rejects summarizer' |
74 usage = 'usage: %prog [options] maillog [maillog [...]]' |
74 usage = 'usage: %prog [options] maillog [maillog [...]]' |
75 version = '%prog '+__version__ |
75 version = '%prog ' + __version__ |
76 parser = OptionParser(description=description,usage=usage,version=version) |
76 parser = OptionParser(description=description, usage=usage, |
|
77 version=version) |
77 parser.add_option('-d', action='store_true', dest='countByDom', |
78 parser.add_option('-d', action='store_true', dest='countByDom', |
78 default=False, help='summarize all MX by domain') |
79 default=False, help='summarize all MX by domain') |
79 parser.add_option('-m', action='store_false', dest='countByDom', |
80 parser.add_option('-m', action='store_false', dest='countByDom', |
80 help='count per MX host [default]') |
81 help='count per MX host [default]') |
81 parser.add_option('-o', dest='oFormat', default='table',metavar='FORMAT', |
82 parser.add_option('-o', dest='oFormat', default='table', metavar='FORMAT', |
82 choices=('csv', 'table'), |
83 choices=('csv', 'table'), |
83 help='the output format: table or csv [default: %default]') |
84 help='the output format: table or csv [default: %default]') |
84 parser.add_option('-p', action='store_true', dest='percent', default=False, |
85 parser.add_option('-p', action='store_true', dest='percent', default=False, |
85 help='show also percentages in table output [default: %default]') |
86 help='show also percentages in table output [default: %default]') |
86 parser.add_option('-s', dest='order', default='name', metavar='SORTBY', |
87 parser.add_option('-s', dest='order', default='name', metavar='SORTBY', |
87 choices=('count', 'name'), |
88 choices=('count', 'name'), |
88 help='arrange output by: name or count [default: %default]') |
89 help='arrange output by: name or count [default: %default]') |
89 parser.add_option('-t', dest='format', default='postfix',metavar='MTA', |
90 parser.add_option('-t', dest='format', default='postfix', metavar='MTA', |
90 choices=('postfix',), |
91 choices=('postfix',), |
91 help='MTA that generated the maillog [default: %default]') |
92 help='MTA that generated the maillog [default: %default]') |
92 return parser |
93 return parser |
93 |
94 |
94 |
95 |
121 return False |
122 return False |
122 |
123 |
123 |
124 |
124 def buildTable(output, domains, percent, orderBy): |
125 def buildTable(output, domains, percent, orderBy): |
125 k = 0 if orderBy == 'name' else 1 |
126 k = 0 if orderBy == 'name' else 1 |
126 doms = sorted(domains.items(), lambda d,c: cmp(d[k],c[k]), reverse=k) |
127 doms = sorted(domains.items(), lambda d, c: cmp(d[k], c[k]), reverse=k) |
127 dlen = len(max(domains.iterkeys(), key=len)) + 1 |
128 dlen = len(max(domains.iterkeys(), key=len)) + 1 |
128 clen = len(str(max(domains.values()))) |
129 clen = len(str(max(domains.values()))) |
129 total = sum(domains.values()) |
130 total = sum(domains.values()) |
130 if percent: |
131 if percent: |
131 format = ' %%%ds %%%dd %%6.2f %%%%\n' % (-dlen, clen) |
132 format = ' %%%ds %%%dd %%6.2f %%%%\n' % (-dlen, clen) |
132 for d, c in doms: |
133 for d, c in doms: |
133 dfrac = 100./total*c |
134 dfrac = 100. / total * c |
134 output.write(format % (d, c, dfrac)) |
135 output.write(format % (d, c, dfrac)) |
135 output.write('%s\n' % ((clen+dlen+14)*'-')) |
136 output.write('%s\n' % ((clen + dlen + 14) * '-')) |
136 output.write(format % ('total', total, 100)) |
137 output.write(format % ('total', total, 100)) |
137 else: |
138 else: |
138 format = ' %%%ds %%%dd\n' % (-dlen, clen) |
139 format = ' %%%ds %%%dd\n' % (-dlen, clen) |
139 for d in doms: |
140 for d in doms: |
140 output.write(format % d) |
141 output.write(format % d) |
141 output.write('%s\n' % ((clen+dlen+4)*'-')) |
142 output.write('%s\n' % ((clen + dlen + 4) * '-')) |
142 output.write(format % ('total', total)) |
143 output.write(format % ('total', total)) |
|
144 |
143 |
145 |
144 def showResult(nixspamsum, options): |
146 def showResult(nixspamsum, options): |
145 if options.countByDom: |
147 if options.countByDom: |
146 nixspamsum.countByDom() |
148 nixspamsum.countByDom() |
147 domains = nixspamsum.getDomains() |
149 domains = nixspamsum.getDomains() |