Skip to content

Commit b25ab2d

Browse files
committed
updated py file for email correct information
1 parent 642752f commit b25ab2d

File tree

3 files changed

+150
-7
lines changed

3 files changed

+150
-7
lines changed

chveulebrivi_for_azure_devops.py

Whitespace-only changes.

get_email_webhook.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import json
32
import hmac
43
import hashlib
54
import requests
@@ -81,7 +80,7 @@ def verify_github_signature(payload_body, signature, secret):
8180
def github_webhook():
8281
payload_body = request.data
8382
signature = request.headers.get("X-Hub-Signature-256")
84-
secret = os.getenv("GITHUB_WEBHOOK_SECRET") # ✅ Correct usage
83+
secret = os.getenv("GITHUB_WEBHOOK_SECRET")
8584

8685
# Debug logging
8786
print("📥 Incoming GitHub webhook")
@@ -104,13 +103,18 @@ def github_webhook():
104103

105104
# Handle repository create/delete events
106105
if event == "repository" and data.get("action") in ["created", "deleted"]:
107-
repo_name = data["repository"]["full_name"]
106+
repo = data.get("repository", {})
107+
owner = repo.get("owner", {})
108108
action = data["action"]
109109

110-
subject = f"[GitHub Alert] Repository {action}: {repo_name}"
110+
subject = f"[GitHub Alert] Repository {action}: {repo.get('full_name', 'unknown')}"
111+
111112
body = (
112113
f"A repository was {action} in your GitHub organization.\n\n"
113-
f"Details:\n{json.dumps(data, indent=2)}"
114+
f"📌 Repository Name: {repo.get('full_name')}\n"
115+
f"🔒 Visibility: {'Private' if repo.get('private') else 'Public'}\n"
116+
f"👤 Owner: {owner.get('login')}\n"
117+
f"🌍 URL: {repo.get('html_url', 'N/A')}\n"
114118
)
115119

116120
print(f"📩 Sending email alert: {subject}")
@@ -135,6 +139,5 @@ def health_check():
135139
)
136140
else:
137141
print("✅ Flask is up and listening on /webhook and /health")
138-
# Azure expects port 8000 by default for containerized apps
139142
port = int(os.getenv("PORT", 8000))
140-
app.run(host="0.0.0.0", port=port)
143+
app.run(host="0.0.0.0", port=port)

