Kaydet (Commit) 89686245 authored tarafından Sjoerd Mullender's avatar Sjoerd Mullender

Script to read and parse error messages from mailer daemons.

Written by Jack, some minor changes by Sjoerd.
üst 2bbe49bf
"""mailerdaemon - classes to parse mailer-daemon messages"""
import string
import rfc822
import regex
import os
import sys
Unparseable = 'mailerdaemon.Unparseable'
class ErrorMessage(rfc822.Message):
def __init__(self, fp):
rfc822.Message.__init__(self, fp)
def is_warning(self):
sub = self.getheader('Subject')
if not sub:
return 0
sub = string.lower(sub)
if sub == 'waiting mail': return 1
if string.find(sub, 'warning') >= 0: return 1
return 0
def get_errors(self):
for p in EMPARSERS:
self.rewindbody()
try:
return p(self.fp)
except Unparseable:
pass
raise Unparseable
sendmail_pattern = regex.compile('[0-9][0-9][0-9] ')
def emparse_sendmail(fp):
while 1:
line = fp.readline()
if not line:
raise Unparseable
line = line[:-1]
# Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:':
raise Unparseable
line = string.split(line)
if len(line) > 3 and \
((line[0] == '-----' and line[1] == 'Transcript') or
(line[0] == '---' and line[1] == 'The' and
line[2] == 'transcript') or
(line[0] == 'While' and line[1] == 'talking' and line[2] == 'to')):
# Yes, found it!
break
errors = []
found_a_line = 0
warnings = 0
while 1:
line = fp.readline()
if not line:
break
line = line[:-1]
if not line:
continue
found_a_line = 1
if sendmail_pattern.match(line) == 4:
# Yes, an error/warning line. Ignore 4, remember 5, stop on rest
if line[0] == '5':
errors.append(line)
elif line[0] == '4':
warnings = 1
else:
raise Unparseable
line = string.split(line)
if line and line[0][:3] == '---':
break
# Empty transcripts are ok, others without an error are not.
if found_a_line and not (errors or warnings):
raise Unparseable
return errors
def emparse_cts(fp):
while 1:
line = fp.readline()
if not line:
raise Unparseable
line = line[:-1]
# Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:':
raise Unparseable
line = string.split(line)
if len(line) > 3 and line[0][:2] == '|-' and line[1] == 'Failed' \
and line[2] == 'addresses':
# Yes, found it!
break
errors = []
while 1:
line = fp.readline()
if not line:
break
line = line[:-1]
if not line:
continue
errors.append(line)
if line[:2] == '|-':
break
return errors
def emparse_aol(fp):
while 1:
line = fp.readline()
if not line:
raise Unparseable
line = line[:-1]
if line:
break
exp = 'The mail you sent could not be delivered to:'
if line[:len(exp)] != exp:
raise Unparseable
errors = []
while 1:
line = fp.readline()
if sendmail_pattern.match(line) == 4:
# Yes, an error/warning line. Ignore 4, remember 5, stop on rest
if line[0] == '5':
errors.append(line)
elif line[0] != '4':
raise Unparseable
elif line == '\n':
break
else:
raise Unparseable
return errors
EMPARSERS = [emparse_sendmail, emparse_aol, emparse_cts]
def parsedir(dir, modify):
os.chdir(dir)
files = os.listdir('.')
pat = regex.compile('^[0-9]*$')
errordict = {}
errorlast = {}
nok = nwarn = nbad = 0
for fn in files:
if pat.match(fn) > 0:
# Ok, so it's a numeric filename. Lets try to parse it.
fp = open(fn)
m = ErrorMessage(fp)
sender = m.getaddr('From')
print '%s\t%-40s\t'%(fn, sender[1]),
if m.is_warning():
print 'warning only'
nwarn = nwarn + 1
if modify:
os.unlink(fn)
continue
try:
errors = m.get_errors()
except Unparseable:
print '** Not parseable'
nbad = nbad + 1
continue
print len(errors), 'errors'
# Remember them
for e in errors:
if not errordict.has_key(e):
errordict[e] = 1
else:
errordict[e] = errordict[e] + 1
errorlast[e] = fn
nok = nok + 1
if modify:
os.unlink(fn)
print '--------------'
print nok, 'files parsed,',nwarn,'files warning-only,',
print nbad,'files unparseable'
print '--------------'
for e in errordict.keys():
print errordict[e], '\t', errorlast[e], '\t', e
def main():
modify = 0
if len(sys.argv) > 1 and sys.argv[1] == '-d':
modify = 1
del sys.argv[1]
if len(sys.argv) > 1:
for folder in sys.argv[1:]:
parsedir(folder, modify)
else:
parsedir('/ufs/jack/Mail/errorsinbox', modify)
if __name__ == '__main__' or sys.argv[0] == __name__:
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment