princemaxp commited on
Commit
c838a25
Β·
verified Β·
1 Parent(s): 07d9eff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -56
app.py CHANGED
@@ -2,125 +2,145 @@ import gradio as gr
2
  from analyze_email_main import analyze
3
  from weasyprint import HTML
4
  import tempfile
 
 
5
 
6
  def html_to_pdf(html_content):
7
- """Convert HTML string to a temporary PDF file and return its path."""
8
  with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf:
9
  HTML(string=html_content).write_pdf(tmp_pdf.name)
10
  return tmp_pdf.name
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def analyze_email(file_path):
13
  if file_path is None:
14
- return "<p style='color:red;'>Please upload a .eml file to analyze.</p>", None
15
 
16
- # Get structured results
17
  summary, details = analyze(file_path)
18
 
19
- # Safely extract summary fields
20
- attack_score = summary.get("Attack Score", 0)
21
- try:
22
- score_val = int(round(float(attack_score)))
23
- except Exception:
24
- score_val = 0
25
- score_val = max(0, min(score_val, 100))
26
 
27
  attack_type = summary.get("Attack Type", "Unknown")
28
  verdict = summary.get("Final Verdict", "No Verdict")
29
 
30
  # Verdict color
31
  verdict_color = "#2ecc71"
32
- v_lower = verdict.lower()
33
- if "malicious" in v_lower:
34
  verdict_color = "#e74c3c"
35
- elif "suspicious" in v_lower:
36
  verdict_color = "#e67e22"
37
- elif "spam" in v_lower:
38
- verdict_color = "#f1c40f"
39
 
40
- # Collect details safely
41
  header_findings = details.get("Header Findings", []) or []
42
  body_findings = details.get("Body Findings", []) or []
43
  url_findings = details.get("URL Findings", []) or []
44
  highlighted_body = details.get("Highlighted Body", "") or ""
45
- auth_results = details.get("Auth Results", None)
46
 
47
- # Render authentication results safely
48
  if isinstance(auth_results, dict):
49
- auth_html = "<ul>" + "".join(f"<li>{k.upper()}: {v}</li>" for k, v in auth_results.items()) + "</ul>"
50
- elif isinstance(auth_results, str):
51
- auth_html = f"<p>{auth_results}</p>"
52
  else:
53
- auth_html = "<p>No auth results found.</p>"
54
 
55
- # Tags
56
- main_tags_str = summary.get("Main Tags", "")
57
- tags = [t.strip() for t in main_tags_str.split(",")] if main_tags_str else []
 
 
 
 
 
 
58
 
59
- # HTML Report
60
  html = f"""
61
- <div style='font-family: Arial, sans-serif; padding: 20px; max-width: 900px; margin:auto;'>
62
- <h2 style="color:#2c3e50;">πŸ“§ Email Security Report</h2>
63
- <h3 style="margin-bottom:6px;">Attack Score</h3>
64
- <div style="background:#ecf0f1; border-radius:10px; overflow:hidden; height:24px; width:100%; margin-bottom:8px;">
65
- <div style="width:{score_val}%; background:#3498db; height:100%; text-align:center; color:white; line-height:24px;">
 
 
 
66
  {score_val}/100
67
  </div>
68
  </div>
69
- <p><b>Attack Type:</b> {attack_type}</p>
70
- <p><b>Final Verdict:</b> <span style="background:{verdict_color}; color:white; padding:4px 10px; border-radius:6px;">
71
- {verdict}
72
- </span></p>
73
 
74
- <details style="margin-top:15px;" open>
 
 
 
 
 
 
 
 
75
  <summary>πŸ”– Attack Analysis Tags ({len(tags)})</summary>
76
- {"<ul>" + "".join(f"<li>{tag}</li>" for tag in tags if tag) + "</ul>" if tags else "<p>No special tags</p>"}
77
  </details>
78
 
79
- <details style="margin-top:15px;" open>
80
  <summary>πŸ›‘ Authentication Results</summary>
81
  {auth_html}
82
  </details>
83
 
84
- <details style="margin-top:15px;" open>
85
  <summary>πŸ•΅οΈ Detailed Findings</summary>
86
- <h4>Headers ({len(header_findings)})</h4>
87
- {"<ul>" + "".join(f"<li>{f}</li>" for f in header_findings) + "</ul>" if header_findings else "<p>No header findings.</p>"}
88
- <h4>Body ({len(body_findings)})</h4>
89
- {"<ul>" + "".join(f"<li>{f}</li>" for f in body_findings) + "</ul>" if body_findings else "<p>No body findings.</p>"}
90
- <h4>URLs ({len(url_findings)})</h4>
91
- {"<ul>" + "".join(f"<li>{f}</li>" for f in url_findings) + "</ul>" if url_findings else "<p>No URL findings.</p>"}
92
  </details>
93
 
94
- <details style="margin-top:15px;">
95
  <summary>πŸ“© Highlighted Email Body</summary>
96
- <div style='border:1px solid #ccc; padding:15px; background:#fdfdfd; border-radius:8px; white-space:pre-wrap;'>
 
 
97
  {highlighted_body}
98
  </div>
99
  </details>
100
  </div>
101
  """
