Initial commit — clean history (removed large test files, browser profiles, Medidata/Clario downloads)
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
# parse_emails_v1.0
|
||||
|
||||
**Název:** parse_emails_v1.0.py
|
||||
**Verze:** 1.0
|
||||
**Datum:** 2026-06-01
|
||||
**Autor:** vladimir.buzalka
|
||||
|
||||
---
|
||||
|
||||
## Účel
|
||||
|
||||
Jednorázový import všech `.msg` souborů do MongoDB. Z každého souboru extrahuje **všechny dostupné vlastnosti** — podobně jako EXIF u fotek.
|
||||
|
||||
- **DB:** `emaily`
|
||||
- **Kolekce:** `vbuzalka@its.jnj.com`
|
||||
- `_id` = Internet Message-ID (nebo `filename:<stem>` jako fallback)
|
||||
- Bezpečné přerušit a opakovat — upsert podle `_id`
|
||||
|
||||
---
|
||||
|
||||
## Zdroje dat
|
||||
|
||||
Výhradně `.msg` soubory — žádná závislost na SQLite ani jiné DB.
|
||||
|
||||
| Z každého .msg se extrahuje |
|
||||
|---|
|
||||
| Předmět, normalized subject |
|
||||
| Odesílatel (email, jméno, SMTP adresa) |
|
||||
| Příjemci To/CC/BCC — strukturovaně `[{type, email, name}]` |
|
||||
| Čas doručení a odeslání (UTC) |
|
||||
| Tělo plaintext + HTML (max 2 MB) |
|
||||
| Přílohy — metadata: jméno, velikost, MIME typ, inline flag |
|
||||
| Internet headers — X-Originating-IP, Received, DKIM, X-Mailer, ... |
|
||||
| MAPI: důležitost, citlivost, příznak, konverzační vlákno, kategorie |
|
||||
| In-Reply-To, References — pro rekonstrukci vlákna |
|
||||
| Všechny raw MAPI properties jako `{0xXXXX: value}` |
|
||||
|
||||
---
|
||||
|
||||
## Konfigurace
|
||||
|
||||
Konstanty přímo v kódu:
|
||||
|
||||
| Konstanta | Hodnota |
|
||||
|---|---|
|
||||
| `MSGS_DIR` | `\\tower\JNJEMAILS` |
|
||||
| `MONGO_URI` | `mongodb://192.168.1.76:27017` |
|
||||
| `MONGO_DB` | `emaily` |
|
||||
| `MONGO_COL` | `vbuzalka@its.jnj.com` |
|
||||
| `BATCH_SIZE` | 200 dokumentů na jeden bulk_write |
|
||||
| `LOG_FILE` | `parse_emails_errors.log` (vedle skriptu) |
|
||||
|
||||
---
|
||||
|
||||
## Spouštění
|
||||
|
||||
**Venv:** `U:\PythonProject\Janssen\.venv\Scripts\python.exe`
|
||||
|
||||
**1. spuštění — kompletní import:**
|
||||
```cmd
|
||||
"U:\PythonProject\Janssen\.venv\Scripts\python.exe" "U:\PythonProject\Janssen\EmailsImport\parse_emails_v1.0.py"
|
||||
```
|
||||
|
||||
**Pokračování po přerušení (druhý den):**
|
||||
```cmd
|
||||
"U:\PythonProject\Janssen\.venv\Scripts\python.exe" "U:\PythonProject\Janssen\EmailsImport\parse_emails_v1.0.py" --skip-existing
|
||||
```
|
||||
|
||||
**Test na malém vzorku:**
|
||||
```cmd
|
||||
"U:\PythonProject\Janssen\.venv\Scripts\python.exe" "U:\PythonProject\Janssen\EmailsImport\parse_emails_v1.0.py" --limit 50 --no-indexes
|
||||
```
|
||||
|
||||
### Všechny parametry
|
||||
|
||||
| Parametr | Popis |
|
||||
|---|---|
|
||||
| `--skip-existing` | Načte seznam hotových souborů z MongoDB a přeskočí je. Použij pro pokračování po přerušení. |
|
||||
| `--limit N` | Zpracuje jen prvních N souborů. Vhodné pro test. |
|
||||
| `--no-indexes` | Nevytváří indexy na konci. Použij pokud je přerušíš uprostřed — indexy vytvoř ručně až je vše hotové. |
|
||||
|
||||
---
|
||||
|
||||
## Průběh na konzoli
|
||||
|
||||
Každý email na jednom řádku:
|
||||
```
|
||||
1/69371 OK RE: Protocol deviation CZ10022 jan.novak@its.jnj.com
|
||||
2/69371 OK UCO3001: Draft FUL pro DD5-CZ10022 monitor@4gclinical.com
|
||||
3/69371 ERR ? ?
|
||||
```
|
||||
|
||||
Každých 500 emailů oddělovač s průběhem:
|
||||
```
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
Průběh: ok=498 err=2 0.4 msg/s ETA 47h12m
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
Na konci souhrn:
|
||||
```
|
||||
====================================================
|
||||
Vysledek: ok=69300 | skip=0 | err=71
|
||||
Celkovy cas: 47h 23m 10s
|
||||
Dokumentu v kolekci: 69300
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Struktura dokumentu v MongoDB
|
||||
|
||||
```json
|
||||
{
|
||||
"_id": "<message-id@domain>",
|
||||
"filename": "7A3F...0000.msg",
|
||||
|
||||
"subject": "RE: Protocol deviation CZ10022",
|
||||
"normalized_subject": "Protocol deviation CZ10022",
|
||||
"importance": 1,
|
||||
"sensitivity": 0,
|
||||
"flag_status": 0,
|
||||
"read_receipt_requested": false,
|
||||
"delivery_receipt_requested": false,
|
||||
"has_attachments": true,
|
||||
"attachment_count": 1,
|
||||
"message_size_bytes": 284512,
|
||||
|
||||
"conversation_topic": "Protocol deviation CZ10022",
|
||||
"conversation_index": "AcqX...",
|
||||
"in_reply_to": "<prev-id@domain>",
|
||||
"internet_references": ["<ref1@domain>", "<ref2@domain>"],
|
||||
"categories": ["UCO3001"],
|
||||
|
||||
"received_at": "2026-05-15T09:23:11",
|
||||
"sent_at": "2026-05-15T09:21:44",
|
||||
|
||||
"sender": {
|
||||
"email": "jan.novak@its.jnj.com",
|
||||
"name": "Novák Jan",
|
||||
"smtp": "jan.novak@its.jnj.com"
|
||||
},
|
||||
"to": "vladimir.buzalka@its.jnj.com",
|
||||
"cc": "petra.free@its.jnj.com",
|
||||
"bcc": "",
|
||||
"display_to": "Buzalka Vladimir",
|
||||
"display_cc": "Free Petra",
|
||||
"recipients": [
|
||||
{ "type": "to", "email": "vbuzalka@its.jnj.com", "name": "Buzalka Vladimir" },
|
||||
{ "type": "cc", "email": "petra.free@its.jnj.com", "name": "Free Petra" }
|
||||
],
|
||||
|
||||
"body_text": "Dobrý den,\n\nposílám...",
|
||||
"body_html": "<html>...",
|
||||
|
||||
"attachments": [
|
||||
{
|
||||
"filename": "PD_report_CZ10022.pdf",
|
||||
"size_bytes": 284512,
|
||||
"mime_type": "application/pdf",
|
||||
"content_id": null,
|
||||
"is_inline": false
|
||||
}
|
||||
],
|
||||
|
||||
"headers": {
|
||||
"message_id": "<xxx@domain>",
|
||||
"x_originating_ip": "10.24.1.55",
|
||||
"x_mailer": "Microsoft Outlook 16.0",
|
||||
"received": ["from SMTP01...", "from EX2019..."],
|
||||
"x_spam_status": "No"
|
||||
},
|
||||
|
||||
"mapi": {
|
||||
"0x0017": 1,
|
||||
"0x0036": 0,
|
||||
"0x0070": "Protocol deviation CZ10022",
|
||||
"0x1035": "<message-id@domain>",
|
||||
"0x1042": "<prev-id@domain>"
|
||||
},
|
||||
|
||||
"parsed_at": "2026-06-01T20:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hodnotové kódy
|
||||
|
||||
| Pole | Hodnota | Význam |
|
||||
|---|---|---|
|
||||
| `importance` | 0 | Nízká |
|
||||
| | 1 | Normální |
|
||||
| | 2 | Vysoká |
|
||||
| `sensitivity` | 0 | Normální |
|
||||
| | 1 | Osobní |
|
||||
| | 2 | Soukromé |
|
||||
| | 3 | Důvěrné |
|
||||
| `flag_status` | 0 | Bez příznaku |
|
||||
| | 1 | Označeno (follow up) |
|
||||
| | 2 | Dokončeno |
|
||||
|
||||
---
|
||||
|
||||
## MongoDB indexy
|
||||
|
||||
Automaticky vytvořeny na konci importu (`--no-indexes` přeskočí):
|
||||
|
||||
| Index | Pole |
|
||||
|---|---|
|
||||
| Chronologický | `received_at`, `sent_at` |
|
||||
| Odesílatel | `sender.email` |
|
||||
| Soubor | `filename` (unique) |
|
||||
| Konverzace | `conversation_topic` |
|
||||
| Filtry | `has_attachments`, `categories`, `importance`, `flag_status` |
|
||||
| Full-text | `subject` + `body_text` + `to` + `cc` (text index `text_search`) |
|
||||
|
||||
---
|
||||
|
||||
## Ukázkové dotazy (MongoDB shell / MCP)
|
||||
|
||||
**Emaily o UCO3001 s přílohou:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
$text: { $search: "UCO3001" },
|
||||
has_attachments: true
|
||||
}).sort({ received_at: -1 })
|
||||
```
|
||||
|
||||
**Emaily od konkrétního odesílatele:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
"sender.email": /covance/i
|
||||
}).sort({ received_at: -1 })
|
||||
```
|
||||
|
||||
**Celé konverzační vlákno:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
conversation_topic: "Protocol deviation CZ10022"
|
||||
}).sort({ received_at: 1 })
|
||||
```
|
||||
|
||||
**Označené emaily (follow up):**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({ flag_status: 1 })
|
||||
```
|
||||
|
||||
**Vysoká priorita s přílohou:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
importance: 2,
|
||||
has_attachments: true
|
||||
}).sort({ received_at: -1 })
|
||||
```
|
||||
|
||||
**Statistiky podle odesílatele (top 20):**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].aggregate([
|
||||
{ $group: { _id: "$sender.email", count: { $sum: 1 } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: 20 }
|
||||
])
|
||||
```
|
||||
|
||||
**Emaily s PDF přílohou:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
"attachments.mime_type": "application/pdf"
|
||||
})
|
||||
```
|
||||
|
||||
**Hledání v těle emailu:**
|
||||
```javascript
|
||||
db["vbuzalka@its.jnj.com"].find({
|
||||
$text: { $search: "inactivation notification" }
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Chybový log
|
||||
|
||||
Soubory které selhaly jsou zalogrovány do `parse_emails_errors.log` vedle skriptu:
|
||||
```
|
||||
2026-06-01 20:14:33 | open failed [7A3F...0000.msg]: <důvod>
|
||||
2026-06-01 20:15:01 | extract_message failed [8B2C...0000.msg]: <důvod>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Výkon
|
||||
|
||||
| Parametr | Hodnota |
|
||||
|---|---|
|
||||
| Počet souborů | ~69 000 |
|
||||
| Rychlost | ~0.4 msg/s (síť SMB + htmlBody dekódování) |
|
||||
| Odhadovaný čas | 48 hodin (přes noc, s pokračováním) |
|
||||
| Batch size | 200 dokumentů / bulk_write |
|
||||
| Odhadovaná velikost DB | 2–5 GB |
|
||||
|
||||
---
|
||||
|
||||
## Závislosti
|
||||
|
||||
```
|
||||
extract-msg==0.55.0
|
||||
pymongo
|
||||
python-dateutil
|
||||
```
|
||||
|
||||
Instalace do venv:
|
||||
```cmd
|
||||
"U:\PythonProject\Janssen\.venv\Scripts\pip.exe" install extract-msg pymongo python-dateutil
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Historie verzí
|
||||
|
||||
| Verze | Datum | Změna |
|
||||
|---|---|---|
|
||||
| 1.0 | 2026-06-01 | Iniciální verze |
|
||||
Reference in New Issue
Block a user