1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2025-04-04 00:17:06 +00:00
mailinabox/management/reporting/capture/mail/PostfixLogParser.py
downtownallday 2a0e50c8d4 Initial commit of a log capture and reporting feature
This adds a new section to the admin panel called "Activity", that
supplies charts, graphs and details about messages entering and leaving
the host.

A new daemon captures details of system mail activity by monitoring
the /var/log/mail.log file, summarizing it into a sqllite database
that's kept in user-data.
2021-01-11 18:02:07 -05:00

126 lines
3.7 KiB
Python

class PostfixLogParser(object):
@staticmethod
def split_host(str):
''' split string in form HOST[IP] and return HOST and IP '''
ip_start = str.find('[')
ip_end = -1
if ip_start>=0:
ip_end = str.find(']', ip_start)
if ip_start<0 or ip_end<0:
return str, str
return str[0:ip_start], str[ip_start+1:ip_end]
@staticmethod
def strip_brackets(str, bracket_l='<', bracket_r='>'):
# strip enclosing '<>'
if len(str)>=2 and str[0]==bracket_l and str[-1]==bracket_r:
return str[1:-1]
return str
class SplitList(object):
''' split a postfix name=value list. For example:
"delay=4.7, to=<alice@post.com>, status=sent (250 2.0.0 <user@domain.tld> YB5nM1eS01+lSgAAlWWVsw Saved)"
returns: {
"delay": {
"name": "delay",
"value": "4.7"
},
"to": {
"name": "to",
"value": "alice@post.com"
},
"status": {
"name": "status",
"value": "sent",
"comment": "250 2.0.0 <user@domain.tld> YB5nM1eS01+lSgAAlWWVsw Saved"
}
}
'''
def __init__(self, str, delim=',', strip_brackets=True):
self.str = str
self.delim = delim
self.strip_brackets = True
self.pos = 0
def asDict(self):
d = {}
for pair in self:
d[pair['name']] = pair
return d
def __iter__(self):
self.pos = 0
return self
def __next__(self):
if self.pos >= len(self.str):
raise StopIteration
# name
eq = self.str.find('=', self.pos)
if eq<0:
self.pos = len(self.str)
raise StopIteration
name = self.str[self.pos:eq].strip()
# value and comment
self.pos = eq+1
value = []
comment = []
while self.pos < len(self.str):
c = self.str[self.pos]
self.pos += 1
if c=='<':
idx = self.str.find('>', self.pos)
if idx>=0:
value.append(self.str[self.pos-1:idx+1])
self.pos = idx+1
continue
if c=='(':
# parens may be nested...
open_count = 1
begin = self.pos
while self.pos < len(self.str) and open_count>0:
c = self.str[self.pos]
self.pos += 1
if c=='(':
open_count += 1
elif c==')':
open_count -= 1
if open_count == 0:
comment.append(self.str[begin:self.pos-1])
else:
comment.append(self.str[begin:len(self.str)])
continue
if c==self.delim:
break
begin = self.pos-1
while self.pos < len(self.str):
lookahead = self.str[self.pos]
if lookahead in [self.delim,'<','(']:
break
self.pos += 1
value.append(self.str[begin:self.pos])
if self.strip_brackets and len(value)==1:
value[0] = PostfixLogParser.strip_brackets(value[0])
return {
'name': name,
'value': ''.join(value),
'comment': None if len(comment)==0 else '; '.join(comment)
}