130 lines
4.0 KiB
Python
130 lines
4.0 KiB
Python
"""
|
|
wipe_jnj_mailbox.py | 2026-06-08
|
|
Vyčistí složku Inbox/JNJ ve schránce vladimir.buzalka@buzalka.cz PŘED testem mirroru.
|
|
|
|
- Zachová samotnou složku Inbox/JNJ
|
|
- Trvale smaže (permanentDelete — obchází Deleted Items) všechny zprávy v JNJ
|
|
i ve všech podsložkách
|
|
- Smaže všechny podsložky JNJ (Inbox, Sent Items, Deleted Items, ...)
|
|
|
|
Výsledek: Inbox/JNJ existuje a je prázdná. Mirror si podsložky vytvoří znovu.
|
|
"""
|
|
import sys
|
|
import msal
|
|
import requests
|
|
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
|
|
GRAPH_TENANT_ID = "7d269944-37a4-43a1-8140-c7517dc426e9"
|
|
GRAPH_CLIENT_ID = "4b222bfd-78c9-4239-a53f-43006b3ed07f"
|
|
GRAPH_CLIENT_SECRET = "Txg8Q~MjhocuopxsJyJBhPmDfMxZ2r5WpTFj1dfk"
|
|
GRAPH_MAILBOX = "vladimir.buzalka@buzalka.cz"
|
|
GRAPH_URL = "https://graph.microsoft.com/v1.0"
|
|
|
|
_token = None
|
|
|
|
|
|
def token():
|
|
global _token
|
|
app = msal.ConfidentialClientApplication(
|
|
GRAPH_CLIENT_ID,
|
|
authority=f"https://login.microsoftonline.com/{GRAPH_TENANT_ID}",
|
|
client_credential=GRAPH_CLIENT_SECRET,
|
|
)
|
|
res = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
|
|
if "access_token" not in res:
|
|
raise RuntimeError(f"auth failed: {res}")
|
|
_token = res["access_token"]
|
|
return _token
|
|
|
|
|
|
def H():
|
|
return {"Authorization": f"Bearer {_token or token()}"}
|
|
|
|
|
|
def get_jnj_id():
|
|
r = requests.get(f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/mailFolders/Inbox/childFolders?$top=100",
|
|
headers=H(), timeout=20).json()
|
|
for f in r.get("value", []):
|
|
if f["displayName"] == "JNJ":
|
|
return f["id"]
|
|
return None
|
|
|
|
|
|
def child_folders(fid):
|
|
out = []
|
|
url = f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/mailFolders/{fid}/childFolders?$top=100"
|
|
while url:
|
|
r = requests.get(url, headers=H(), timeout=20).json()
|
|
out += r.get("value", [])
|
|
url = r.get("@odata.nextLink")
|
|
return out
|
|
|
|
|
|
def all_descendants(root_id):
|
|
"""Vrať [(id, displayName)] root + všech podsložek (BFS)."""
|
|
result = [(root_id, "JNJ")]
|
|
i = 0
|
|
while i < len(result):
|
|
fid = result[i][0]
|
|
i += 1
|
|
for f in child_folders(fid):
|
|
result.append((f["id"], f["displayName"]))
|
|
return result
|
|
|
|
|
|
def wipe_messages(fid, name):
|
|
deleted = 0
|
|
while True:
|
|
r = requests.get(
|
|
f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/mailFolders/{fid}/messages?$select=id&$top=100",
|
|
headers=H(), timeout=30).json()
|
|
msgs = r.get("value", [])
|
|
if not msgs:
|
|
break
|
|
for m in msgs:
|
|
pd = requests.post(
|
|
f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/messages/{m['id']}/permanentDelete",
|
|
headers=H(), timeout=20)
|
|
if pd.status_code in (200, 204):
|
|
deleted += 1
|
|
else:
|
|
# fallback: běžné smazání
|
|
requests.delete(f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/messages/{m['id']}",
|
|
headers=H(), timeout=20)
|
|
deleted += 1
|
|
print(f" {name}: smazáno {deleted} zpráv")
|
|
return deleted
|
|
|
|
|
|
def main():
|
|
print("=== wipe_jnj_mailbox ===")
|
|
token()
|
|
|
|
jnj_id = get_jnj_id()
|
|
if not jnj_id:
|
|
print("Složka Inbox/JNJ neexistuje — není co mazat.")
|
|
return
|
|
|
|
folders = all_descendants(jnj_id)
|
|
print(f"Nalezeno složek pod JNJ (vč. JNJ): {len(folders)}\n")
|
|
|
|
print("Mažu zprávy (trvale)...")
|
|
total = 0
|
|
for fid, name in folders:
|
|
total += wipe_messages(fid, name)
|
|
|
|
# smaž podsložky JNJ (ne samotnou JNJ)
|
|
print("\nMažu podsložky JNJ...")
|
|
subs = child_folders(jnj_id)
|
|
for f in subs:
|
|
r = requests.delete(f"{GRAPH_URL}/users/{GRAPH_MAILBOX}/mailFolders/{f['id']}",
|
|
headers=H(), timeout=20)
|
|
print(f" podsložka {f['displayName']}: {'smazána' if r.status_code in (200,204) else 'CHYBA '+str(r.status_code)}")
|
|
|
|
print(f"\n=== Hotovo: smazáno {total} zpráv, Inbox/JNJ je prázdná ===")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|