sync: Auto-sync from ACG-M-L5090 at 2026-03-10 19:11:00
Synced files: - Quote wizard frontend (all components, hooks, types, config) - API updates (config, models, routers, schemas, services) - Client work (bg-builders, gurushow) - Scripts (BGB Lesley termination, CIPP, Datto, migration) - Temp files (Bardach contacts, VWP investigation, misc) - Credentials and session logs - Email service, PHP API, session logs Machine: ACG-M-L5090 Timestamp: 2026-03-10 19:11:00 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
temp/bardach_contacts_check.py
Normal file
134
temp/bardach_contacts_check.py
Normal file
@@ -0,0 +1,134 @@
|
||||
import urllib.request, urllib.parse, json, sys
|
||||
|
||||
CIPP_URL = "https://cippcanvb.azurewebsites.net"
|
||||
CIPP_TENANT = "ce61461e-81a0-4c84-bb4a-7b354a9a356d"
|
||||
CIPP_CLIENT = "420cb849-542d-4374-9cb2-3d8ae0e1835b"
|
||||
CIPP_SECRET = "MOn8Q~otmxJPLvmL~_aCVTV8Va4t4~SrYrukGbJT"
|
||||
CLAUDE_APP = "fabb3421-8b34-484b-bc17-e46de9703418"
|
||||
CLAUDE_SECRET = "~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO"
|
||||
TENANT = "bardach.net"
|
||||
TENANT_ID = "dd4a82e8-85a3-44ac-8800-07945ab4d95f"
|
||||
|
||||
def get_token(tenant_id, client_id, client_secret, scope):
|
||||
data = urllib.parse.urlencode({
|
||||
'client_id': client_id,
|
||||
'client_secret': client_secret,
|
||||
'scope': scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}).encode()
|
||||
req = urllib.request.Request(f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token", data=data, method='POST')
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
return json.loads(resp.read())['access_token']
|
||||
|
||||
# Get Exchange token for bardach.net
|
||||
print("[STEP 1] Getting Exchange token...")
|
||||
try:
|
||||
exo_token = get_token(TENANT_ID, CLAUDE_APP, CLAUDE_SECRET, "https://outlook.office365.com/.default")
|
||||
print("[OK] Exchange token acquired")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Run Get-MailboxFolderStatistics to find contact folders including deleted
|
||||
print("\n[STEP 2] Getting mailbox folder statistics (contacts scope)...")
|
||||
invoke_url = f"https://outlook.office365.com/adminapi/beta/{TENANT_ID}/InvokeCommand"
|
||||
headers = {'Authorization': f'Bearer {exo_token}', 'Content-Type': 'application/json'}
|
||||
|
||||
cmd = json.dumps({
|
||||
"CmdletInput": {
|
||||
"CmdletName": "Get-MailboxFolderStatistics",
|
||||
"Parameters": {
|
||||
"Identity": "barbara@bardach.net",
|
||||
"FolderScope": "Contacts"
|
||||
}
|
||||
}
|
||||
}).encode()
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(invoke_url, data=cmd, headers=headers, method='POST')
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
result = json.loads(resp.read())
|
||||
|
||||
for item in result.get('value', []):
|
||||
name = item.get('Name', '?')
|
||||
count = item.get('ItemsInFolder', '?')
|
||||
folder_type = item.get('FolderType', '?')
|
||||
size = item.get('FolderSize', '?')
|
||||
print(f" {name}: {count} items ({folder_type})")
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode()
|
||||
print(f"[ERROR] HTTP {e.code}: {body[:500]}")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] {e}")
|
||||
|
||||
# Also check RecoverableItems scope
|
||||
print("\n[STEP 3] Getting mailbox folder statistics (RecoverableItems scope)...")
|
||||
cmd2 = json.dumps({
|
||||
"CmdletInput": {
|
||||
"CmdletName": "Get-MailboxFolderStatistics",
|
||||
"Parameters": {
|
||||
"Identity": "barbara@bardach.net",
|
||||
"FolderScope": "RecoverableItems"
|
||||
}
|
||||
}
|
||||
}).encode()
|
||||
|
||||
try:
|
||||
req2 = urllib.request.Request(invoke_url, data=cmd2, headers=headers, method='POST')
|
||||
with urllib.request.urlopen(req2) as resp2:
|
||||
result2 = json.loads(resp2.read())
|
||||
|
||||
for item in result2.get('value', []):
|
||||
name = item.get('Name', '?')
|
||||
count = item.get('ItemsInFolder', '?')
|
||||
size = item.get('FolderSize', '?')
|
||||
folder_type = item.get('FolderType', '?')
|
||||
print(f" {name}: {count} items ({folder_type}) - {size}")
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode()
|
||||
print(f"[ERROR] HTTP {e.code}: {body[:500]}")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] {e}")
|
||||
|
||||
# Also get ALL folder stats to see everything
|
||||
print("\n[STEP 4] Getting ALL mailbox folder statistics...")
|
||||
cmd3 = json.dumps({
|
||||
"CmdletInput": {
|
||||
"CmdletName": "Get-MailboxFolderStatistics",
|
||||
"Parameters": {
|
||||
"Identity": "barbara@bardach.net"
|
||||
}
|
||||
}
|
||||
}).encode()
|
||||
|
||||
try:
|
||||
req3 = urllib.request.Request(invoke_url, data=cmd3, headers=headers, method='POST')
|
||||
with urllib.request.urlopen(req3) as resp3:
|
||||
result3 = json.loads(resp3.read())
|
||||
|
||||
# Filter for anything contact-related
|
||||
contact_folders = []
|
||||
for item in result3.get('value', []):
|
||||
name = item.get('Name', '?')
|
||||
folder_type = item.get('FolderType', '?')
|
||||
count = item.get('ItemsInFolder', 0)
|
||||
container_class = item.get('ContainerClass', '?')
|
||||
if 'contact' in name.lower() or 'contact' in str(folder_type).lower() or 'contact' in str(container_class).lower() or count > 100:
|
||||
contact_folders.append(item)
|
||||
print(f" {name}: {count} items (type={folder_type}, class={container_class})")
|
||||
|
||||
if not contact_folders:
|
||||
print(" No contact-related folders found in full stats")
|
||||
# Show all folders with items
|
||||
print("\n All folders with >0 items:")
|
||||
for item in result3.get('value', []):
|
||||
count = item.get('ItemsInFolder', 0)
|
||||
if count > 0:
|
||||
name = item.get('Name', '?')
|
||||
folder_type = item.get('FolderType', '?')
|
||||
print(f" {name}: {count} items ({folder_type})")
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode()
|
||||
print(f"[ERROR] HTTP {e.code}: {body[:500]}")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] {e}")
|
||||
Reference in New Issue
Block a user