5.5 KiB
jnj_mailbox_sync v1.5.0
Soubor: jnj_mailbox_sync_v1.5.py
Datum: 2026-06-16
Autor: vladimir.buzalka
Běží: JNJ stroj (Outlook MAPI), Python z Thonny.
Co to je
Synchronizace JNJ Outlooku (MAPI) → osobní schránka (přes msgreceiver) + bookkeeping
v SQLite (C:\Users\vbuzalka\SQLITE\jnjemails.db). Sleduje přesuny e-mailů mezi
složkami a příznak „už není ve schránce" — bez opětovného přenosu těla.
Skenované složky: Inbox + Sent Items + Deleted Items + Archive (vč. podsložek).
Novinka v1.5 — provenance verze skriptu na úrovni entry
Do tabulky messages přidány dva sloupce (jen pro náhled, Tower je nezpracovává —
nejsou v mirroru do jnj_messages):
| Sloupec | Význam |
|---|---|
captured_by_version |
verze skriptu, která entry poprvé zachytila/odeslala (set při INSERT) |
last_upload_version |
verze, která naposledy re-uploadla tělo (set při INSERT i při re-uploadu) |
Smysl: kdykoliv se podívat (jnjemails SQL), kterou verzí byl daný e-mail přenesen.
Pravidlo: při jakékoliv změně skriptu vždy bumpni verzi (SCRIPT_VERSION) — jinak
tahle stopa ztrácí smysl. Migrace přes ALTER TABLE (staré řádky = NULL).
Novinka v1.4 — skenování složky Archive (primární schránka)
Přidána složka Archive (jednoklikové archivování v Outlooku) v primární schránce.
Archive není default folder, takže se hledá podle jména "Archive" pod kořenem
primární schránky (Inbox.Parent) a přidává se do scanned_roots (aby se její položky
nehodnotily jako „opustilo schránku"). Online Archive (samostatný store) se i nadále
neskenuje. Řeší případy, kdy odeslaná kopie skončila v Archive (jinak chyběla domácímu
přehledu i párování dvojčat).
Novinka v1.3 — detekce změny obsahu (re-upload změněného e-mailu)
Problém: e-mail bez Message-ID (typicky NEODESLANÝ Sent kvůli SendAsDenied,
nebo čerstvě odeslaný, kde Exchange ještě nedoplnil Message-ID) má stabilní EntryID.
Když do něj Outlook po zachycení dopíše chybu odeslání, obsah se změní, ale identita
(entryid:<EID>) zůstane → starý sync to vyhodnotil jako „známé, beze změny" a
aktualizovaný (chybový) e-mail už domů nepřenesl. Naproti tomu úspěšně odeslaný
e-mail dostane nové EntryID + Message-ID, takže se zachytil jako nový. Vznikla
asymetrie: failed-update se ztrácel.
Řešení: identita zůstává (Message-ID / entryid:), ale navíc se sleduje verzní otisk
= PR_LAST_MODIFICATION_TIME (0x30080040). U známé položky bez Message-ID
(mid začíná entryid:) se otisk porovná; když se posunul, e-mail se znovu uloží
(SaveAs) a nahraje s overwrite=1 → server přepíše původní .msg na místě → Tower ho
přeparsuje → dokument v Mongu se aktualizuje (vč. těla s chybou).
- Hlídání je levné — druhé čtení property jen u známých no-ID položek (desítky kusů); položky s Message-ID jsou finalizované a nesledují se.
- Re-upload běží jen v režimech, které smějí nahrávat (capture, full-update), a posílá se
s
folder=""→ server nedělá Graph re-import (žádný duplikát v Graph zrcadle). - Vyžaduje msgreceiver app.py ≥ v2.4 (overwrite na
/upload). Bez něj se re-upload chová jako starý skip (nepřepíše, ale nic nerozbije) — pořadí nasazení server → JNJ bez výpadku.
Nové sloupce SQLite
messages.last_mod_time— PR_LAST_MODIFICATION_TIME při posledním zachycení (otisk).messages.content_uploads— kolikrát se tělo nahrálo (1 = jen první zachycení).runs.content_updated— kolik e-mailů se v běhu re-uploadlo kvůli změně obsahu.
(Migrace přes stávající ALTER TABLE smyčku — staré jnjemails.db se doplní automaticky.)
Argumenty
--mode {capture,update-paths,full-update} (default capture), --days N
(0 = celé), --dry-run, --limit N, --no-db-upload.
Spouštění (JNJ stroj, plné cesty)
"C:\Users\vbuzalka\AppData\Local\Programs\Thonny\python.exe" "c:\Users\vbuzalka\OneDrive - JNJ\##JNJPrenos\Python\jnj_mailbox_sync_v1.5.py" --mode full-update --days 60
full-update --days 60 = dorovná chybějící + re-uploadne změněné (chybové) Sent položky
za poslední 60 dní. To je doporučený běh pro „aktualizovat i neodeslané".
Revert
Stará verze: Trash/jnj_mailbox_sync_v1.4.py (bez provenance sloupců),
…_v1.3.py (bez skenování Archive), …_v1.2.py (bez detekce změny). Server v2.4
zůstává zpětně kompatibilní (overwrite je opt-in), takže revert na JNJ straně
nevyžaduje zásah na serveru.
Historie
- 1.0.0 — režimy capture/update-paths/full-update, sledování přesunů, updated_at.
- 1.1.0 — + Deleted Items do skenovaných složek.
- 1.2.0 — upload SQLite komprimován (lzma/xz max) + šifrován (Fernet) →
.db.xz.enc. - 1.3.0 — + detekce změny obsahu přes
PR_LAST_MODIFICATION_TIME: známé no-ID položky, které se po zachycení změnily (např. dopsaná chybaSendAsDenied), se znovu nahrávají soverwrite=1. Nové sloupcelast_mod_time,content_uploads,runs.content_updated. Vyžaduje app.py ≥ v2.4. - 1.4.0 — + skenování složky Archive v primární schránce (hledá se podle jména pod kořenem schránky, ne přes default folder; Online Archive se neskenuje).
- 1.5.0 — + provenance verze na úrovni entry: sloupce
captured_by_versionalast_upload_version(jen náhled, Tower nezpracovává).