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:
106
temp/vwp_add_mail_send.py
Normal file
106
temp/vwp_add_mail_send.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""Add Mail.Send permission to the app registration and grant admin consent."""
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
import ssl
|
||||
|
||||
TENANT_ID = "5c53ae9f-7071-4248-b834-8685b646450f"
|
||||
APP_ID = "fabb3421-8b34-484b-bc17-e46de9703418"
|
||||
APP_SECRET = "~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO"
|
||||
GRAPH_APP_ID = "00000003-0000-0000-c000-000000000000" # Microsoft Graph
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
|
||||
|
||||
def get_token():
|
||||
data = urllib.parse.urlencode({
|
||||
"client_id": APP_ID,
|
||||
"scope": "https://graph.microsoft.com/.default",
|
||||
"client_secret": APP_SECRET,
|
||||
"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, context=ctx) as resp:
|
||||
return json.loads(resp.read())["access_token"]
|
||||
|
||||
|
||||
def graph_get(token, url):
|
||||
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
|
||||
with urllib.request.urlopen(req, context=ctx) as resp:
|
||||
return json.loads(resp.read())
|
||||
|
||||
|
||||
def graph_post(token, url, payload=None):
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
body = None
|
||||
if payload:
|
||||
headers["Content-Type"] = "application/json"
|
||||
body = json.dumps(payload).encode()
|
||||
else:
|
||||
body = b""
|
||||
req = urllib.request.Request(url, data=body, headers=headers, method="POST")
|
||||
try:
|
||||
with urllib.request.urlopen(req, context=ctx) as resp:
|
||||
content = resp.read()
|
||||
return json.loads(content) if content else {}
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode()
|
||||
try:
|
||||
return json.loads(body)
|
||||
except:
|
||||
return {"error": {"message": body, "code": str(e.code)}}
|
||||
|
||||
|
||||
token = get_token()
|
||||
print("[OK] Token acquired")
|
||||
|
||||
# Find our app's service principal
|
||||
filter_val = urllib.parse.quote(f"appId eq '{APP_ID}'")
|
||||
url = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter={filter_val}"
|
||||
data = graph_get(token, url)
|
||||
if not data.get("value"):
|
||||
print("[ERROR] Could not find our service principal")
|
||||
print(json.dumps(data, indent=2)[:1000])
|
||||
sys.exit(1)
|
||||
our_sp_id = data["value"][0]["id"]
|
||||
print(f"[OK] Our SP ID: {our_sp_id}")
|
||||
|
||||
# Find Microsoft Graph service principal
|
||||
filter_val2 = urllib.parse.quote(f"appId eq '{GRAPH_APP_ID}'")
|
||||
url2 = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter={filter_val2}"
|
||||
data2 = graph_get(token, url2)
|
||||
graph_sp_id = data2["value"][0]["id"]
|
||||
print(f"[OK] Graph SP ID: {graph_sp_id}")
|
||||
|
||||
# Find Mail.Send role
|
||||
app_roles = data2["value"][0].get("appRoles", [])
|
||||
mail_send_id = None
|
||||
for role in app_roles:
|
||||
if role.get("value") == "Mail.Send":
|
||||
mail_send_id = role["id"]
|
||||
break
|
||||
|
||||
if not mail_send_id:
|
||||
print("[ERROR] Mail.Send role not found")
|
||||
sys.exit(1)
|
||||
print(f"[OK] Mail.Send role ID: {mail_send_id}")
|
||||
|
||||
# Grant the appRoleAssignment (admin consent)
|
||||
payload = {
|
||||
"principalId": our_sp_id,
|
||||
"resourceId": graph_sp_id,
|
||||
"appRoleId": mail_send_id
|
||||
}
|
||||
url3 = f"https://graph.microsoft.com/v1.0/servicePrincipals/{our_sp_id}/appRoleAssignments"
|
||||
result = graph_post(token, url3, payload)
|
||||
if result.get("id"):
|
||||
print(f"[SUCCESS] Mail.Send permission granted! Assignment ID: {result['id']}")
|
||||
elif "already exists" in str(result.get("error", {}).get("message", "")):
|
||||
print("[INFO] Mail.Send permission already assigned")
|
||||
else:
|
||||
print(f"[RESULT] Response: {json.dumps(result, indent=2)[:1000]}")
|
||||
Reference in New Issue
Block a user