Files
claudetools/temp/vwp_send_notification.py
Mike Swanson fa15b03180 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>
2026-03-10 19:59:08 -07:00

200 lines
6.6 KiB
Python

"""
VWP BEC Incident - Send phishing notification to all affected recipients.
Sends from JR's account via Microsoft Graph API sendMail endpoint.
"""
import json
import subprocess
import sys
import tempfile
import os
# === Configuration ===
TENANT_ID = "5c53ae9f-7071-4248-b834-8685b646450f"
APP_ID = "fabb3421-8b34-484b-bc17-e46de9703418"
APP_SECRET = "~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO"
JR_USER_ID = "0af923d0-48c5-4cc1-8553-c60625802815"
JR_EMAIL = "j-r@valleywideplastering.com"
RECIPIENTS_FILE = r"D:\ClaudeTools\temp\vwp_exchange_recipients.json"
# Addresses to exclude (lowercase for comparison)
EXCLUDE_EXACT = {
"j-r@valleywideplastering.com",
"jr@valleywideplastering.com",
"jr@casarica.net",
"jrsuperwall@gmail.com",
"kathya@azappliancehome.com.com", # malformed double .com
}
EXCLUDE_DOMAINS = ["bidmail.com", "onmicrosoft.com"]
def get_access_token():
"""Acquire OAuth2 token via client credentials flow."""
token_url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
result = subprocess.run(
[
"curl", "-s", "-X", "POST", token_url,
"-H", "Content-Type: application/x-www-form-urlencoded",
"-d", f"client_id={APP_ID}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret={APP_SECRET}&grant_type=client_credentials",
],
capture_output=True, text=True
)
resp = json.loads(result.stdout)
if "access_token" not in resp:
print("[ERROR] Failed to get access token:")
print(json.dumps(resp, indent=2))
sys.exit(1)
print("[OK] Access token acquired")
return resp["access_token"]
def load_recipients():
"""Load and filter recipients from the JSON file."""
with open(RECIPIENTS_FILE, encoding="utf-8") as f:
data = json.load(f)
raw = data["all_unique_recipients"]
print(f"[INFO] Raw recipient count: {len(raw)}")
# Strip surrounding single quotes and whitespace
cleaned = [addr.strip().strip("'").strip() for addr in raw]
# Filter and deduplicate (case-insensitive)
seen = set()
filtered = []
for addr in cleaned:
lower = addr.lower()
# Skip excluded exact addresses
if lower in EXCLUDE_EXACT:
continue
# Skip excluded domain patterns
if any(domain in lower for domain in EXCLUDE_DOMAINS):
continue
# Deduplicate
if lower not in seen:
seen.add(lower)
filtered.append(addr)
print(f"[INFO] After filtering and dedup: {len(filtered)} BCC recipients")
return filtered
def send_notification(token, bcc_recipients):
"""Send the notification email via Graph API sendMail endpoint."""
subject = 'Security Notice - Do Not Open Box.com File "Valley Wide Plastering, INC......pdf"'
body_html = (
'<p>You recently received a file sharing invitation from my Box.com account '
'for a file named "Valley Wide Plastering, INC......pdf".</p>'
'\n\n'
'<p>This file was <strong>NOT</strong> sent by me. My email account was temporarily '
'compromised, and the attacker used it to distribute this malicious link through '
'Box.com. The issue has been resolved and my account has been secured.</p>'
'\n\n'
'<p><strong>Please take the following steps:</strong></p>'
'\n'
'<ol>'
'<li>Do NOT open or click the Box.com link if you haven\'t already</li>'
'<li>If you DID click the link or entered any credentials on the page, please '
'change your password immediately and notify your IT department</li>'
'<li>Delete the Box.com sharing notification email from your inbox</li>'
'<li>If you created a Box.com account as a result of this invitation, consider removing it</li>'
'</ol>'
'\n\n'
'<p>We apologize for the inconvenience. If you have any questions or concerns, '
'please contact our office directly.</p>'
'\n\n'
'<p>JR Guerrero<br>Valley Wide Plastering, Inc.</p>'
)
payload = {
"message": {
"subject": subject,
"body": {
"contentType": "HTML",
"content": body_html
},
"toRecipients": [
{"emailAddress": {"address": JR_EMAIL}}
],
"bccRecipients": [
{"emailAddress": {"address": addr}} for addr in bcc_recipients
]
},
"saveToSentItems": True
}
# Write payload to temp file to avoid command-line length limits
tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False, encoding="utf-8")
json.dump(payload, tmp, ensure_ascii=False)
tmp.close()
send_url = f"https://graph.microsoft.com/v1.0/users/{JR_USER_ID}/sendMail"
try:
result = subprocess.run(
[
"curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
"-X", "POST", send_url,
"-H", f"Authorization: Bearer {token}",
"-H", "Content-Type: application/json",
"-d", f"@{tmp.name}",
],
capture_output=True, text=True
)
status_code = result.stdout.strip()
print(f"[INFO] HTTP status code: {status_code}")
if status_code == "202":
print("[SUCCESS] Notification email sent successfully!")
else:
print(f"[ERROR] Unexpected status code: {status_code}")
# Re-run to capture response body for debugging
result2 = subprocess.run(
[
"curl", "-s",
"-X", "POST", send_url,
"-H", f"Authorization: Bearer {token}",
"-H", "Content-Type: application/json",
"-d", f"@{tmp.name}",
],
capture_output=True, text=True
)
print(result2.stdout[:2000])
finally:
os.unlink(tmp.name)
def main():
print("=" * 60)
print("VWP BEC Incident - Phishing Notification Sender")
print("=" * 60)
# Step 1: Load and filter recipients
bcc_recipients = load_recipients()
# Print all recipients for verification
print("\n[INFO] BCC recipient list:")
for i, addr in enumerate(bcc_recipients, 1):
print(f" {i:3d}. {addr}")
print(f"\n[INFO] Total BCC recipients: {len(bcc_recipients)}")
print(f"[INFO] To recipient: {JR_EMAIL}")
# Step 2: Get access token
token = get_access_token()
# Step 3: Send the email
print(f"\n[INFO] Sending notification email...")
send_notification(token, bcc_recipients)
print("\n[OK] Done.")
if __name__ == "__main__":
main()