# -*- coding: utf-8 -*- # ============================================================================= # Nazev: jnj_dump_recipient_msgs_v1.0.py # Verze: 1.0 # Datum: 2026-06-16 # Popis: JNJ-native (MAPI / pywin32). Najde VSECHNY e-maily danemu prijemci # (default Hustak) napric vybranymi slozkami, ULOZI je jako .msg a # u kazdeho VYPISE diagnosticke MAPI vlastnosti precteni ze ZIVE # polozky (Message-ID 0x1035, SenderName 0x0C1A, SentRepresentingName # 0x0042, addrtype 0x0C1E/0x0064, ReportText 0x1001, PrimarySendAccount # 0x0E28, MessageFlags 0x0E07, item.Sent). Cil: porovnat, zda tyto # vlastnosti zustanou i v ulozenem .msg (olefile kontrola doma). # Pouziti: Spustit v JNJ Pythonu (Thonny), Outlook s JNJ schrankou. # pip install pywin32 ; python jnj_dump_recipient_msgs_v1.0.py # Skript NIC neodesila ani nemaze, jen CTE a uklada .msg kopie. # ============================================================================= import os import re import sys import win32com.client # pywin32 # ----------------------------- KONFIGURACE ----------------------------------- SENDER_SMTP = "vbuzalka@its.jnj.com" # ucet (jeho store se prohledava) TARGET_EMAIL = "rastislav.hustak@fntt.sk" # koho hledame (To NEBO Cc) # Slozky k prohledani (shoda na NAZEV slozky kdekoli ve strome; vc. podslozek). # Prazdny seznam + SCAN_ALL=True => projde celou schranku (pomale!). SCAN_FOLDERS = ["Sent Items", "Drafts", "Deleted Items", "Archive", "Inbox"] SCAN_ALL = False # Kam ulozit .msg kopie (na JNJ stroji). Vytvori se, kdyz neexistuje. OUTPUT_DIR = r"C:\Users\vbuzalka\hustak_dump" # ----------------------------------------------------------------------------- OL_MSG = 3 # olMSG (SaveAs typ) OL_FOLDER_SENT = 5 PA = "http://schemas.microsoft.com/mapi/proptag/0x{:s}" # Diagnosticke tagy (PT_UNICODE 001F, dlouhe 0003) TAGS = [ ("Msg-ID", "1035001F"), ("SenderName", "0C1A001F"), ("SenderAddrType", "0C1E001F"), ("SentRepName", "0042001F"), ("SentRepAddrType", "0064001F"), ("ReportText", "1001001F"), ("PrimarySendAcct", "0E28001F"), ] TAG_MSGFLAGS = "0E070003" TAG_RCPT_ADDRTYPE = "3002001F" def smtp_of(recipient): try: return (recipient.PropertyAccessor.GetProperty(PA.format("39FE001E")) or "").lower() except Exception: try: return (recipient.Address or "").lower() except Exception: return "" def get_prop(item, tag): try: v = item.PropertyAccessor.GetProperty(PA.format(tag)) return v except Exception: return None def get_store_root(ns): try: for acct in ns.Accounts: if (acct.SmtpAddress or "").lower() == SENDER_SMTP.lower(): return acct.DeliveryStore.GetRootFolder() except Exception: pass return ns.GetDefaultFolder(OL_FOLDER_SENT).Parent # fallback: koren default store def iter_target_folders(root): """Yield slozek, ktere se maji skenovat (dle nazvu + jejich podslozky).""" def walk(folder, inscope): scope = inscope or SCAN_ALL or (folder.Name in SCAN_FOLDERS) if scope: yield folder try: for sub in folder.Folders: yield from walk(sub, scope) except Exception: pass yield from walk(root, False) def safe(s, n=40): s = re.sub(r"[^A-Za-z0-9._-]+", "_", (s or "")) return s[:n].strip("_") def matches_target(item): """Vrati ('To'/'Cc') kdyz je TARGET_EMAIL mezi prijemci, jinak None.""" tgt = TARGET_EMAIL.lower() try: for r in item.Recipients: if smtp_of(r) == tgt: return {1: "To", 2: "Cc", 3: "Bcc"}.get(r.Type, "To") except Exception: pass return None def main(): os.makedirs(OUTPUT_DIR, exist_ok=True) outlook = win32com.client.Dispatch("Outlook.Application") ns = outlook.GetNamespace("MAPI") root = get_store_root(ns) print(f"Hledam e-maily, kde je prijemce: {TARGET_EMAIL}") print(f"Slozky: {'VSE' if SCAN_ALL else ', '.join(SCAN_FOLDERS)}") print(f"Vystup .msg: {OUTPUT_DIR}") print("=" * 90) idx = 0 for folder in iter_target_folders(root): try: items = folder.Items except Exception: continue for it in list(items): try: if it.Class != 43: # olMail continue except Exception: continue role = matches_target(it) if not role: continue idx += 1 # --- diagnostika ze ZIVE polozky --- try: sent_flag = it.Sent except Exception: sent_flag = "?" flags = get_prop(it, TAG_MSGFLAGS) props = {label: get_prop(it, tag) for label, tag in TAGS} try: sent_on = it.SentOn except Exception: sent_on = None try: entry_tail = (it.EntryID or "")[-20:] except Exception: entry_tail = "" print(f"\n[{idx}] slozka='{folder.Name}' role={role} Sent={sent_flag} flags={flags}") print(f" subject : {getattr(it,'Subject','')}") print(f" sent_on : {sent_on}") print(f" Msg-ID : {props['Msg-ID']}") print(f" SenderName : {props['SenderName']} (addrtype {props['SenderAddrType']})") print(f" SentRepName : {props['SentRepName']} (addrtype {props['SentRepAddrType']})") print(f" PrimarySendAcct: {props['PrimarySendAcct']}") rt = props["ReportText"] print(f" ReportText 0x1001: {'ANO -> ' + repr(rt[:120]) if rt else '-'}") # --- ulozeni .msg --- fn = f"{idx:02d}_{safe(folder.Name,18)}_{safe(getattr(it,'Subject',''),28)}_{entry_tail}.msg" path = os.path.join(OUTPUT_DIR, fn) try: it.SaveAs(path, OL_MSG) print(f" ulozeno: {fn}") except Exception as e: print(f" !! SaveAs chyba: {e}") print("\n" + "=" * 90) print(f"Hotovo. Nalezeno a ulozeno: {idx} polozek do {OUTPUT_DIR}") print("Prines .msg domu a porovnej vlastnosti olefilem (zive vs ulozene).") if __name__ == "__main__": try: main() except Exception as e: print("CHYBA:", e) sys.exit(1)