Skip to content

Commit 7db3981

Browse files
authored
Update get_email_webhook.py
1 parent 4ca3198 commit 7db3981

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

get_email_webhook.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,24 @@
66
from msal import ConfidentialClientApplication
77
from datetime import datetime, timezone, timedelta
88

9-
# --- Environment variables (loaded once) ---
10-
TENANT_ID = os.getenv("TENANT_ID")
11-
CLIENT_ID = os.getenv("CLIENT_ID")
12-
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
13-
FROM_EMAIL = os.getenv("FROM_EMAIL")
14-
TO_EMAIL = os.getenv("TO_EMAIL")
15-
GITHUB_WEBHOOK_SECRET = os.getenv("GITHUB_WEBHOOK_SECRET")
16-
17-
# --- Mode toggle (Test vs Webhook server) ---
9+
# --- Determine mode ---
1810
TEST_MODE = os.getenv("TEST_MODE", "true").lower() == "true"
1911

12+
# Import Flask only if not in TEST_MODE
2013
if not TEST_MODE:
2114
from flask import Flask, request
2215
app = Flask(__name__)
2316

24-
2517
# --- Microsoft Graph Email Sending Function ---
2618
def send_email_via_graph(subject, body):
27-
"""Send email using Microsoft Graph API via client credentials flow."""
19+
TENANT_ID = os.getenv("TENANT_ID")
20+
CLIENT_ID = os.getenv("CLIENT_ID")
21+
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
22+
FROM_EMAIL = os.getenv("FROM_EMAIL")
23+
TO_EMAIL = os.getenv("TO_EMAIL")
24+
2825
if not all([TENANT_ID, CLIENT_ID, CLIENT_SECRET, FROM_EMAIL, TO_EMAIL]):
29-
print("❌ Missing required environment variables for email sending")
26+
print("❌ Missing required environment variables")
3027
return
3128

3229
try:
@@ -37,7 +34,6 @@ def send_email_via_graph(subject, body):
3734
)
3835
token = app_msal.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
3936
access_token = token.get("access_token")
40-
4137
if not access_token:
4238
print(f"❌ Failed to get access token: {token}")
4339
return
@@ -64,10 +60,8 @@ def send_email_via_graph(subject, body):
6460
except Exception as e:
6561
print(f"❌ Exception occurred while sending email: {e}")
6662

67-
68-
# --- GitHub Webhook Signature Verification ---
63+
# --- Verify GitHub webhook signature ---
6964
def verify_github_signature(payload_body, signature, secret):
70-
"""Verify X-Hub-Signature-256 against webhook secret."""
7165
if not secret:
7266
print("⚠️ No webhook secret set, skipping verification")
7367
return True
@@ -79,10 +73,8 @@ def verify_github_signature(payload_body, signature, secret):
7973
expected_signature = "sha256=" + mac.hexdigest()
8074
return hmac.compare_digest(expected_signature, signature)
8175

82-
8376
# --- Convert UTC timestamp to UTC+4 ---
8477
def convert_to_utc4(timestamp):
85-
"""Convert ISO UTC timestamp string to UTC+4 formatted datetime string."""
8678
if not timestamp:
8779
return "N/A"
8880
try:
@@ -93,10 +85,8 @@ def convert_to_utc4(timestamp):
9385
print(f"⚠️ Failed to convert timestamp {timestamp}: {e}")
9486
return timestamp
9587

96-
9788
# --- Format GitHub repository event for email ---
9889
def format_repo_event(repo, action):
99-
"""Generate subject + body text for repository created/deleted events."""
10090
repo_name = repo["full_name"]
10191
visibility_icon = "🔒 Private" if repo.get("private") else "🌐 Public"
10292
owner = repo["owner"]["login"]
@@ -118,20 +108,20 @@ def format_repo_event(repo, action):
118108
)
119109
return subject, body
120110

121-
122-
# --- Flask Handlers (only if not in TEST_MODE) ---
111+
# --- GitHub Webhook + Health Handlers ---
123112
if not TEST_MODE:
124113
@app.route("/webhook", methods=["POST"])
125114
def github_webhook():
126115
payload_body = request.data
127116
signature = request.headers.get("X-Hub-Signature-256")
117+
secret = os.getenv("GITHUB_WEBHOOK_SECRET")
128118

129119
print("📥 Incoming GitHub webhook")
130120
print(f"📥 Event: {request.headers.get('X-GitHub-Event')}")
131121
print(f"📥 Signature header: {signature}")
132122

133-
if not verify_github_signature(payload_body, signature, GITHUB_WEBHOOK_SECRET):
134-
print("❌ Invalid signature! Webhook rejected.")
123+
if not verify_github_signature(payload_body, signature, secret):
124+
print(f"❌ Invalid signature! Webhook rejected.")
135125
return "❌ Invalid signature", 401
136126

137127
try:
@@ -143,7 +133,18 @@ def github_webhook():
143133
event = request.headers.get("X-GitHub-Event", "")
144134
action = data.get("action", "")
145135

146-
if event == "repository" and action in ["created", "deleted"]:
136+
repo_actions = [
137+
"created",
138+
"deleted",
139+
"publicized", # private → public
140+
"privatized", # public → private
141+
"archived",
142+
"unarchived",
143+
"renamed",
144+
"transferred"
145+
]
146+
147+
if event == "repository" and action in repo_actions:
147148
subject, body = format_repo_event(data["repository"], action)
148149
print(f"📩 Sending email alert: {subject}")
149150
send_email_via_graph(subject, body)
@@ -156,11 +157,10 @@ def github_webhook():
156157
def health_check():
157158
return {"status": "running"}, 200
158159

159-
160160
# --- Main Entry Point ---
161161
if __name__ == "__main__":
162162
if TEST_MODE:
163-
print("🔹 TEST_MODE enabled: sending test email...")
163+
print("🔹 TEST_MODE: sending test email")
164164
test_repo = {
165165
"full_name": "quantori/sadsrepo",
166166
"private": True,
@@ -170,7 +170,7 @@ def health_check():
170170
"updated_at": "2025-09-09T13:09:20Z",
171171
"html_url": "https://github.com/quantori/sadsrepo"
172172
}
173-
subject, body = format_repo_event(test_repo, "created")
173+
subject, body = format_repo_event(test_repo, "publicized")
174174
send_email_via_graph(subject, body)
175175
else:
176176
print("✅ Flask is up and listening on /webhook and /health")

0 commit comments

Comments
 (0)