This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
logtracker/logtracker/mail/utils.py

67 lines
3.0 KiB
Python
Executable File

#!/usr/bin/python3
# Entrouvert 2019
# Exim log parser
# See Summary of Fields in Log Lines in https://www.exim.org/exim-html-current/doc/html/spec_html/ch-log_files.html
import re
import pytz
from logtracker.journal.models import Entry
from logtracker.mail.models import Mail, Property, Sender, Recipient
paris = pytz.timezone('Europe/Paris')
patterns = {'ignore': re.compile('([\d-]+) ([\d:]+)? .*(Start queue run|End queue run|daemon started|relay not permitted|Spool file is locked'
'|Connection refused|Connection timed out|no immediate delivery|error ignored|Greylisting in action'
'|Remote host closed connection|No route to host|SMTP error|SMTP protocol error'
'|SMTP protocol synchronization error|SMTP command timeout|no host name found|unexpected disconnection'
'|TLS error|log string overflowed|cancelled by timeout|PRDR'
'|Key usage violation in certificate has been detected.: delivering unencrypted'
'|SIGHUP received: re-exec daemon).*'),
'match': re.compile('(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)? ?([\w\d\-]+) (<=|=>|->|==|\*\*|Completed|SMTP error|Message is frozen|Frozen|Unfrozen)\s*(.*)$'),
}
def parse_exim_lines(qs, debug=False):
for entry in qs:
if not entry.data.get('SYSLOG_IDENTIFIER') == 'exim':
continue
message = entry.data.get('MESSAGE')
match = re.match(patterns['match'], message)
if match:
_, identifier, action, data = match.groups()
yield entry, identifier, action, data
def extract_exim_emails():
metadata, _ = Property.objects.get_or_create(name='metadata')
if 'extracted_index' not in metadata.data:
metadata.data = {"extracted_index": 0}
metadata.save()
entry = None
try:
for entry, identifier, action, data in parse_exim_lines(Entry.objects.filter(pk__gt=metadata.data['extracted_index'])):
mail, created = Mail.objects.get_or_create(identifier=identifier)
if created:
mail.host = entry.host
mail.timestamp = entry.timestamp
mail.entries = [entry.pk]
else:
mail.entries.append(entry.pk)
if action == '<=':
address = data.split(' ')[0]
sender, _ = Sender.objects.get_or_create(email=address)
mail.sender = sender
elif action in ('=>', '->'):
address, _ = Recipient.objects.get_or_create(email=data.split(' ')[0])
mail.recipients.add(address)
elif action == 'Completed':
mail.has_completed = True
elif action == '==' or action == '**':
mail.has_error = True
mail.save()
finally:
if entry:
metadata.data['extracted_index'] = entry.pk
metadata.save()