#!/usr/bin/env python3 """ Download alle e-mails van een IMAP-account naar lokale .eml-bestanden. Gebruik: python download_mailbox.py Resultaat: mailbox//.eml Het script is herstart-safe: al gedownloade mails worden overgeslagen. """ import imaplib import os import re import sys import getpass from pathlib import Path IMAP_HOST = "australius.nl" IMAP_PORT = 993 LOCAL_DIR = Path(__file__).parent / "mailbox" def parse_folder_name(line: bytes) -> str | None: """Haal mapnaam op uit IMAP LIST-response.""" decoded = line.decode("utf-8", errors="replace") # Formaat: (\Flags) "delimiter" "naam" of (\Flags) "delimiter" naam match = re.match(r'\(.*?\)\s+".*?"\s+(.*)', decoded) if not match: return None name = match.group(1).strip().strip('"') return name if name else None def safe_path(name: str) -> str: """Zet mapnaam om naar een veilige directorynaam.""" return re.sub(r'[<>:"/\\|?*\x00-\x1f]', "_", name) def download(): username = input("E-mailadres: ").strip() password = getpass.getpass("Wachtwoord: ") print(f"\nVerbinden met {IMAP_HOST}:{IMAP_PORT} ...") try: mail = imaplib.IMAP4_SSL(IMAP_HOST, IMAP_PORT) mail.login(username, password) except Exception as exc: print(f"Mislukt: {exc}") sys.exit(1) print("Ingelogd.\n") # Alle mappen ophalen status, raw_folders = mail.list() if status != "OK": print("Kan mappenlijst niet ophalen.") sys.exit(1) folders = [parse_folder_name(f) for f in raw_folders if f] folders = [f for f in folders if f] print(f"Gevonden mappen ({len(folders)}):") for f in folders: print(f" {f}") print() total_new = total_skip = total_err = 0 num_folders = len(folders) for folder_idx, folder in enumerate(folders, 1): folder_prefix = f"[map {folder_idx}/{num_folders}] {folder}" quoted = f'"{folder}"' status, data = mail.select(quoted, readonly=True) if status != "OK": print(f"{folder_prefix}: kan niet openen – overgeslagen.") continue num = int(data[0]) local_dir = LOCAL_DIR / safe_path(folder) local_dir.mkdir(parents=True, exist_ok=True) if num == 0: print(f"{folder_prefix}: leeg.") continue status, data = mail.search(None, "ALL") if status != "OK": print(f"{folder_prefix}: zoeken mislukt – overgeslagen.") continue ids = data[0].split() num_to_fetch = sum(1 for uid in ids if not (local_dir / f"{uid.decode()}.eml").exists()) new = skip = err = 0 for msg_idx, uid in enumerate(ids, 1): path = local_dir / f"{uid.decode()}.eml" if path.exists(): skip += 1 continue done = new + err + 1 print(f"\r{folder_prefix}: bericht {done}/{num_to_fetch} ", end="", flush=True) try: status, msg_data = mail.fetch(uid, "(RFC822)") if status == "OK" and msg_data and msg_data[0]: path.write_bytes(msg_data[0][1]) new += 1 else: err += 1 except Exception: err += 1 total_new += new total_skip += skip total_err += err parts = [f"{new} nieuw", f"{skip} al aanwezig"] if err: parts.append(f"{err} fout") print(f"\r{folder_prefix}: " + ", ".join(parts) + " ") mail.logout() print(f"\nKlaar. {total_new} gedownload, {total_skip} overgeslagen", end="") if total_err: print(f", {total_err} fouten", end="") print(f".\nOpgeslagen in: {LOCAL_DIR.resolve()}") if __name__ == "__main__": LOCAL_DIR.mkdir(exist_ok=True) download()