from __future__ import absolute_import
# Standard modules
-import copy
+# import copy
import logging
import re
_ = XLATOR.gettext
ngettext = XLATOR.ngettext
-__version__ = '0.2.0'
+__version__ = '0.2.1'
# =============================================================================
class PostfixLogfileParser(HandlingObject):
"""Handler class for parsing and analysing postfix logfiles."""
- pattern_logentry = r'^(?P<timestamp>\S+)\s+\S+\s+'
+ pattern_logentry = r'^(?P<timestamp>\S+)\s+(?P<host>\S+)\s+'
pattern_logentry += r'(?P<command>[^\[\s]+)\[(?P<pid>\d+)\]:\s+'
pattern_logentry += r'(?P<msg>.*)\s*$'
self.active_smtpd_pid = {}
# -------------------------------------------------------------------------
- def parse(self, fh, mailhost=None):
+ def parse(self, fh):
"""Parse the content of a given logfile and store the results in self.chains."""
- if mailhost:
- msg = _('Start parsing postfix logfile from {!r} ...').format(mailhost)
- else:
- msg = _('Start parsing postfix logfile ...')
- LOG.debug(msg)
+ LOG.debug(_('Start parsing postfix logfile ...'))
for line in fh.readlines():
- self.evaluate_logline(line, mailhost)
+ self.evaluate_logline(line)
# -------------------------------------------------------------------------
- def evaluate_logline(self, line, mailhost):
+ def evaluate_logline(self, line):
"""Parse a single line from a postfix logfile."""
m = self.re_logentry.match(line)
if not m:
return
timestamp = m['timestamp']
+ host = m['host']
command = m['command']
pid = int(m['pid'])
message = m['msg']
m_conn = self.re_connect.search(message)
if m_conn:
chain = PostfixLogchainInfo(
- client_host= m_conn['client'],
+ client_host=m_conn['client'],
client_addr=m_conn['addr'],
start=timestamp,
postfix_id=postfix_id,
smtpd_pid=pid,
- mailhost=mailhost,
+ mailhost=host,
)
self.active_smtpd_pid[pid] = chain
_ = XLATOR.gettext
ngettext = XLATOR.ngettext
-__version__ = '0.5.1'
+__version__ = '0.5.2'
LOG = logging.getLogger(__name__)
)
# -------------------------------------------------------------------------
- def __init__(
- self, client_host=None, client_addr=None, start=None, end=None, message_id=None,
- postfix_id=None, ehlo=None, starttls=None, sent_quit=None, auth=None, commands=None,
- rcpt=None, data=None, mail=None, from_address=None, to_address=None, smtpd_pid=None,
- mailhost=None):
+ def __init__(self, **kwargs):
"""Initialize this object."""
- self._auth = None
- self._client_addr = None
- self._client_host = None
- self._commands = None
- self._data = None
- self._end = None
- self._ehlo = None
- self._from_address = None
- self._mail = None
- self._message_id = None
- self._postfix_id = None
- self._rcpt = None
- self._sent_quit = None
- self._smtpd_pid = None
- self._start = None
- self._starttls = None
- self._to_address = None
- self._mailhost = None
-
- self.auth = auth
- self.client_addr = client_addr
- self.client_host = client_host
- self.commands = commands
- self.data = data
- self.ehlo = ehlo
- self.end = end
- self.from_address = from_address
- self.message_id = message_id
- self.mail = mail
- self.mailhost = mailhost
- self.postfix_id = postfix_id
- self.rcpt = rcpt
- self.sent_quit = sent_quit
- self.smtpd_pid = smtpd_pid
- self.start = start
- self.starttls = starttls
- self.to_address = to_address
+ for attr in self.attributes:
+ priv_name = '_' + attr
+ setattr(self, priv_name, None)
+
+ for attr in kwargs.keys():
+ if attr not in self.attributes:
+ msg = _('Unknown parameter {p!r} on calling {c}.__init__().').format(
+ p=attr, c=self.__class__.__name__)
+ raise AttributeError(msg)
+ setattr(self, attr, kwargs[attr])
# -------------------------------------------------------------------------
@classmethod
else:
res = super(PostfixLogchainInfo, self).as_dict(short=short)
- atribs = (
- 'client_host', 'client_addr', 'start', 'end', 'message_id', 'postfix_id', 'ehlo',
- 'starttls', 'sent_quit', 'auth', 'commands', 'rcpt', 'data', 'mail', 'from_address',
- 'to_address', 'smtpd_pid', 'mailhost')
- for attrib in atribs:
+ for attrib in self.attributes:
if not hasattr(self, attrib):
continue
value = getattr(self, attrib, None)
return res
+ # -------------------------------------------------------------------------
+ def __copy__(self):
+ """Copy the current chain data into a new object."""
+ params = {}
+
+ for attrib in self.attributes:
+ value = getattr(self, attrib, None)
+ if value is None:
+ continue
+ params[attrib] = copy.copy(value)
+
+ return self.__class__(**params)
+
# =============================================================================