Triage forwarded phishing reports and post verdicts to Slack

By General Input

Every 20 minutes, suspicious emails your staff forward get their links safely scanned and a clear verdict posted to your security channel.

Integrations

  • Gmail
  • urlscan.io
  • Slack Bot

Type

Agentic Task

Categories

  • Operations
  • Engineering

I want to triage the suspicious emails my staff forward to our phishing report mailbox, so my security team stops doing it by hand. Use a cron trigger that runs every 20 minutes during business hours, Monday to Friday between 8am and 6pm in our local timezone.

Start with Gmail List Messages to pull unread messages carrying our "Phishing Reports" label, which is the label applied to everything sent to our phishing@ alias. For each message returned, call Gmail Get a Message using the full format so you can read the complete body along with the headers, including the From address, Reply-To, Return-Path, and Subject. Note who forwarded the report as well as the original sender inside it.

Extract every URL you find in the message body and headers. Before scanning anything, skip URLs that point at our own corporate domains, and skip links from common safe senders and routine infrastructure such as unsubscribe and tracking links belonging to vendors we already trust. This saves scan quota and avoids handing internal links to a third party. Keep track of what you skipped and why, so it can be mentioned in the summary.

Send each remaining URL to urlscan Submit URL Scan, and always set visibility to private. This is not optional. Publicly submitted URLs can be seen by anyone browsing urlscan, and reported phishing emails routinely contain password reset links, account confirmation links, and internal document URLs with tokens embedded in them. Real organisations have leaked exactly this kind of link by letting an automated playbook submit scans publicly. If visibility is omitted, the account default applies and that default may be public, so set it explicitly on every single submission.

Scanning is asynchronous and takes roughly 10 to 30 seconds. After submitting, wait, then call urlscan Get Scan Result with the UUID that the submission returned. A 404 response means the scan is not ready yet, not that it failed, so wait a few seconds and retry, up to about a minute per URL before giving up on that one and saying so in the output. From the finished result, read the overall verdict, the malicious score, and the detected brand impersonation target when the result includes one.

Do not simply forward a raw score. Weigh the urlscan verdict alongside the sender address and how it relates to any brand being impersonated, the tone and content of the email body, and whether links had to be skipped. A clean score on a URL sent from a lookalike domain impersonating our bank still deserves a human look, and a scary looking score on a well known marketing tracker usually does not.

Post one consolidated message per reported email to our security channel using the Slack Bot integration's Send a Message action, so alerts are attributed to the automation rather than to a person. Do not post a separate message per URL. Each message should say clearly whether the report looks malicious, benign, or needs a human look, and should include who reported it, the original sender, the subject, each scanned URL with its verdict and malicious score, the brand being impersonated if one was detected, a count of any skipped links, and the urlscan result link for each scan. Close with a short plain English assessment explaining the call.

Defang every suspicious URL in the Slack output so nobody clicks one by accident. Write hxxp in place of http and wrap the dots in square brackets, so that example.com becomes example[.]com. Apply the same treatment to any domains that appear in the sender address or subject line. The urlscan result links themselves are safe and should be left clickable.

Finish each report with Gmail Modify Message Labels on that message to mark it triaged, removing the UNREAD label and adding a "Triaged" label, so the next run does not process it a second time. Only mark a message triaged after its Slack message has actually been posted, so nothing is silently swallowed if a step fails.

Related prompts

Explore more prompts
Win back LiveChat visitors whose chats went unansweredA brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasonLiveChat coverage board for planning next week's shiftsPhone routing control panel for LiveKit voice agentsLinkedIn Ads budget pacing dashboard for every client accountGive your team Looker numbers without buying more seats