eb53bc123a
Prompt since previous commit: execute step 1 Centralized route targets, source-folder policy, and modified UTF-7 mailbox quoting. Verification: py_compile, route/folder consistency, and git diff --check passed.
115 lines
3.3 KiB
Python
115 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Download alle e-mails van een IMAP-account naar lokale .eml-bestanden.
|
||
Gebruik: python download_mailbox.py
|
||
|
||
Resultaat: mailbox/<mapnaam>/<id>.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
|
||
from imap_utils import list_folders, quote_mailbox
|
||
|
||
IMAP_HOST = "australius.nl"
|
||
IMAP_PORT = 993
|
||
LOCAL_DIR = Path(__file__).parent / "mailbox"
|
||
|
||
|
||
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")
|
||
|
||
folders = list_folders(mail)
|
||
if not folders:
|
||
print("Kan mappenlijst niet ophalen.")
|
||
sys.exit(1)
|
||
|
||
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}"
|
||
|
||
status, data = mail.select(quote_mailbox(folder), 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()
|