diff --git a/mail/server.py b/mail/server.py index a10a931..0932870 100644 --- a/mail/server.py +++ b/mail/server.py @@ -7,6 +7,8 @@ import io import contextlib import imaplib import mailbox +import gc +import ctypes from email.header import decode_header from email.mime.text import MIMEText from email.utils import formatdate @@ -47,6 +49,22 @@ mcp = FastMCP("Mail", stateless_http=True, transport_security={"enable_dns_rebinding_protection": False}) +try: + _libc = ctypes.CDLL("libc.so.6") +except OSError: + _libc = None + + +def _trim_memory(): + """gc + malloc_trim: Speicher nach grossen Operationen ans OS zurueckgeben.""" + gc.collect() + if _libc is not None: + try: + _libc.malloc_trim(0) + except Exception: + pass + + def _safe_decode(payload, charset): """Decode bytes robust gegen unbekannte/kaputte Charsets (z.B. 'x-unknown').""" if not isinstance(payload, bytes): @@ -207,7 +225,9 @@ def search_mail( continue results.append(f"[{date_str}] {frm} -> {to}\n Subject: {subj}\n Account: {acct_name}, Folder: {fld}, Key: {key}") if len(results) >= limit: + _trim_memory() return "\n\n".join(results) + _trim_memory() return "\n\n".join(results) if results else "No results found" @@ -254,6 +274,7 @@ def read_attachment( attachment_index: Annotated[int, Field(description="Attachment number from the read_mail attachment list (1-based)")], ) -> list[TextContent | ImageContent | EmbeddedResource]: """Read an email attachment. Images shown inline, PDFs as extracted text, text directly, other documents as binary. Get the index from read_mail.""" + _trim_memory() user = get_current_user() if not user: return [TextContent(type="text", text="Error: not authenticated")]