z230
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
# -*- 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)
|
||||
Reference in New Issue
Block a user