File size: 4,794 Bytes
6db87f4
5db9ef3
f3aa8db
c2bbd91
f3aa8db
 
 
fe5f164
 
 
6db87f4
dce68b5
15cd72a
c2bbd91
5db9ef3
d6c2f43
 
5db9ef3
d6c2f43
 
 
 
 
 
8ebc299
d6c2f43
 
 
5db9ef3
f3aa8db
d6c2f43
 
 
fe5f164
d6c2f43
fe5f164
d6c2f43
fe5f164
5db9ef3
d6c2f43
 
 
 
 
8ebc299
c3f2fbf
8ebc299
 
 
 
 
 
 
cc9ac5d
dce68b5
d6c2f43
 
e09248b
 
5db9ef3
d6c2f43
5db9ef3
d6c2f43
 
5db9ef3
 
 
 
 
 
d6c2f43
5db9ef3
dce68b5
d6c2f43
fe5f164
d6c2f43
fe5f164
dce68b5
c3f2fbf
 
 
 
dce68b5
d6c2f43
 
 
 
 
 
 
 
fe5f164
dce68b5
fe5f164
 
d6c2f43
 
fe5f164
 
5db9ef3
 
 
dce68b5
 
 
 
 
 
e09248b
fe5f164
5db9ef3
dce68b5
5db9ef3
 
c2bbd91
dce68b5
c2bbd91
 
 
 
 
5db9ef3
dce68b5
6db87f4
 
1258978
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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()