# inbox_full_sync_v1.1

**Název:** inbox_full_sync_v1.1.py  
**Verze:** 1.1.0  
**Datum:** 2026-06-08  
**Autor:** vladimir.buzalka  

---

## Účel

Jednorázový skript pro úplný přenos **Inboxu i Sent Items** 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 rekurzivně obě výchozí složky včetně všech podsložek:
   - **Inbox** — `GetDefaultFolder(6)`
   - **Sent Items** — `GetDefaultFolder(5)`
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

Složky k synchronizaci jsou v konstantě `SYNC_FOLDERS = [(6, "Inbox"), (5, "Sent Items")]`.

**Online Archive se nepřenáší** — `GetDefaultFolder(5/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` |
| `SYNC_FOLDERS` | `[(6, "Inbox"), (5, "Sent Items")]` |

---

## 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 (Inbox i Sent Items podstrom) |
| `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 + kořenová složka (Inbox / Sent Items) |
| `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 |
| 1.1.0 | 2026-06-08 | Synchronizace i složky **Sent Items** (`GetDefaultFolder(5)`) vedle Inboxu |