get_email_webhook_old_musha.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import os
2+
import json
3+
import hmac
4+
import hashlib
5+
import requests
6+
from msal import ConfidentialClientApplication
7+
8+
# --- Determine mode ---
9+
TEST_MODE = os.getenv("TEST_MODE", "true").lower() == "true"
10+
11+
# Only import Flask if not in TEST_MODE
12+
if not TEST_MODE:
13+
from flask import Flask, request, jsonify
14+
app = Flask(__name__)
15+
16+
# --- Microsoft Graph Email Sending Function ---
17+
def send_email_via_graph(subject, body):
18+
TENANT_ID = os.getenv("TENANT_ID")
19+
CLIENT_ID = os.getenv("CLIENT_ID")
20+
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
21+
FROM_EMAIL = os.getenv("FROM_EMAIL")
22+
TO_EMAIL = os.getenv("TO_EMAIL")
23+
24+
if not all([TENANT_ID, CLIENT_ID, CLIENT_SECRET, FROM_EMAIL, TO_EMAIL]):
25+
print("❌ Missing required environment variables")
26+
return False
27+
28+
try:
29+
app_msal = ConfidentialClientApplication(
30+
CLIENT_ID,
31+
authority=f"https://login.microsoftonline.com/{TENANT_ID}",
32+
client_credential=CLIENT_SECRET
33+
)
34+
token = app_msal.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
35+
access_token = token.get("access_token")
36+
if not access_token:
37+
print(f"❌ Failed to get access token: {token}")
38+
return False
39+
40+
email_msg = {
41+
"message": {
42+
"subject": subject,
43+
"body": {"contentType": "Text", "content": body},
44+
"toRecipients": [{"emailAddress": {"address": TO_EMAIL}}]
45+
}
46+
}
47+
48+
response = requests.post(
49+
f"https://graph.microsoft.com/v1.0/users/{FROM_EMAIL}/sendMail",
50+
headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
51+
json=email_msg
52+
)
53+
54+
if response.status_code == 202:
55+
print(f"✅ Email sent to {TO_EMAIL}")
56+
return True
57+
else:
58+
print(f"❌ Failed to send email: {response.status_code} {response.text}")
59+
return False
60+
61+
except Exception as e:
62+
print(f"❌ Exception occurred while sending email: {e}")
63+
return False
64+
65+
# --- Verify GitHub webhook signature ---
66+
def verify_github_signature(payload_body, signature, secret):
67+
if not secret:
68+
print("⚠️ No webhook secret set, skipping verification")
69+
return True
70+
if not signature:
71+
print("❌ No signature provided in headers")
72+
return False
73+
74+
mac = hmac.new(secret.encode(), msg=payload_body, digestmod=hashlib.sha256)
75+
expected_signature = "sha256=" + mac.hexdigest()
76+
return hmac.compare_digest(expected_signature, signature)
77+
78+
# --- GitHub Webhook Handler ---
79+
if not TEST_MODE:
80+
@app.route("/webhook", methods=["POST"])
81+
def github_webhook():
82+
payload_body = request.data
83+
signature = request.headers.get("X-Hub-Signature-256")
84+
secret = os.getenv("GITHUB_WEBHOOK_SECRET") # ✅ Correct usage
85+
86+
# Debug logging
87+
print("📥 Incoming GitHub webhook")
88+
print(f"📥 Payload size: {len(payload_body)} bytes")
89+
print(f"📥 GitHub Event: {request.headers.get('X-GitHub-Event')}")
90+
print(f"📥 Signature header: {signature}")
91+
print(f"📥 Secret length: {len(secret) if secret else 'None'}")
92+
93+
if not verify_github_signature(payload_body, signature, secret):
94+
print("❌ Invalid signature! Webhook rejected.")
95+
return "❌ Invalid signature", 401
96+
97+
try:
98+
data = request.json or {}
99+
except Exception as e:
100+
print(f"❌ Failed to parse JSON payload: {e}")
101+
return "❌ Bad payload", 400
102+
103+
event = request.headers.get("X-GitHub-Event", "")
104+
105+
# Handle repository create/delete events
106+
if event == "repository" and data.get("action") in ["created", "deleted"]:
107+
repo_name = data["repository"]["full_name"]
108+
action = data["action"]
109+
110+
subject = f"[GitHub Alert] Repository {action}: {repo_name}"
111+
body = (
112+
f"A repository was {action} in your GitHub organization.\n\n"
113+
f"Details:\n{json.dumps(data, indent=2)}"
114+
)
115+
116+
print(f"📩 Sending email alert: {subject}")
117+
send_email_via_graph(subject, body)
118+
else:
119+
print(f"ℹ️ Ignored event: {event}, action: {data.get('action')}")
120+
121+
return "OK", 200
122+
123+
# Health check endpoint
124+
@app.route("/health", methods=["GET"])
125+
def health_check():
126+
return jsonify({"status": "running"}), 200
127+
128+
# --- Main Entry Point ---
129+
if __name__ == "__main__":
130+
if TEST_MODE:
131+
print("🔹 TEST_MODE: sending test email")
132+
send_email_via_graph(
133+
"[Test] Graph Email",
134+
"This is a test email sent via Microsoft Graph with application permissions."
135+
)
136+
else:
137+
print("✅ Flask is up and listening on /webhook and /health")
138+
# Azure expects port 8000 by default for containerized apps
139+
port = int(os.getenv("PORT", 8000))
140+
app.run(host="0.0.0.0", port=port)

0 commit comments

Comments
 (0)