from __future__ import annotations import hashlib import time from collections import OrderedDict class EmailDeduplicator: def __init__(self, max_entries: int = 100_000, ttl_seconds: int = 259200): self._seen: OrderedDict[str, float] = OrderedDict() self._max_entries = max_entries self._ttl = ttl_seconds def is_duplicate(self, message_id: str, uid: str = "") -> bool: key = self._make_key(message_id, uid) self._expire() return key in self._seen def mark(self, message_id: str, uid: str = ""): key = self._make_key(message_id, uid) self._expire() self._seen[key] = time.monotonic() if len(self._seen) > self._max_entries: self._seen.popitem(last=False) def _make_key(self, message_id: str, uid: str) -> str: raw = f"{message_id}|{uid}".strip().lower() return hashlib.sha256(raw.encode()).hexdigest()[:32] def _expire(self): now = time.monotonic() while self._seen: key, ts = next(iter(self._seen.items())) if now - ts > self._ttl: self._seen.popitem(last=False) else: break def handle_uidvalidity_change(self): self._seen.clear()