Sindbad~EG File Manager
#!/usr/lib/rads/venv/bin/python3
import hashlib
import re
import json
import os
PATTERN_IN = re.compile(
r'^(?P<date>\d{4}-\d{2}-\d{2}) '
r'(?P<time>\d{2}:\d{2}:\d{2})\.\d+\s+'
r'\[\d+\] (?P<msgid>\S+) <= (?P<env_sender>\S+).*?'
r'T="(?P<subject>.*?)"\s+'
r'from\s+<(?P<sender>[^>]+)>\s+'
r'for\s+(?P<recipient>\S+)'
)
PATTERN_OUT = re.compile(
r'^\d{4}-\d{2}-\d{2} '
r'\d{2}:\d{2}:\d{2}\.\d+ '
r'\[\d+\] (?P<msgid>\S+) => '
r'(?P<recipient>\S+).*?'
r'\bR=(?P<router>\S+)'
)
MSGID_MAP = {}
EXIM_LOG = "/var/log/exim_mainlog"
OFFSET_FILE = "/opt/dedrads/mailparse/log_offsets.json"
OUTUT_LOG = "/opt/dedrads/mailparse/out/messages.json"
routers = [
"remoteserver_route",
"dkim_lookuphost",
]
def load_offset(json_file):
try:
with open(json_file, encoding="utf-8") as f:
return json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
return {} # If the file doesn't exist or can't be decoded, start from 0
# Function to save the offset to a JSON file
def save_offset(json_file, offsets):
with open(json_file, 'w', encoding="utf-8") as f:
json.dump(offsets, f, indent=4)
def parse_exim():
offsets = load_offset(OFFSET_FILE)
last_position = offsets.get(EXIM_LOG, 0)
previous_first_line = offsets.get('exim_start_hash', 0)
# store the md5 of the first line
with open(EXIM_LOG, encoding="utf-8", errors="replace") as f:
current_first_line = f.readline().strip()
current_first_line_hash = hashlib.md5(
current_first_line.encode("utf-8")
).hexdigest()
# start at 0 if the first line md5s dont match or the log is smaller
# than the offset
if (
previous_first_line != current_first_line_hash
or last_position > os.path.getsize(EXIM_LOG)
):
last_position = 0
offsets['exim_start_hash'] = current_first_line_hash
# store <= lines
with open(EXIM_LOG, encoding="utf-8", errors="replace") as f:
f.seek(last_position)
for line in f:
m = PATTERN_IN.search(line)
if m:
msgid = m.group("msgid")
MSGID_MAP[msgid] = {
"msgid": msgid,
"date": m.group("date"),
"time": m.group("time"),
"envelope_sender": m.group("env_sender"),
"subject": m.group("subject"),
"from": m.group("sender"),
"original_recipient": m.group("recipient"),
}
# store => lines
with (
open(EXIM_LOG, encoding="utf-8", errors="replace") as f,
open(OUTUT_LOG, "a", encoding="utf-8") as out,
):
f.seek(last_position)
for line in f:
m = PATTERN_OUT.search(line)
if not m:
continue
msgid = m.group("msgid")
router = m.group("router")
# identify outgoing message by checking for known routers
if msgid in MSGID_MAP and router in routers:
result = MSGID_MAP[msgid].copy()
result["delivered_to"] = m.group("recipient")
# result["router"] = router
result["outbound_line"] = line.strip()
out.write(json.dumps(result) + "\n")
# get end of file
last_position = f.tell()
offsets[EXIM_LOG] = last_position
# update offset json
save_offset(OFFSET_FILE, offsets)
if __name__ == "__main__":
parse_exim()
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists