# msgreceiver — deployment instrukce ## Soubory - Zdrojový skript: `U:\PythonProject\Janssen\EmailsImport\DockerCustomApp\app.py` - Network share: `\\tower\appdata\msgreceiver\app.py` - Unraid cesta: `/mnt/user/appdata/msgreceiver/` ## Přihlašovací údaje - **Unraid SSH:** `root@192.168.1.76`, heslo: `7309208104` - **Docker kontejner:** `msgreceiver` ## Postup při nové verzi app.py ### 1. Zkopírovat app.py na server ```powershell Copy-Item "U:\PythonProject\Janssen\EmailsImport\DockerCustomApp\app.py" "\\tower\appdata\msgreceiver\app.py" -Force ``` ### 2. Připojit se přes SSH a přebuildovat Docker (přes Python paramiko) ```python import paramiko c = paramiko.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect('192.168.1.76', username='root', password='7309208104') # Build _, stdout, stderr = c.exec_command('docker build -t msgreceiver /mnt/user/appdata/msgreceiver/ 2>&1') print(stdout.read().decode()) # Restart _, stdout, stderr = c.exec_command('docker restart msgreceiver') print(stdout.read().decode()) c.close() ``` > Poznámka: `sshpass` není na tomto Windows stroji k dispozici, Windows OpenSSH neumí neinteraktivní heslo — proto vždy použij **paramiko**. ## Struktura adresáře na serveru ``` /mnt/user/appdata/msgreceiver/ ├── Dockerfile ├── app.py ├── requirements.txt └── .env ← Dropbox credentials ``` ## Dropbox konfigurace (.env) Proměnné načítané z `.env`: - `DROPBOX_APP_KEY` - `DROPBOX_APP_SECRET` - `DROPBOX_APP_REFRESH_TOKEN` Upload cesta v Dropboxu: `/!!!Days/Downloads Z230/{filename}` ## API endpointy Bearer token: `13e1bb01-9fd5-44a8-8ce9-4ee27133d340` | Endpoint | Přijímá | Chování | |---|---|---| | `POST /upload` | `.msg` / `.emsg` | `.emsg` Fernet dešifruje → uloží `.msg` do `/msgs`, přeskočí pokud existuje; volitelně import do Graphu. **v2.4:** form pole `overwrite=1` → existující `.msg` **přepíše** (re-upload změněného e-mailu z `jnj_mailbox_sync >= v1.3`); při overwrite se Graph re-import nedělá | | `POST /upload-db` | `.db` / `.db.xz.enc` | **v2.1:** `.db.xz.enc` Fernet dešifruje + lzma rozbalí → plain `.db`; pak smaže staré `.db` v `/msgs/db` a uloží. Plain `.db` bere i nadále (zpětná kompatibilita) | | `POST /upload-dropbox` | cokoliv | Nahraje do Dropboxu (overwrite) | > **v2.1 (2026-06-10):** `/upload-db` umí komprimovanou+šifrovanou DB (`.db.xz.enc`) > od `jnj_mailbox_sync >= v1.2`. Staré `.db` se smažou **až po** úspěšném > dešifrování/rozbalení (při chybě zůstane poslední dobrá DB). Vyžaduje `lzma` > (stdlib) — ověřeno v kontejneru. Nasazení = jen restart (app.py je bind-mount), > bez rebuildu. > **v2.4 (2026-06-16):** `/upload` — nové form pole `overwrite=1`. Když `.msg` > už v `/msgs` existuje, místo `{"status":"exists"}` ho **přepíše** a vrátí > `{"status":"overwritten"}`. Bez pole zůstává původní idempotentní skip (žádná > regrese). Slouží pro re-upload **změněného** e-mailu z `jnj_mailbox_sync >= v1.3` > (detekce změny obsahu — např. dopsaná chyba `SendAsDenied` do neodeslané Sent > položky). Při overwrite se **Graph re-import nedělá** (klient posílá `folder=""`, > takže nevznikne duplikát v Graph zrcadle); přepsaný soubor má novější mtime → > Tower (`jnj_tower_ingest`) ho přeparsuje a upsertne dokument v Mongu dle `_id`. > Nasazení = jen `docker restart` (bind-mount). > **v2.3 (2026-06-10):** `/item/{token}` — při `Accept: application/json` > (klient `janssenpc_file_receive >= v1.2`) vrací `{"data": ""}` > místo binární přílohy. Důvod: JNJ filtr (Zscaler/SiteMinder) blokoval binární > downloady — zachytil odpověď, replay GET bez auth (401 v logu) a klientovi > vrátil 403 + `?_sm_nck=1`. JSON inspekci příloh nespouští. Bez `Accept` > hlavičky zůstává binární režim (zpětná kompatibilita s v1.1). > **v2.2 (2026-06-10):** `/item/{token}` — oprava 500 u souborů s ne-ASCII znaky > ve jméně (např. `▲▲...pdf`): `Content-Disposition` je nyní ASCII fallback + > RFC 5987 `filename*` (HTTP hlavičky jsou latin-1, `▲` shazoval Response na > UnicodeEncodeError). Zároveň se přesun do `##Trash` dělá až PO sestavení > odpovědi — pád už neodstraní soubor z fronty. Klient (`janssenpc_file_receive`) > hlavičku nečte, žádná změna na JNJ straně není potřeba. > **Pozn. k nasazení:** `app.py` je bind-mountovaný (`/mnt/user/appdata/msgreceiver` → `/app`), > takže pro změnu KÓDU stačí přepsat soubor + `docker restart msgreceiver`. > `docker build` je potřeba jen při změně `requirements.txt`.