102
 
103
- # ALWAYS generate PDF
104
  try:
105
  pdf_path = html_to_pdf(html)
106
- except Exception as e:
107
  pdf_path = None
108
- html += f"<p style='color:#c0392b;'><b>PDF export failed:</b> {e}</p>"
109
 
110
  return html, pdf_path
111
 
112
- # Gradio Interface (checkbox removed)
113
  demo = gr.Interface(
114
  fn=analyze_email,
115
- inputs=[
116
- gr.File(label="Upload .eml File", type="filepath")
117
- ],
118
  outputs=[
119
  gr.HTML(label="Analysis Report"),
120
- gr.File(label="Download PDF Report")
121
  ],
122
  title="πŸ“§ Email Security Analyzer",
123
- description="Upload an .eml file to detect phishing, spam, or malicious emails. A PDF report will be generated automatically."
124
  )
125
 
126
  demo.launch()
 
2
  from analyze_email_main import analyze
3
  from weasyprint import HTML
4
  import tempfile
5
+ import re
6
+
7
 
8
  def html_to_pdf(html_content):
 
9
  with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf:
10
  HTML(string=html_content).write_pdf(tmp_pdf.name)
11
  return tmp_pdf.name
12
 
13
+
14
+ def normalize_score(raw_score):
15
+ """
16
+ Accepts: int, float, '85', '85/100'
17
+ Returns: int 0–100
18
+ """
19
+ if isinstance(raw_score, (int, float)):
20
+ return max(0, min(int(raw_score), 100))
21
+
22
+ if isinstance(raw_score, str):
23
+ m = re.search(r"\d+", raw_score)
24
+ if m:
25
+ return max(0, min(int(m.group()), 100))
26
+
27
+ return 0
28
+
29
+
30
  def analyze_email(file_path):
31
  if file_path is None:
32
+ return "<p style='color:red;'>Please upload a .eml file.</p>", None
33
 
 
34
  summary, details = analyze(file_path)
35
 
36
+ # πŸ”₯ FIXED SCORE HANDLING
37
+ raw_score = summary.get("Attack Score", 0)
38
+ score_val = normalize_score(raw_score)
 
 
 
 
39
 
40
  attack_type = summary.get("Attack Type", "Unknown")
41
  verdict = summary.get("Final Verdict", "No Verdict")
42
 
43
  # Verdict color
44
  verdict_color = "#2ecc71"
45
+ v = verdict.lower()
46
+ if "malicious" in v:
47
  verdict_color = "#e74c3c"
48
+ elif "suspicious" in v:
49
  verdict_color = "#e67e22"
 
 
