Sindbad~EG File Manager

Current Path : /opt/dedrads/mailparse/
Upload File :
Current File : //opt/dedrads/mailparse/eximparse.py

#!/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