# -*- coding: utf-8 -*- # ============================================================================= # Nazev: backfill_send_failed_v1.0.py # Verze: 1.0 # Datum: 2026-06-17 # Popis: Jednorazovy backfill. Pro Sent-Items dokumenty bez Internet # Message-ID (_id zacina "filename:") v Mongo emaily."vbuzalka@its.jnj.com" # precte z odpovidajici .msg na Toweru (/mnt/user/JNJEMAILS) MAPI # PrimarySendAccount (0x0E28) + SentRepresenting (0x0065) a nastavi: # send_account = hodnota 0x0E28 # send_failed = True, kdyz obsahuje buzalka.cz (SendAs past) # send_error = "SendAs buzalka.cz (PrimarySendAccount)" # -> rychly dotaz na NEODESLANE: { send_failed: true } # Pouziti: python backfill_send_failed_v1.0.py (dry-run / nahled) # python backfill_send_failed_v1.0.py --apply (zapise do Mongo) # Pozn.: Cte .msg pres SFTP (paramiko) primo do pameti (BytesIO + olefile). # ============================================================================= import io import sys import paramiko import olefile from pymongo import MongoClient MONGO_URI = "mongodb://192.168.1.76:27017" DBN, COL = "emaily", "vbuzalka@its.jnj.com" TOWER_HOST, TOWER_USER, TOWER_PASS = "192.168.1.76", "root", "7309208104" REMOTE_DIR = "/mnt/user/JNJEMAILS" def ole_str(ole, tag4): for t in (tag4 + "001F", tag4 + "001E"): name = "__substg1.0_" + t if ole.exists(name): b = ole.openstream(name).read() if t.endswith("001F"): try: return b.decode("utf-16-le").strip() except Exception: pass for enc in ("cp1250", "cp1252", "utf-8", "latin-1"): try: return b.decode(enc).strip() except Exception: continue return "" def main(): apply = "--apply" in sys.argv cli = MongoClient(MONGO_URI) col = cli[DBN][COL] docs = list(col.find( {"jnj_folder": {"$regex": "Sent Items"}, "_id": {"$regex": "^filename:"}}, {"_id": 1, "filename": 1, "to": 1, "subject": 1})) print(f"Sent-Items bez Message-ID (filename:): {len(docs)}") ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(TOWER_HOST, username=TOWER_USER, password=TOWER_PASS, timeout=30) sftp = ssh.open_sftp() n_buz = n_other = n_missing = 0 updates = [] for d in docs: fn = d.get("filename") if not fn: n_missing += 1 continue try: raw = sftp.open(f"{REMOTE_DIR}/{fn}", "rb").read() ole = olefile.OleFileIO(io.BytesIO(raw)) except Exception as e: print(f" !! {fn}: {e}") n_missing += 1 continue try: send_acct = ole_str(ole, "0E28") sentrep = ole_str(ole, "0065") finally: ole.close() blob = (send_acct + " " + sentrep).lower() is_buz = "buzalka.cz" in blob if is_buz: n_buz += 1 err = "SendAs buzalka.cz (PrimarySendAccount)" else: n_other += 1 err = None updates.append((d["_id"], send_acct, is_buz, err, d.get("to"))) sftp.close(); ssh.close() print(f" buzalka.cz (send_failed=True): {n_buz}") print(f" jine send-account (False): {n_other}") print(f" chybi soubor/cteni: {n_missing}") print() for _id, acct, is_buz, err, to in updates[:10]: print(f" [{'FAIL' if is_buz else 'ok '}] {to} | acct={acct[:60]}") if len(updates) > 10: print(f" ... a dalsich {len(updates)-10}") if not apply: print("\n>>> DRY-RUN. Pro zapis spust s --apply") return n = 0 for _id, acct, is_buz, err, to in updates: res = col.update_one({"_id": _id}, {"$set": { "send_account": acct, "send_failed": bool(is_buz), "send_error": err, }}) n += res.modified_count print(f"\n>>> ZAPSANO (modified): {n}") if __name__ == "__main__": main()