Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from analyze_email_main import analyze | |
| from weasyprint import HTML | |
| import tempfile | |
| def html_to_pdf(html_content): | |
| """Convert HTML string to a temporary PDF file and return its path.""" | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf: | |
| HTML(string=html_content).write_pdf(tmp_pdf.name) | |
| return tmp_pdf.name | |
| def analyze_email(file_path): | |
| if file_path is None: | |
| return "<p style='color:red;'>Please upload a .eml file to analyze.</p>", None | |
| # Get structured results | |
| summary, details = analyze(file_path) | |
| # Safely extract summary fields | |
| attack_score = summary.get("Attack Score", 0) | |
| try: | |
| score_val = int(round(float(attack_score))) | |
| except Exception: | |
| score_val = 0 | |
| score_val = max(0, min(score_val, 100)) | |
| attack_type = summary.get("Attack Type", "Unknown") | |
| verdict = summary.get("Final Verdict", "No Verdict") | |
| # Verdict color | |
| verdict_color = "#2ecc71" | |
| v_lower = verdict.lower() | |
| if "malicious" in v_lower: | |
| verdict_color = "#e74c3c" | |
| elif "suspicious" in v_lower: | |
| verdict_color = "#e67e22" | |
| elif "spam" in v_lower: | |
| verdict_color = "#f1c40f" | |
| # Collect details safely | |
| header_findings = details.get("Header Findings", []) or [] | |
| body_findings = details.get("Body Findings", []) or [] | |
| url_findings = details.get("URL Findings", []) or [] | |
| highlighted_body = details.get("Highlighted Body", "") or "" | |
| auth_results = details.get("Auth Results", None) | |
| # Render authentication results safely | |
| if isinstance(auth_results, dict): | |
| auth_html = "<ul>" + "".join(f"<li>{k.upper()}: {v}</li>" for k, v in auth_results.items()) + "</ul>" | |
| elif isinstance(auth_results, str): | |
| auth_html = f"<p>{auth_results}</p>" | |
| else: | |
| auth_html = "<p>No auth results found.</p>" | |
| # Tags | |
| main_tags_str = summary.get("Main Tags", "") | |
| tags = [t.strip() for t in main_tags_str.split(",")] if main_tags_str else [] | |
| # HTML Report | |
| html = f""" | |
| <div style='font-family: Arial, sans-serif; padding: 20px; max-width: 900px; margin:auto;'> | |
| <h2 style="color:#2c3e50;">π§ Email Security Report</h2> | |
| <h3 style="margin-bottom:6px;">Attack Score</h3> | |
| <div style="background:#ecf0f1; border-radius:10px; overflow:hidden; height:24px; width:100%; margin-bottom:8px;"> | |
| <div style="width:{score_val}%; background:#3498db; height:100%; text-align:center; color:white; line-height:24px;"> | |
| {score_val}/100 | |
| </div> | |
| </div> | |
| <p><b>Attack Type:</b> {attack_type}</p> | |
| <p><b>Final Verdict:</b> <span style="background:{verdict_color}; color:white; padding:4px 10px; border-radius:6px;"> | |
| {verdict} | |
| </span></p> | |
| <details style="margin-top:15px;" open> | |
| <summary>π Attack Analysis Tags ({len(tags)})</summary> | |
| {"<ul>" + "".join(f"<li>{tag}</li>" for tag in tags if tag) + "</ul>" if tags else "<p>No special tags</p>"} | |
| </details> | |
| <details style="margin-top:15px;" open> | |
| <summary>π‘ Authentication Results</summary> | |
| {auth_html} | |
| </details> | |
| <details style="margin-top:15px;" open> | |
| <summary>π΅οΈ Detailed Findings</summary> | |
| <h4>Headers ({len(header_findings)})</h4> | |
| {"<ul>" + "".join(f"<li>{f}</li>" for f in header_findings) + "</ul>" if header_findings else "<p>No header findings.</p>"} | |
| <h4>Body ({len(body_findings)})</h4> | |
| {"<ul>" + "".join(f"<li>{f}</li>" for f in body_findings) + "</ul>" if body_findings else "<p>No body findings.</p>"} | |
| <h4>URLs ({len(url_findings)})</h4> | |
| {"<ul>" + "".join(f"<li>{f}</li>" for f in url_findings) + "</ul>" if url_findings else "<p>No URL findings.</p>"} | |
| </details> | |
| <details style="margin-top:15px;"> | |
| <summary>π© Highlighted Email Body</summary> | |
| <div style='border:1px solid #ccc; padding:15px; background:#fdfdfd; border-radius:8px; white-space:pre-wrap;'> | |
| {highlighted_body} | |
| </div> | |
| </details> | |
| </div> | |
| """ | |
| # ALWAYS generate PDF | |
| try: | |
| pdf_path = html_to_pdf(html) | |
| except Exception as e: | |
| pdf_path = None | |
| html += f"<p style='color:#c0392b;'><b>PDF export failed:</b> {e}</p>" | |
| return html, pdf_path | |
| # Gradio Interface (checkbox removed) | |
| demo = gr.Interface( | |
| fn=analyze_email, | |
| inputs=[ | |
| gr.File(label="Upload .eml File", type="filepath") | |
| ], | |
| outputs=[ | |
| gr.HTML(label="Analysis Report"), | |
| gr.File(label="Download PDF Report") | |
| ], | |
| title="π§ Email Security Analyzer", | |
| description="Upload an .eml file to detect phishing, spam, or malicious emails. A PDF report will be generated automatically." | |
| ) | |
| demo.launch() | |