# inbox_full_sync_v1.0 **Název:** inbox_full_sync_v1.0.py **Verze:** 1.0.4 **Datum:** 2026-06-01 **Autor:** vladimir.buzalka --- ## Účel Jednorázový skript pro úplný přenos Inboxu z JNJ Outlooku (MAPI) do osobní schránky `vladimir.buzalka@buzalka.cz` přes Microsoft Graph API. Spouštět ručně jako záchranná síť nebo iniciální sync. Bezpečné opakovat — duplicity se automaticky přeskočí. --- ## Co dělá 1. Připojí se k Outlooku přes MAPI (`win32com`) 2. Projde celý **Inbox** včetně všech podsložek rekurzivně 3. Pro každý email zkontroluje SQLite DB — pokud už je přenesen, přeskočí ho 4. Nový email uloží jako `.msg` do temp složky, **zašifruje** (Fernet/AES) a odešle jako `.emsg` na `msgs.buzalka.cz/upload` 5. Server (`app.py`) dešifruje, parsuje `.msg`, importuje do Graph API a vrátí `graph_id` 6. Záznam se uloží do DB (`messages`, `log`) 7. Každých 100 přenesených emailů + na konci uploaduje DB na server **Online Archive se nepřenáší** — `GetDefaultFolder(6)` vrátí pouze primární schránku. --- ## Šifrování (Zscaler bypass) JNJ síť používá **Zscaler DLP** — blokuje upload souborů s medicínským obsahem (ECG reporty, klinická data) na externí URL. Řešení: soubor se před odesláním zašifruje pomocí **Fernet** (AES-128 CBC + HMAC). Zscaler vidí pouze šifrovaný bináč a nerozpozná obsah. - Šifrovací klíč se odvozuje z `TOKEN` přes SHA-256 — žádná extra konstanta, obě strany derivují klíč samostatně - Soubor se odesílá s příponou `.emsg` místo `.msg` - Server (app.py v1.6+) automaticky detekuje `.emsg`, dešifruje a dále zpracuje standardně --- ## Konfigurace Konstanty jsou přímo v kódu: | Konstanta | Hodnota | |---|---| | `TOKEN` | Bearer token pro msgs.buzalka.cz (slouží i jako základ šifrovacího klíče) | | `UPLOAD_URL` | `https://msgs.buzalka.cz/upload` | | `DB_UPLOAD_URL` | `https://msgs.buzalka.cz/upload-db` | | `DB_PATH` | `C:\Users\vbuzalka\SQLITE\jnjemails.db` | | `LOG_PATH` | `C:\Users\vbuzalka\SQLITE\inbox_full_sync_errors.log` | --- ## Závislosti - Python 3.10+, Windows - Outlook musí být spuštěn - `pywin32`, `requests`, `cryptography` - Server `msgs.buzalka.cz` musí běžet (app.py v1.6+) --- ## SQLite DB (`jnjemails.db`) ### Tabulka `messages` Jeden záznam na každý přenesený email. | Sloupec | Popis | |---|---| | `message_id` | Internet Message-ID (nebo `entryid:...` jako fallback) | | `entry_id` | Outlook EntryID — pro zpětné dohledání v MAPI | | `graph_id` | ID zprávy v Graph API — pro sync operace | | `is_read` | Stav přečtení při přenosu (0/1) | | `jnj_folder` | Složka v JNJ při přenosu | | `source` | Vždy `inbox_full_sync` | ### Tabulka `runs` Jeden záznam na každý běh skriptu. | Sloupec | Popis | |---|---| | `script` | `inbox_full_sync` | | `version` | verze skriptu | | `started_at` / `finished_at` | časy běhu | | `transferred` | počet nově přenesených emailů | | `skipped` | počet přeskočených (již v DB) | | `errors` | počet chyb | ### Tabulka `log` Flat event log — každý console výstup i interní událost jako řádek. | Sloupec | Popis | |---|---| | `run_id` | FK na `runs.id` | | `level` | `INFO` / `ERROR` | | `event` | typ události (viz níže) | | `subject` | předmět emailu (pokud relevantní) | | `folder` | složka (pokud relevantní) | | `graph_id` | Graph ID (pokud relevantní) | | `detail` | pro `upload_saved`: `size=XKB`; pro `upload_error`: `error=... \| size=XKB \| body=... \| sender=... \| received=... \| entry_id=... \| message_id=...` | #### Události (`log.event`) | Event | Popis | |---|---| | `run_start` | start skriptu | | `mailbox` | název schránky | | `folder_start` | vstup do složky (detail = počet položek) | | `folder_done` | konec složky (detail = přeneseno/skip) | | `upload_saved` | nový email úspěšně přenesen (detail = size=XKB) | | `upload_exists` | email již v DB, přeskočen | | `upload_error` | chyba při uploadu — detail obsahuje sender, received, entry_id, message_id pro dohledání v Outlooku | | `progress` | každých 100 přenesených emailů | | `db_upload` | úspěšný upload DB na server | | `db_upload_error` | chyba uploadu DB | | `run_done` | konec skriptu (detail = souhrn) | --- ## Užitečné dotazy **Poslední běh — kompletní log:** ```sql SELECT r.script, r.version, r.started_at, l.level, l.event, l.subject, l.folder, l.detail, l.created_at FROM log l JOIN runs r ON r.id = l.run_id WHERE l.run_id = (SELECT MAX(id) FROM runs) ORDER BY l.created_at ``` **Přehled všech běhů:** ```sql SELECT id, script, version, started_at, finished_at, transferred, skipped, errors FROM runs ORDER BY started_at DESC ``` **Chyby z posledního běhu:** ```sql SELECT l.event, l.subject, l.folder, l.detail, l.created_at FROM log l WHERE l.run_id = (SELECT MAX(id) FROM runs) AND l.level = 'ERROR' ORDER BY l.created_at ``` --- ## Návaznost - Sdílí DB s `janssenpc_email_send_new_v1.5.py` — záznamy jsou kompatibilní - Emaily přenesené tímto skriptem mají `graph_id` a jsou od té chvíle hlídány sync průchodem v1.5 - Server endpoint: `msgs.buzalka.cz/upload` musí vracet `graph_id` (app.py v1.6+) - nginx `client_max_body_size` nastaven na **200M** (SWAG `msgreceiver.subdomain.conf`) --- ## Historie verzí | Verze | Datum | Změna | |---|---|---| | 1.0.0 | 2026-06-01 | Základní funkce: Inbox full scan, dedup přes DB, entry_id/graph_id/is_read | | 1.0.1 | 2026-06-01 | DB upload každých 100 emailů + finální upload | | 1.0.2 | 2026-06-01 | SQLite tabulky runs + log | | 1.0.3 | 2026-06-01 | Kompletní konzolový výstup zrcadlen do log tabulky, skipped counter | | 1.0.4 | 2026-06-01 | Šifrování Fernet (.emsg) pro bypass Zscaler DLP; rozšířený error detail (sender/received/entry_id/size) |