mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-28 16:52:22 +01:00
33 lines
1.2 KiB
Python
33 lines
1.2 KiB
Python
"""Per-principal extraction directories for email attachments.
|
|
|
|
Shared by the HTTP email routes and the email MCP server, which both extract
|
|
attachments under MAIL_ATTACHMENTS_DIR.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
def attachment_scope_dir(root, folder, uid, *, owner, account_id) -> Path:
|
|
"""Return the extraction directory for one message's attachments.
|
|
|
|
IMAP UIDs are small per-mailbox counters and folder names are server- or
|
|
caller-supplied (`/`-delimited hierarchies, absolute or `..` segments), so
|
|
neither may become a path. The directory is one hex segment derived from
|
|
(owner, account, folder, uid): distinct principals and mailboxes never
|
|
share it, and no input can steer it out of *root*. Containment is checked
|
|
after resolution, so a symlinked entry cannot redirect it either.
|
|
"""
|
|
scope = json.dumps(
|
|
[str(owner or ""), str(account_id or ""), str(folder or ""), str(uid or "")],
|
|
ensure_ascii=False,
|
|
)
|
|
base = Path(root).resolve()
|
|
target = (base / hashlib.sha256(scope.encode("utf-8")).hexdigest()[:32]).resolve()
|
|
if target.parent != base:
|
|
raise ValueError("attachment directory escapes the extraction root")
|
|
return target
|