Automation · IT and security
How to build phishing report triage
Forty people report the same email, forty tickets open, and the copies are still sitting in four hundred inboxes. The design behind triage that treats a campaign as one case, the prompts that build it, and what running it takes.
Built with Tray Headless
- System Gmail
- Step Check the email
- Step Group by campaign
- Step Find every copy
- System Jira
Reports are grouped by campaign before anyone looks, so forty reports of one email become one case, and one search pulls every copy.
The short answer
What is phishing report triage automation?
Phishing report triage has four parts: checking each reported email automatically for the sender, links, attachments and look-alike domains, grouping reports of the same email into one campaign case, finding and removing every other copy across the company once a campaign is confirmed, and replying to every reporter with the verdict. Teams usually come unstuck on the grouping. Without it, forty reports are forty tickets, the analyst works the same email forty times, and the copies nobody reported stay in the inbox.
Stage 3 of 7: Phishing report triage. Part of Security operations, end to end : every stage, the systems it runs on and the guide that builds it.
What matters here
- Group reports by campaign before anyone looks. Forty reports of one email is one case.
- Check the email automatically first: sender, reply-to, links, attachments and how new the sending domain is.
- Once a campaign is confirmed, find every copy, not just the reported ones. Most recipients never report.
- Check who clicked. A removed email still matters if somebody entered a password before it was pulled.
- Reply to every reporter with the verdict. People who hear back keep reporting.
Who this is for
You run security operations. The phishing mailbox fills faster than anybody can read it, and the reports you do read are mostly marketing email.
How it works in practice
From an employee pressing the report button to the campaign being closed.
- 1
The reported email is read from the phishing mailbox
With its full headers and attachments, not a forwarded copy that has lost them.
- 2
The email is checked automatically
Sender and reply-to, authentication results, link destinations, attachment types and the age of the sending domain.
- 3
Reports of the same email are grouped into one case
Same sender, subject pattern, links or attachment, within a window.
- 4
Clear cases are decided, the rest go to an analyst
Known marketing and internal mail are closed. Anything unclear arrives with the checks already done.
- 5
A confirmed campaign is pulled from every inbox
Every copy, reported or not, with a list of who opened it and who clicked.
- 6
Every reporter hears the verdict
Safe, spam or phishing, with a thank you. The answer is what keeps people reporting.
What phishing triage is made of
Four parts, and the second decides how much of the analyst's day goes on the same email.
Automatic checks
Sender, reply-to, authentication results, link destinations, attachments, and how recently the sending domain was registered.
Campaign grouping
Reports of the same email become one case with a count. The analyst decides once, and the decision applies to every report.
Company-wide removal
Once a campaign is confirmed, every copy is found and removed, and the people who clicked are listed for follow-up.
A reply to every reporter
The verdict, in plain words, within the day. Reporting falls off fast when nobody answers.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up, then read reports with their headers
A forwarded copy has lost the evidence.
Headless skills
build-workflowUse build-workflow. The systems in play are Gmail or Microsoft Outlook for the phishing mailbox, Google Workspace with domain-wide access or the Microsoft 365 admin API for searching every mailbox, Office365 Management for mailbox activity, Okta, Jira, Slack and Snowflake, or whatever we run in those seats. Before you plan anything, tell me which of them are already authenticated in the workspace, because I do not want a connector stubbed that I have not authenticated. Read each report from the phishing mailbox with the original email attached, including its full headers and attachments. If the report button forwards a copy instead of attaching the original, tell me, because the headers are what most of the checks need.
- 2
Check every reported email automatically
Most reports can be decided from facts a machine can look up.
Headless skills
build-workflowUse build-workflow. For every reported email, record: Sender, reply-to, and whether they differ Whether the email passed sender authentication Whether the sender is internal, a known supplier, or a known marketing platform we use Every link, where it really goes, and how new that domain is Attachment types, and whether any are macros, archives or scripts Look-alike domains: our own name with a letter changed Close the clear cases automatically: our own marketing tools, internal mail that passed authentication, and newsletters people subscribed to. Send everything else to triage with the checks attached.
Closing the clear cases is most of the value. Every reported newsletter and internal notice used to take an analyst a few minutes.
- 3
Group reports into campaigns
Forty reports of one email is one case.
Before opening a case, group reports that share a sender, a link domain, an attachment, or a subject pattern, within a 24 hour window. Open one case per campaign in Jira with: the count of reports, the first and latest report time, the checks, and one example email. Add later reports to the same case instead of opening new ones. When the analyst gives a verdict on the case, apply it to every report in it.
- 4
Pull every copy, and find who clicked
Most recipients never report.
Headless skills
tray-gotchasUse tray-gotchas. When a case is confirmed as phishing, search every mailbox for copies of the email by sender, subject and link, and list them with the recipient and whether each was opened. Removing copies from every mailbox needs an analyst's approval in Slack, showing the count and three example recipients. Once approved, move them to a held folder rather than deleting them, so a wrong call can be put back, and record each removal on the case. Then check who clicked or replied. For anyone who entered a password on a phishing page, open a compromised account case rather than treating it as part of this one.
- 5
Reply to every reporter
People who hear back keep reporting.
When a case closes, reply to every reporter with the verdict in plain words: safe, unwanted marketing, or phishing that has now been removed. Thank them either way. Report monthly: reports received, share closed automatically, time to verdict, campaigns confirmed, copies removed, and the share of recipients who reported a confirmed campaign.
- 6
Validate it, then hand the rules to security ops
Because the safe-sender list is a security decision with an owner.
Run the per-step schema checks and the whole-workflow audit before this touches production. Run it shadow for two weeks: check and group everything, close nothing, remove nothing, and compare its calls with what analysts decided. Then open the same workflow in Tray Build so security operations can manage the safe-sender list, the grouping window and the auto-close rules in the visual canvas.
What it connects to
Reports arrive in one mailbox, and the copies sit in everyone else's.
Microsoft Outlook
Read reports from the phishing mailbox where the company runs on Microsoft 365.
Reads
Google Workspace
With domain-wide access, search every mailbox for copies of a confirmed campaign and move them to a held folder once approved. On Microsoft 365 the same step runs through its admin API.
Reads and writes
Office365 Management
Read mailbox and sign-in activity, to see who received, opened or acted on a campaign.
Reads
Okta
Look up each recipient, and hand anyone who entered a password to the compromised account workflow.
Reads
Snowflake
Land every report and verdict, so auto-close accuracy and time to verdict are measurable.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Google BigQuery, Microsoft Teams, Azure Active Directory, ServiceNow, Databricks or Google Chat.
Connections in this build
Field mapping, templates and common problems for each pairing: G-Suite + Okta, Office365 Management + Okta, Gmail + Jira and Gmail + Slack.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This reads and removes mail across the company. It has to be careful, and it has to show its work.
It runs where production runs, not on a laptop
Reports are checked and grouped as they arrive, at whatever volume a campaign produces, with every decision recorded.
Removal always has an approver
Pulling mail from every inbox needs an analyst's yes, with the count and examples in front of them. Every removal is on the case.
Managed credentials, not secrets in a config file
Searching every mailbox is one of the most sensitive permissions you hold. It is a scoped authentication in your workspace, never written into the build.
Security ops own the rules
The safe-sender list, grouping window and auto-close rules open in Tray Build, owned by the team that answers for a miss.
Run it shadow first
Two weeks checking and grouping while closing nothing, compared against what analysts decided. That comparison sets the auto-close rules.
Questions people ask
Why group reports by campaign?
Because forty reports of one email is one decision. Without grouping, the analyst works the same email forty times and the queue looks forty times worse than it is.
Why remove copies nobody reported?
Because most recipients never report. The reported copies are a sample of the campaign, not the whole of it.
Should removal be automatic?
No. Pulling mail from every inbox goes to an analyst for approval, with the count and examples in front of them. Copies are held rather than deleted, so a wrong call can be put back.
What about people who already clicked?
Anyone who entered a password on a phishing page gets a compromised account case of their own, with sessions revoked and their sign-in reset.
Why reply to every reporter?
Because people who hear back keep reporting, and people who don't, stop. Reports are the cheapest detection the company has.
Related guides
IT and security
How to build compromised account response
Ask the user about a risky sign-in, revoke every session in every app on a confirmed takeover, and remove what the attacker left behind. The prompts.
IT and security
How to build security alert triage
Enrich before a human sees it, suppress the known-benign, escalate on asset value, and measure what you closed rather than what fired. The prompts.
IT and security
How to build endpoint alert containment
Decide which endpoint detections isolate a device on a rule and which need a person, contain the account, tell the user, and release cleanly. The prompts.
Last reviewed October 2026.