50
 
 
51
  header_findings = details.get("Header Findings", []) or []
52
  body_findings = details.get("Body Findings", []) or []
53
  url_findings = details.get("URL Findings", []) or []
54
  highlighted_body = details.get("Highlighted Body", "") or ""
55
+ auth_results = details.get("Auth Results", {})
56
 
57
+ # Auth rendering
58
  if isinstance(auth_results, dict):
59
+ auth_html = "<ul>" + "".join(
60
+ f"<li>{k.upper()}: {v}</li>" for k, v in auth_results.items()
61
+ ) + "</ul>"
62
  else:
63
+ auth_html = f"<p>{auth_results}</p>"
64
 
65
+ tags = [
66
+ t.strip()
67
+ for t in (summary.get("Main Tags") or "").split(",")
68
+ if t.strip()
69
+ ]
70
+
71
+ # πŸ”₯ DARK MODE SAFE BODY
72
+ body_bg = "#fdfdfd"
73
+ body_fg = "#000000"
74
 
 
75
  html = f"""
76
+ <div style="font-family:Arial; max-width:900px; margin:auto; padding:20px;">
77
+ <h2>πŸ“§ Email Security Report</h2>
78
+
79
+ <h3>Attack Score</h3>
80
+ <div style="background:#e0e0e0; border-radius:10px; height:24px;">
81
+ <div style="width:{score_val}%; background:#3498db; height:100%;
82
+ border-radius:10px; color:white; text-align:center;
83
+ line-height:24px;">
84
  {score_val}/100
85
  </div>
86
  </div>
 
 
 
 
87
 
88
+ <p><b>Attack Type:</b> {attack_type}</p>
89
+ <p><b>Final Verdict:</b>
90
+ <span style="background:{verdict_color}; color:white;
91
+ padding:4px 10px; border-radius:6px;">
92
+ {verdict}
93
+ </span>
94
+ </p>
95
+
96
+ <details open>
97
  <summary>πŸ”– Attack Analysis Tags ({len(tags)})</summary>
98
+ {"<ul>" + "".join(f"<li>{t}</li>" for t in tags) + "</ul>" if tags else "<p>None</p>"}
99
  </details>
100
 
101
+ <details open>
102
  <summary>πŸ›‘ Authentication Results</summary>
103
  {auth_html}
104
  </details>
105
 
106
+ <details open>
107
  <summary>πŸ•΅οΈ Detailed Findings</summary>
108
+ <h4>Headers</h4>
109
+ {"<ul>" + "".join(f"<li>{f}</li>" for f in header_findings) + "</ul>"}
110
+ <h4>Body</h4>
111
+ {"<ul>" + "".join(f"<li>{f}</li>" for f in body_findings) + "</ul>"}
112
+ <h4>URLs</h4>
113
+ {"<ul>" + "".join(f"<li>{f}</li>" for f in url_findings) + "</ul>"}
114
  </details>
115
 
116
+ <details>
117
  <summary>πŸ“© Highlighted Email Body</summary>
118
+ <div style="background:{body_bg}; color:{body_fg};
119
+ padding:15px; border-radius:8px;
120
+ white-space:pre-wrap;">
121
  {highlighted_body}
122
  </div>
123
  </details>
124
  </div>
125
  """
126
 
 
127
  try:
128
  pdf_path = html_to_pdf(html)
129
+ except Exception:
130
  pdf_path = None
 
131
 
132
  return html, pdf_path
133
 
134
+
135
  demo = gr.Interface(
136
  fn=analyze_email,
137
+ inputs=gr.File(label="Upload .eml File", type="filepath"),
 
 
138
  outputs=[
139
  gr.HTML(label="Analysis Report"),
140
+ gr.File(label="Download PDF Report"),
141
  ],
142
  title="πŸ“§ Email Security Analyzer",
143
+ description="Upload an .eml file to analyze threats."
144
  )
145
 
146
  demo.launch()