62 lines
11 KiB
Markdown
62 lines
11 KiB
Markdown
---
|
||
name: project-mailstore
|
||
description: "MailStore Server na 192.168.1.53 — archiv emailů, Management API, IMAP přístup, Claws Mail klient"
|
||
metadata:
|
||
node_type: memory
|
||
type: project
|
||
originSessionId: 49cbd8a2-c71e-49be-8c52-59dfa5ac7680
|
||
---
|
||
|
||
MailStore Server v26.2.1.24065 na `192.168.1.53` (hostname MAILSTORE, Win). Archiv ~2,3 mil emailů, data na `Z:\MailArchive`. Největší schránka vladimir.buzalka@buzalka.cz: 1 077 799 zpráv / 273 GB.
|
||
|
||
**Přístupy:**
|
||
- Windows admin (WinRM): `administrator` / `Vlado7309208104++`. WinRM remoting funguje z U:/janssen PC (TrustedHosts nastaveno).
|
||
- MailStore admin: `admin` / `*$N(B)vMUym!%`
|
||
|
||
**Management API (HTTPS, port 8463):** zapnuté v configu `MailStoreServer.json` (`API via HTTPS Configuration.Enabled=true`). Volá se `POST https://192.168.1.53:8463/api/invoke/<Funkce>`, Basic Auth, parametry jako **form body** (`application/x-www-form-urlencoded`), ne JSON. Self-signed cert → `-SkipCertificateCheck`. Async operace vrátí `token`+`statusCode=running`, výsledek se poluje přes `POST /api/get-status` (params `token`, `lastKnownStatusVersion`, `millisecondsTimeout`); `result` je v poslední odpovědi po `succeeded`. ~90 funkcí (GetUsers, GetStores, GetMessages, GetChildFolders, GetFolderStatistics, RunProfile, CreateBackup…). Dokumentace: help.mailstore.com/en/server/Administration_API_-_Function_Reference. GetMessages chce přesnou cestu složky (např. `vladimir.buzalka@buzalka.cz/Exchange vladimir.buzalka/Sent Items`).
|
||
|
||
**IMAP (port 143, STARTTLS):** zapnuté v configu (`IMAP Server Configuration.Enabled=true`). Po STARTTLS server nabízí jen `AUTH=PLAIN`, ale prostý IMAP `LOGIN` command funguje (Python imaplib.login OK, curl `--ssl-reqd` OK). Jako admin vidět všechny archivy. Lze stáhnout raw EML konkrétní zprávy.
|
||
|
||
**Claves Mail (Windows) klient:** Metoda autentizace MUSÍ být **"Prostý text"** (= prostý LOGIN command). "PLAIN"/"LOGIN"/"Automaticky" selhávají — Claws/libetpan na Windows je **bez SASL pluginů** ("PLAIN" → "Bad arguments", "LOGIN" → chybějící SASL plugin). Nastavení: server 192.168.1.53:143, STARTTLS, auth "Prostý text", admin / heslo. Na první zobrazení složek nutno "Obnovit strom složek" → Ano.
|
||
|
||
**Bezpečnost:** port 8463 ani 143 NEjsou forwardované na MikroTiku (192.168.1.2), přístup jen z LAN. MikroTik API na 8728 (admin/Vlado9674+).
|
||
|
||
**Nástroje v `U:/janssen/mailstore/`** (ruční prohlížeč archivu, schránka→složka→zpráva, spouštět `.venv\Scripts\python.exe`):
|
||
- `mailstore_map_v1.0.py <schránka>` — strom složek z API GetChildFolders (+`--no-stats`, `--list`). Arg = top-level složka (např. `vladimir.buzalka@buzalka.cz`).
|
||
- `mailstore_folder_v1.0.py "<plná cesta složky>"` — seznam zpráv (datum|od|předmět) přes dávkový IMAP FETCH hlaviček (+`--limit N`, `--all`, `--oldest`).
|
||
- `mailstore_read_v1.0.py "<složka>" <číslo>` — plný obsah jedné zprávy (hlavičky, tělo, přílohy) přes IMAP FETCH RFC822 (+`--uid`, `--save DIR`, `--raw`).
|
||
|
||
**Ingest do Mongo — `mailstore_ingest_v1.0.py <schránka> --since ROK [--dry-run] [--folder X] [--limit N]`**: backfill staré historie z MailStore do Mongo kolekce `emaily`. Dedup podle internet Message-ID (= `_id` v Mongu, shoduje se 1:1 s IMAP hlavičkou). Filtr data client-side z DATE headeru (NE IMAP SEARCH). Schéma dokumentu = jako Graph import. `--dry-run` spočítá kolik chybí bez zápisu. PILOT OVĚŘEN end-to-end 2026-06-11: MailStore IMAP → ingest → Mongo → enrich_fulltext → PG → MCP emaily search našel zprávu z 2020. Header scan ~490 zpráv/s (1M ≈ 30 min). vladimir.buzalka@buzalka.cz: Sent Items má 20k zpráv 2020+ k dobrání (i odeslané chybí z Graphu!). Plán: roztáhnout celou schránku, pak `--since` hlouběji do minulosti.
|
||
|
||
**STAV 2026-06-13: backfill 2019+2020+ KOMPLETNÍ.** Mongo kolekce `vladimir.buzalka@buzalka.cz`: 332 204 zpráv (z toho 256 808 z mailstore), PG fulltext 100 % (`pg_indexed=mongo_total`). 2019 dobrán samostatným během `--since 2019 --until 2019` s **vlastním checkpointem** `ingest_done_2019.txt` (stávající checkpoint 2020+ by 2019 minul — přeskočí složky před scanem!). Pozn.: `mailstore_uid` v dokumentech je ve skutečnosti **sekvenční číslo** (ne IMAP UID), fetch přes `M.fetch(seq,'(RFC822)')` + kontrola Message-ID.
|
||
|
||
**Přílohy → SeaweedFS (PoC, [[project-seaweedfs]]):** `mailstore_attachments_poc.py` — re-fetch EML přes IMAP, přílohy do Fileru `192.168.1.50:8888` (PUT raw), dedup SHA-256, write-back pole `seaweed_attachments[]` (filename, sha256, seaweed_url) + marker `seaweed_synced_at`. Dávkový samostránkující režim (NE jeden dlouhý kurzor — `CursorNotFound` po hodině!). 88 930 mailů s přílohami 100 % hotovo, 0 failed; SeaweedFS 72k objektů / 27 GB. **Drift sekvencí** u živých složek (Sent Items, Odeslaná pošta — dostávaly poštu během ingestu) → `--remap-failed` režim: naskenuje mapu Message-ID→aktuální seq a dofetchne správně. Běží z toweru přes `_run_poc.py` (`_run_ingest_2019.py` pro 2019 ingest).
|
||
|
||
**Běh na serveru (python-runner kontejner na Unraidu .76):** skript v `/mnt/user/Scripts/MailStore/` (deploy přes paramiko SFTP `_deploy.py`, SSH root@192.168.1.76 heslo `7309208104`). Kontejner má pymongo, dosáhne na MailStore .53 i Mongo .76. **DŮLEŽITÉ: Unraid agresivně zabíjí odpojené procesy** — `docker exec -d`, `nohup &`, `setsid` (host i kontejner) VŠECHNY selžou (i prostý `sleep 60` zmizí; SSH session cleanup zabije celý user slice; screen/tmux/at nejsou). Jediné co funguje: **blokující `docker exec` držený aktivním spojením** (paramiko z PC v background tasku, `_run_ingest.py`). Ingest je **idempotentní** (dedup Message-ID + `$setOnInsert`) → přerušení (notebook usne) nevadí, příští běh dobere zbytek.
|
||
|
||
**Velký backfill 2026-06-12 (vladimir.buzalka@buzalka.cz --since 2020) — DOKONČEN: 168 364 zpráv z mailstore v Mongo** (kolekce celkem 243 607). Cestou vyřešeno + zpevněno ve skriptu (v aktuální verzi ~20kB):
|
||
- **ROOT CAUSE celého dne (zjištěno až nakonec): plný disk C:.** MailStore měl v configu `"IMAP Server Connection Debug Log Enabled": true` → náš těžký IMAP provoz (FETCH celých těl) vygeneroval za den **65 GB Connection debug logů** do `C:\ProgramData\MailStore\Debug Log\Connection\` (jednotlivé soubory 10-35 GB!). C: (jen 99 GB) se zaplnil na 0 → Firebird story na Z: házely `Unable to open the archive store ... Code 335544373 SetFilePointer failed`, IMAP wedgoval pod zátěží (nešlo psát temp/zámky), a po restartu story nešly mountnout (API GetChildFolders=0 pro VŠECHNY schránky, GetStores ukázal chyby). **Fix: vypnout Connection debug log** (config `MailStoreServer.json` v `C:\Program Files (x86)\MailStore\MailStore Server\`, hodnotu na `false`, stop/edit/start; záloha `.bak_20260613`) + **smazat logy** (`C:\ProgramData\MailStore\Debug Log\Connection\*` — pozor: harness blokuje `Remove-Item` na ProgramData, použij `Get-ChildItem | %{$_.Delete()}`). Po smazání 65 GP uvolněno, restart → story OK, 1795 složek, archiv online. **Diagnostika: `_store_status.py` (GetStores přes API, POST i bez params = `data=b""`, dekóduj `utf-8-sig` kvůli BOM).**
|
||
- **MailStore IMAP se pod zátěží ZASEKNE NATVRDO** (`abort: command: FETCH/CAPABILITY/EXAMINE => socket error: EOF`) — primárně to byl důsledek plného C: výše. Port 143 přijme TCP, ale server spojení hned utne — i z PC. **Probudí ho JEN restart služby `MailStoreServer`** (retry nepomůže). Restart přes WinRM: `Restart-Service -Name MailStoreServer -Force` (admin `administrator`/`Vlado7309208104++`, TrustedHosts OK). Po wedgi 0 established spojení, služba "Running" — zaseklé je IMAP vlákno gateway. **Při dalším velkém ingestu HLÍDAT volné místo na C:!** (s vypnutým debug logem by problém neměl nastat).
|
||
- Po wedgi **login projde, ale FETCH hned EOFne** → skript dělal kaskádu falešných přeskoků a vracel falešné rc=0. Fix: čítač `consec_aborts`, po **4 abortech v řadě `return 2`** → orchestrátor pozná wedge.
|
||
- **`coll.distinct("_id")` překročí 16MB cap** u velké kolekce → nahrazeno kurzorem `find({},{_id:1}).batch_size(5000)`.
|
||
- `imap_connect()` má retry (6×5s) na abort/error/OSError.
|
||
- **`--checkpoint FILE`** (hotové složky, jedna cesta/řádek) → po wedgi další běh přeskočí hotové BEZ FETCH (rychlé navázání). Složka se zapíše až po úplném dokončení; abort během fetche ji NEoznačí.
|
||
- **Orchestrátor `_orchestrate.ps1`**: smyčka run ingest → rc≠0 → `Restart-Service` MailStore přes WinRM → čekej až IMAP odpoví (`_imap_test.py`) → zkus znovu. Konec na rc=0. Konverguje díky checkpointu.
|
||
- **HEADER_BATCH snížen 2000→500** (šetrnější).
|
||
- **Dvě obří složky (Odstraněná 170k, Doručená 47k) jdou re-scanovat jen na čerstvém MailStore — jinak deterministicky wedgnou na 1. FETCH.** Přijaty jako hotové ~99 % (Odstraněná 14 637/14 728, Doručená 2 666/2 719; data zapsaly dřívější běhy) a ručně seednuty do checkpointu (`_seed_checkpoint.py`). Zbývá ~150 stragglerů + 2 maličké složky (`_OPTUM_PATROc`, `27646` — v Mongu 0) na pozdější šetrný doběh.
|
||
- **PO forced restartu Management API (8463) chvíli vrací 0 složek** (GetChildFolders/collect_folders = 0) — MailStore mountuje index obří schránky (273 GB) minuty. Opakované forced restarty počet složek degradovaly 1795→1507→0. **Nehammrovat restarty**; nechat MailStore dosednout. collect_folders=0 → běh nemá co dělat → falešné rc=0 (pozor v orchestraci).
|
||
|
||
Pro denní udržování plánováno: Unraid User Scripts plugin nebo python-runner cron (nezávislé na SSH) + sync_state (UID watermark). Pomocné skripty v `mailstore/`: `_run_ingest.py`, `_orchestrate.ps1`, `_status_check.py`, `_mongo_count.py`, `_tail_log.py`, `_checkpoint_diff.py`, `_imap_test.py`, `_seed_checkpoint.py`, `_deploy.py`, `_folder_coverage.py`.
|
||
|
||
vladimir.buzalka@buzalka.cz má **1795 složek** (hluboká struktura #Innopharma/!Zpracovat/@Zpracovat po studiích). Velké: Odstraněná pošta 170k, Sent Items 63k, Doručená pošta 47k. Header scan ~490 zpráv/s (velká složka ~2-4 min).
|
||
|
||
**Tři gotchas (vyřešené):**
|
||
0. IMAP názvy složek s diakritikou (Doručená pošta) musí být v **modified UTF-7** (RFC 3501) — MailStore neumí UTF8=ACCEPT. `encode_mutf7()` ve všech 3 IMAP skriptech. A nestandardní charsety hlaviček/těl (`unknown-8bit`) shazují `bytes.decode` → `_safe_decode()` s fallbackem utf-8/latin-1.
|
||
1. Kolekce `emaily` má unique+sparse index na `graph_id`. MailStore dokument musí pole `graph_id` ÚPLNĚ VYNECHAT (ne `None`) — explicitní null koliduje (sparse ignoruje jen chybějící pole). Jinak E11000 duplicate key.
|
||
2. Mongo `{'graph_id': None}` matchuje i dokumenty BEZ pole — `delete_many` tím smete i validní dokumenty. Pozor při úklidu.
|
||
3. enrich_fulltext spouštět přes `U:/janssen/.venv/Scripts/python.exe` (system Python C:\Python312 nemá psycopg).
|
||
|
||
IMAP SEARCH je slepá ulička (78s, vrací jen ~10 výsledků). API GetMessages dává jen metadata (id, date, uid1=Message-ID, outgoing), ne obsah — obsah jen přes IMAP. API `id` (1:947923) ≠ IMAP UID, most je Message-ID (=uid1).
|
||
|
||
Pracovní adresář: `U:/janssen/mailstore/`. Pozn.: [[feedback-admin-powershell]] — admin příkazy (winget) rovnou psát uživateli.
|