cat > /tmp/parse.py << 'EOF'
import re, csv, datetime
entries = []
current = None
with open('/tmp/raw.txt') as f:
for line in f:
line = line.rstrip()
if line.startswith('QENTRY:') or line.startswith('SMTPD:'):
if current and current.get('to'):
entries.append(current)
current = {'timestamp':'','from':'','to':'','status':'','size':'','client':'','msgid':''}
elif current is not None:
if line.startswith('CTIME:'):
try:
ts = int(line.split(':',1)[1].strip(), 16)
current['timestamp'] = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
except: pass
elif line.startswith('SIZE:'):
current['size'] = line.split(':',1)[1].strip()
elif line.startswith('CLIENT:'):
current['client'] = line.split(':',1)[1].strip()
elif line.startswith('MSGID:'):
current['msgid'] = line.split(':',1)[1].strip().strip('<>')
elif line.startswith('TO:'):
parts = line.split(':', 4)
if len(parts) >= 4:
code = parts[3].strip()
if code in ('A','P','2'): current['status'] = 'allowed'
elif code in ('B','N'): current['status'] = 'blocked'
elif code == 'Q': current['status'] = 'quarantine'
elif code in ('G','D','4'): current['status'] = 'greylisted'
elif code == '5': current['status'] = 'failed'
else: current['status'] = code
m = re.search(r'from <([^>]*)> to <([^>]*)>', line)
if m:
current['from'] = m.group(1)
current['to'] = m.group(2)
if current and current.get('to'):
entries.append(current)
entries.sort(key=lambda x: x['timestamp'])
counts = {}
for e in entries:
counts[e['status']] = counts.get(e['status'], 0) + 1
with open('/tmp/ipa_mail_report.csv', 'w', newline='') as f:
w = csv.writer(f, delimiter=';')
w.writerow(['timestamp','from','to','status','size','client','msgid'])
for e in entries:
w.writerow([e['timestamp'], e['from'], e['to'], e['status'], e['size'], e['client'], e['msgid']])
print(f"{len(entries)} Mails exportiert")
for k in sorted(counts):
print(f" {k}: {counts[k]}")
if entries:
print(f"Zeitbereich: {entries[0]['timestamp']} bis {entries[-1]['timestamp']}")
EOF