A lab tool for triaging suspicious emails. Paste raw email content, or upload an .eml, .msg (Outlook), or .txt file, and it breaks down what it found, tells you what to do about it, and hands you something reusable to take away.
Everything runs server-side and entirely offline. No email content, no extracted URL, and no filename is ever sent to a third-party API. Uploaded files are parsed in memory only, never written to disk, and are bounded by strict size limits before any parsing happens. Attachments are treated the same way: only the filename and declared type are looked at, the contents are never opened.
What it checks
Authentication. SPF, DKIM and DMARC results read straight from the message's own headers, including the softer cases most tools skip: DMARC enforcement being applied, a domain publishing no policy at all, a missing signature rather than a failed one. From, Return-Path and Reply-To are compared at the registrable domain, so a company sending through its own bounce subdomain is not treated as a mismatch.
Those results are read at face value, because nothing here makes a DNS query of its own to independently verify SPF, DKIM, or DMARC. That is worth naming as a gap on its own, not just living with quietly: a header claiming a pass can be hand-crafted by whoever sent the message, before it ever reached a real mail server. So the tool cross-references the claimed server against the message's own delivery path. If the header says one server checked it but the actual chain shows the message was received somewhere else entirely, that discrepancy is surfaced. A security filter legitimately sitting in the path can produce the same shape, so it is not treated as proof on its own, only as something worth a second look.
The delivery path. The Received chain is walked oldest hop first. This is the part of a message an attacker cannot fully forge: they can prepend whatever headers they like, but every hop after the injection point is written by servers they do not control, and those servers record both the name the sender announced and the name their own lookup returned. When those two disagree, that is a spoofing indicator obtained without a single network request. The chain also catches timestamps running backwards, which means a hop was fabricated, since no server can rewrite the clocks of the servers further along the path.
Links. Typosquats, including lookalike character substitutions such as paypa1.com and rnicrosoft.com. Brand names planted in a subdomain or hyphenated into an unrelated domain, which is the shape most real phishing takes and which is not a typosquat at all because the spelling is exact. Userinfo tricks, raw IP addresses in their various notations, unusual ports, links straight to an executable, shorteners, and abuse-prone TLDs.
Lookalike domains, decoded. Telling someone a hostname "uses punycode" is true and useless. The tool decodes it and shows what it actually reads as, so xn--pypal-4ve.com is presented as pаypal.com with the Cyrillic character called out. Two different tricks get reported separately, because a test for one misses the other: a mostly-Latin word with a single foreign character substituted in, and a word written entirely in another script chosen to look Latin. Genuinely international domains are left alone.
Deceptive link text. A link whose visible text names one destination while it actually points at another. This only exists in the HTML part of a message, which is exactly where the trick lives.
Links with no destination to check at all. A data: link can carry an entire fake page encoded inline, with no domain in it anywhere for any of the checks above to look at. A javascript: link just runs code the moment it is clicked. Neither belongs in an email, and both used to slip past every other link check for exactly the reason they are dangerous: there was nothing resembling a URL for those checks to find.
Content. Urgency and pressure language, credential and financial requests, authority impersonation, generic greetings, and display-name spoofing. The subject line and the visible text of the HTML part are both scanned, not just the plain text body, because a message can carry a harmless-looking plain text part alongside an HTML part doing the real work.
Thread hijacking. A message that presents itself as a reply or forward inside an existing conversation, carrying the real technical headers a mail client generates from an actual prior message, while simultaneously failing a genuine authentication check. Ordinary phishing has no reason to fake thread continuity at all, so that specific combination points at something more particular: a compromised account, or a hijacked thread built from a real one.
Attachments. Executables, double extensions like invoice.pdf.exe, macro-enabled Office documents, disk images, shortcut and script containers, archives, and a declared type that contradicts the filename, such as a .jpg whose message metadata calls it a Windows executable. Filename and declared type only. For messages submitted as raw text or an .eml file, an MD5, SHA-1, and SHA-256 are also computed over each attachment's raw bytes, since the parser already holds them in memory as an ordinary part of reading the message. That is not a change to what gets opened: a hash treats a file as an undifferentiated block of bytes and never interprets its format, so it carries none of the risk that actually parsing a file would. Outlook .msg uploads don't get a hash, because that parser never reads attachment bytes at all, by design, and this doesn't change that.
How it scores
The scoring model is the part I care most about, because getting it wrong is how a tool ends up technically correct and practically useless.
Findings carry a category and a severity rather than a hand-picked number. Within a category the strongest finding counts in full and the rest count for much less. That matters more than it sounds: SPF, DKIM and DMARC all failing is one fact, that the message is not authenticated, not three independent pieces of evidence. Adding them up meant an ordinary unauthenticated message scored as high risk before it had done anything phishy at all.
Categories are treated as the independent axes, and no single one can reach the top band by itself. Getting a high-risk verdict takes evidence in more than one place, which is how phishing actually presents.
Evidence is also allowed to argue both ways. An aligned authentication pass, a message with no links in it at all, the ordinary machinery of a legitimate bulk sender: these lower the score. They stop mattering the moment something serious fires, because plenty of real phishing is sent from perfectly configured infrastructure the attacker owns outright.
Confidence is reported separately from the score, along with a list of what could not be checked. "We looked at everything and found nothing" and "we could barely see anything" are very different answers and the report says which one you got.
What you get back
A verdict on its own is not much use to the person holding the email, so the report leads with what to do, ordered by urgency. The actions that come first are the ones that matter to someone who has already clicked: change the password, turn on multi-factor authentication, disconnect the machine. That window is measured in minutes, and it is exactly when someone goes looking for a tool like this.
Underneath that, for whoever is writing the incident up rather than deciding what is safe to click, there is a section with the delivery path laid out hop by hop, indicators defanged so they can be pasted into a ticket without turning into a live link, MITRE ATT&CK technique mappings, a generated Sigma rule built from what was actually observed, and the full result again as plain JSON, for whoever wants to feed it into a ticketing system or a playbook instead of only reading it on the page.
The Sigma rule is the piece that turns a single analyzed message into something reusable. It is deliberately labelled a starting point rather than a finished rule, in its own header comments, because email telemetry field names differ across every platform and a rule that looks ready to deploy but quietly matches nothing would be worse than no rule at all. One selection inside it is the exception: when an attachment hash is available, the rule includes it, and an exact hash match is high-confidence on its own in a way a domain or subject-line selection never is.
Where a computed hash appears, there is also a plain link to look it up on VirusTotal. It only opens if you click it, in your own browser, exactly the way the ATT&CK links already on the page work. Nothing here ever sends anything anywhere on its own.
That analyst section is collapsed by default, and printing a page in that state used to mean the browser simply left it out, delivery path and all, if you tried to save the report as a PDF for a ticket. It opens itself automatically the moment you print or export, and closes back up again afterward.
What it doesn't catch
Being upfront about the gaps matters as much as the feature list.
The phrase matching is English-only, so a phishing email in another language will score lower than it should on content alone.
Nothing here knows anything about reputation or history. Every check is structural, because the tool makes no external calls by design. It cannot tell you a domain was registered yesterday, or that an address has never written to you before. Both would mean sending what you submitted somewhere else, which is the one thing this tool promises not to do.
QR codes in images are not read. The tool says so in its own output when a message contains images. Hashing an attachment, which the tool does now, is not the same thing as opening it: a hash treats the bytes as an undifferentiated block and never interprets what they represent. Reading a QR code means actually decoding an image format and interpreting pixels, which is a real step past that line, and it would introduce decoding of hostile image data. It is the most significant gap left, and it is on the list rather than overlooked.
None of this replaces a person. A heuristic verdict is a starting point for a decision, not the decision.
Why it's built this way
Since this is a security company's own tool, handling other people's potentially malicious email, it was built defensively from the start:
- Output is HTML-escaped everywhere, verified against injected script and event-handler payloads.
- Unicode bidi-override and zero-width characters are stripped from any header text before it is displayed, so a crafted header cannot make a filename or domain visually read as something it is not. The same stripping now runs on the text the content checks actually scan, before matching happens rather than only before display, since the same invisible characters can be used to break up a word like "verify" and quietly defeat keyword matching.
- Hard size caps on uploads and on the text handed to the parsers, plus a per-IP rate limit, so the tool cannot be turned into a resource-exhaustion vector. Hostname comparisons are length-bounded for the same reason.
- Uploads are memory-only. A client-supplied filename is never used to read or write anything on disk.
- Nothing is stored. The submitted message and the resulting verdict are never logged or persisted anywhere, because a server that keeps other people's suspicious email is a liability dressed up as a feature.
- Nothing is sent anywhere automatically. The one link out to a third party, the optional VirusTotal lookup next to a hash, only fires if you click it yourself.
See it in action at /phish-report.