notebook
This commit is contained in:
+133
-25
@@ -48,20 +48,32 @@ c.close()
|
||||
|
||||
---
|
||||
|
||||
## Aktuální skripty v /scripts
|
||||
## Pipeline — 5 skriptů v pořadí spouštění
|
||||
|
||||
| Soubor | Popis |
|
||||
|---------------------------------|--------------------------------------------------------------|
|
||||
| `parse_emails_graph_v1.3.py` | Import emailů ze schránky přes Graph API → MongoDB |
|
||||
| `download_attachments_v1.3.py` | Stažení skutečných příloh emailů (Graph API) → `/mnt/Emails` |
|
||||
| `python_runner.md` | Tato dokumentace |
|
||||
| `parse_emails_errors.log` | Log chyb (soubory/zprávy které selhaly) |
|
||||
Prefix `1_` … `5_` indikuje pořadí v pipeline. Bezpečné opakovat každý krok (idempotentní upserty).
|
||||
|
||||
> **POZOR:** oba skripty pouze **čtou** ze schránky — žádný zápis do schránky.
|
||||
| # | Skript | Účel | Zdroj → Cíl |
|
||||
|---|---|---|---|
|
||||
| 1 | `1_parse_emails_graph_v1.4.py` | Import emailů z Graph API | Graph → Mongo `emaily.<mailbox>` |
|
||||
| 2 | `2_refetch_text_bodies_v1.0.py` | ONETIME oprava starých plain-text emailů (v1.3 ukládal jen 2000 znaků do `body_preview`) | Graph → Mongo `body_text` |
|
||||
| 3 | `3_download_attachments_v1.3.py` | Stažení binárek příloh + SHA256 dedup | Graph → `/mnt/Emails/<mailbox>/Attachments/` + Mongo `attachments_index` |
|
||||
| 4 | `4_unwrap_smime_v1.0.py` | Rozbalení S/MIME wrapper (`smime.p7m`) na vnitřní MIME tělo | Graph → Mongo `smime_body_text/html`, `smime_inner_attachments` |
|
||||
| 5 | `5_enrich_fulltext_emails_v1.2.py`| Plný text emailů do PG fulltext indexu | Mongo → PG `MongoEmaily.emails` |
|
||||
|
||||
Doplňkové soubory v `/scripts/`:
|
||||
|
||||
| Soubor | Popis |
|
||||
|---|---|
|
||||
| `python_runner.md` | Tato dokumentace |
|
||||
| `*.log` | Výstupy běhů (`parse_emails.log`, `download_attachments.log`, `unwrap_smime.log`, `refetch.log`) |
|
||||
| `*_errors.log` | Chyby konkrétních zpráv/příloh |
|
||||
| `Trash/` | Staré verze skriptů |
|
||||
|
||||
> **POZOR:** všechny skripty pouze **čtou** ze schránky — žádný zápis do schránky.
|
||||
|
||||
---
|
||||
|
||||
## Microsoft Graph API — konfigurace (v obou skriptech)
|
||||
## Microsoft Graph API — konfigurace (sdílená všemi skripty)
|
||||
|
||||
| Parametr | Hodnota |
|
||||
|-----------------|----------------------------------------|
|
||||
@@ -77,29 +89,35 @@ c.close()
|
||||
| Kolekce emailů | `<mailbox>` (např. `ordinace@buzalkova.cz`) |
|
||||
| Index příloh | `attachments_index` |
|
||||
|
||||
| PostgreSQL | Hodnota |
|
||||
|-----------------|----------------------------------------|
|
||||
| Host | `192.168.1.76` |
|
||||
| DB | `MongoEmaily` |
|
||||
| Tabulka | `emails` (GIN tsvector, config `soubory`) |
|
||||
|
||||
---
|
||||
|
||||
## 1) parse_emails_graph_v1.3.py — import emailů → MongoDB
|
||||
## 1) `1_parse_emails_graph_v1.4.py` — import emailů → MongoDB
|
||||
|
||||
Čte **všechny složky** schránky rekurzivně (Inbox, Sent, Deleted, archivy …) přes
|
||||
Graph API a importuje každou zprávu jako dokument do MongoDB. `_id` = Internet
|
||||
Message-ID (fallback `graphid:<id>`). Upsert → bezpečné přerušit a opakovat.
|
||||
|
||||
Z každé zprávy extrahuje: předmět, odesílatel, příjemci To/CC/BCC, časy (UTC),
|
||||
HTML tělo (max 2 MB) + text preview, přílohy (metadata + `graph_att_id`),
|
||||
internet headers (SPF/DKIM/Received/X-*), MAPI-ekvivalenty (důležitost, příznak,
|
||||
konverzační vlákno, kategorie, In-Reply-To, References), `isRead`, `isDraft`,
|
||||
`folder_path`, `inferenceClassification`.
|
||||
HTML tělo (max 2 MB) + text preview, **plné plain-text tělo (`body_text`, max 2 MB)**,
|
||||
přílohy (metadata + `graph_att_id`), internet headers (SPF/DKIM/Received/X-*),
|
||||
MAPI-ekvivalenty (důležitost, příznak, konverzační vlákno, kategorie,
|
||||
In-Reply-To, References), `isRead`, `isDraft`, `folder_path`, `inferenceClassification`.
|
||||
|
||||
```bash
|
||||
# První import (vše):
|
||||
docker exec -it python-runner python /scripts/parse_emails_graph_v1.3.py --mailbox ordinace@buzalkova.cz
|
||||
docker exec -it python-runner python /scripts/1_parse_emails_graph_v1.4.py --mailbox ordinace@buzalkova.cz
|
||||
|
||||
# Test na 50 zprávách bez indexů:
|
||||
docker exec -it python-runner python /scripts/parse_emails_graph_v1.3.py --mailbox ordinace@buzalkova.cz --limit 50 --no-indexes
|
||||
docker exec -it python-runner python /scripts/1_parse_emails_graph_v1.4.py --mailbox ordinace@buzalkova.cz --limit 50 --no-indexes
|
||||
|
||||
# Pravidelný sync na pozadí (log do souboru):
|
||||
docker exec -d python-runner bash -c "python /scripts/parse_emails_graph_v1.3.py --mailbox ordinace@buzalkova.cz --mode sync > /scripts/parse_emails.log 2>&1"
|
||||
docker exec -d python-runner bash -c "python /scripts/1_parse_emails_graph_v1.4.py --mailbox ordinace@buzalkova.cz --mode sync > /scripts/parse_emails.log 2>&1"
|
||||
```
|
||||
|
||||
> **`-d` = detached:** příkaz se hned vrátí a skript běží dál v kontejneru i po
|
||||
@@ -119,7 +137,23 @@ docker exec -d python-runner bash -c "python /scripts/parse_emails_graph_v1.3.py
|
||||
|
||||
---
|
||||
|
||||
## 2) download_attachments_v1.3.py — stažení příloh → /mnt/Emails
|
||||
## 2) `2_refetch_text_bodies_v1.0.py` — dohnání plain-text těl
|
||||
|
||||
**ONETIME oprava.** Starý `parse_emails_graph_v1.3` ukládal plain-text emaily
|
||||
jen jako prvních 2000 znaků do `body_preview` — plné tělo se zahazovalo.
|
||||
Tenhle skript v Mongo najde emaily kde `body_html` chybí a re-fetchne plné
|
||||
tělo z Graphu do nového pole `body_text` (max 2 MB).
|
||||
|
||||
```bash
|
||||
docker exec -d python-runner bash -c "python /scripts/2_refetch_text_bodies_v1.0.py --mailbox ordinace@buzalkova.cz > /scripts/refetch.log 2>&1"
|
||||
```
|
||||
|
||||
> Po importu schránky přes v1.4 už tenhle skript prakticky nemá co dělat
|
||||
> (kandidátů 0). Drží se kvůli archivním schránkám, které byly importovány v1.3.
|
||||
|
||||
---
|
||||
|
||||
## 3) `3_download_attachments_v1.3.py` — stažení příloh → /mnt/Emails
|
||||
|
||||
Stahuje skutečné přílohy (`is_inline=False`) všech emailů z MongoDB přes Graph API
|
||||
do `/mnt/Emails/<schránka>/Attachments/`. Primárně přes `graph_att_id` (přímé ID),
|
||||
@@ -135,15 +169,13 @@ mime_type, mailbox, first_seen_at, ref_count). Emaily kde mají všechny přílo
|
||||
`file_hash` se přeskočí → bezpečné opakovat.
|
||||
|
||||
```bash
|
||||
# Interaktivně (vidíš výstup, skončí zavřením terminálu):
|
||||
docker exec -it python-runner python /scripts/download_attachments_v1.3.py --mailbox ordinace@buzalkova.cz
|
||||
# Interaktivně:
|
||||
docker exec -it python-runner python /scripts/3_download_attachments_v1.3.py --mailbox ordinace@buzalkova.cz
|
||||
|
||||
# Na pozadí (běží dál i po zavření terminálu, log do souboru):
|
||||
docker exec -d python-runner bash -c "python /scripts/download_attachments_v1.3.py --mailbox ordinace@buzalkova.cz > /scripts/download_attachments.log 2>&1"
|
||||
# Na pozadí:
|
||||
docker exec -d python-runner bash -c "python /scripts/3_download_attachments_v1.3.py --mailbox ordinace@buzalkova.cz > /scripts/download_attachments.log 2>&1"
|
||||
```
|
||||
|
||||
> `-d` = detached — stejné chování jako u skriptu výše (viz poznámka v sekci 1).
|
||||
|
||||
### Parametry
|
||||
|
||||
| Parametr | Popis |
|
||||
@@ -155,10 +187,82 @@ docker exec -d python-runner bash -c "python /scripts/download_attachments_v1.3.
|
||||
|
||||
---
|
||||
|
||||
## 4) `4_unwrap_smime_v1.0.py` — rozbalení S/MIME zpráv
|
||||
|
||||
Některé emaily (Datová schránka, mBank, ComGate, PayU, PostSignum …) přicházejí
|
||||
jako S/MIME signed-data wrapper: viditelné tělo je jen *"This is an S/MIME
|
||||
signed message"*, skutečný obsah je zabalený uvnitř přílohy `smime.p7m`.
|
||||
|
||||
Skript najde tyto emaily, stáhne binárku `smime.p7m` z Graphu, rozbalí PKCS7
|
||||
SignedData (`asn1crypto.cms`), extrahuje vnitřní MIME zprávu a doplní do Mongo:
|
||||
|
||||
| Pole | Obsah |
|
||||
|---|---|
|
||||
| `smime_unwrapped: True` | flag — už rozbaleno |
|
||||
| `smime_subject` | Subject z vnitřní MIME hlavičky |
|
||||
| `smime_body_text` | plain text vnitřního těla |
|
||||
| `smime_body_html` | HTML vnitřního těla (pokud je) |
|
||||
| `smime_inner_attachments[]` | `{filename, content_type, size_bytes}` vnitřních příloh |
|
||||
|
||||
Pole pak používá `5_enrich_fulltext_emails_v1.2` — preferuje `smime_body_*` před
|
||||
prázdným wrapper tělem a názvy vnitřních příloh přidá do `attachments_summary`
|
||||
(takže je najde MCP `emaily.find_attachment`).
|
||||
|
||||
```bash
|
||||
docker exec -it python-runner python /scripts/4_unwrap_smime_v1.0.py # vsechny schránky
|
||||
docker exec -it python-runner python /scripts/4_unwrap_smime_v1.0.py --mailbox ordinace@buzalkova.cz
|
||||
docker exec -it python-runner python /scripts/4_unwrap_smime_v1.0.py --limit 10 # test
|
||||
```
|
||||
|
||||
### POZOR: `smime.p7m` vs `smime.p7s` — dva různé typy
|
||||
|
||||
| Příloha | Co to je | Skript dělá |
|
||||
|---|---|---|
|
||||
| `smime.p7m` | **Enveloped/signed-data wrapper** — vnější obal kolem celé MIME zprávy. Bez rozbalení je viditelné jen *"This is an S/MIME signed message"*. | **Rozbalí** → extrahuje vnitřní tělo + přílohy do Mongo. |
|
||||
| `smime.p7s` | **Detached signature** — jen digitální podpis vedle čistého emailu. Vlastní `body_html` / `body_text` je normálně dostupné. | **Ignoruje** — není co rozbalovat. Mail je už čitelný. |
|
||||
|
||||
Filtr ve skriptu (`SMIME_FILTER`) je proto explicitně `^smime\.p7m$`. Pokud při
|
||||
auditu vidíš email s přílohou `smime.p7s` a `smime_unwrapped != True`, je to
|
||||
**správně** — žádná akce není potřeba.
|
||||
|
||||
### Závislosti
|
||||
|
||||
```bash
|
||||
pip install asn1crypto
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5) `5_enrich_fulltext_emails_v1.2.py` — fulltext do PostgreSQL
|
||||
|
||||
Vytáhne plný text z emailů v MongoDB a uloží do PostgreSQL
|
||||
(`MongoEmaily.emails`) s GIN `tsvector` indexem (config `soubory` — simple + unaccent).
|
||||
Emaily se **nestahují znovu** — tělo už je v Mongo z kroků 1/2/4.
|
||||
|
||||
**Priorita zdroje těla** (`body_source`):
|
||||
1. `smime` — `smime_body_text` / `smime_body_html` (pokud unwrap proběhl)
|
||||
2. `html` — `body_html`
|
||||
3. `text` — `body_text` (z parse v1.4 nebo refetch v1.0)
|
||||
4. `preview` — `body_preview` (fallback)
|
||||
|
||||
Inkrementalita: pokud `(mailbox, message_id)` existuje a `extractor_version`
|
||||
je aktuální a `modified_at` v Mongo není novější → skip. Bump `EXTRACTOR_VERSION`
|
||||
přeparsuje vše.
|
||||
|
||||
```bash
|
||||
docker exec -d python-runner bash -c "python /scripts/5_enrich_fulltext_emails_v1.2.py > /scripts/enrich.log 2>&1"
|
||||
docker exec -it python-runner python /scripts/5_enrich_fulltext_emails_v1.2.py --mailbox ordinace@buzalkova.cz
|
||||
docker exec -it python-runner python /scripts/5_enrich_fulltext_emails_v1.2.py --limit 500 # test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sledování průběhu
|
||||
|
||||
```bash
|
||||
docker exec -it python-runner tail -f /scripts/parse_emails.log
|
||||
docker exec -it python-runner tail -f /scripts/download_attachments.log
|
||||
docker exec -it python-runner tail -f /scripts/unwrap_smime.log
|
||||
```
|
||||
|
||||
---
|
||||
@@ -172,6 +276,7 @@ pymongo 4.17.0
|
||||
python-dateutil 2.9.0.post0
|
||||
extract-msg 0.55.0
|
||||
cryptography 48.0.0
|
||||
asn1crypto (S/MIME unwrap)
|
||||
beautifulsoup4 4.13.5
|
||||
oletools 0.60.2
|
||||
msoffcrypto-tool 6.0.0
|
||||
@@ -183,6 +288,7 @@ pcodedmp 1.2.6
|
||||
tzlocal 5.3.1
|
||||
six 1.17.0
|
||||
pip 25.0.1
|
||||
psycopg (PG klient pro krok 5)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -201,4 +307,6 @@ docker exec python-runner pip install <balicek>
|
||||
|
||||
| Datum | Změna |
|
||||
|---|---|
|
||||
| 2026-06-02 | Přechod z `.msg` souborů na Microsoft Graph API. Skript `parse_emails_tower_v1.1.py` (import lokálních `.msg`) nahrazen `parse_emails_graph_v1.3.py`; přidán `download_attachments_v1.3.py`. Staré verze v `Trash/`. |
|
||||
| 2026-06-02 | Přechod z `.msg` souborů na Microsoft Graph API. `parse_emails_tower_v1.1.py` (import lokálních `.msg`) nahrazen `parse_emails_graph_v1.3.py`; přidán `download_attachments_v1.3.py`. Staré verze v `Trash/`. |
|
||||
| 2026-06-03 | `parse_emails_graph_v1.4` (ukládá i plné plain-text tělo do `body_text`). Přidán `refetch_text_bodies_v1.0` (dohnání starých plain-text). Přidán `unwrap_smime_v1.0` (rozbalení `smime.p7m`). `enrich_fulltext_emails_v1.2` (preferuje `smime_body_*`, body_source `smime`/`text`). |
|
||||
| 2026-06-04 | Skripty přejmenovány s prefixem `1_…5_` podle pořadí v pipeline. `enrich_v1.1` + `parse_emails_tower_v1.1*` do `Trash/`. |
|
||||
|
||||
Reference in New Issue
Block a user