Triage forwarded phishing reports and post verdicts to Slack

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

Agentic Task
Gmailurlscan.ioSlack BotOperationsEngineeringFeedback TriageNotifications & Alerts
PromptCreate

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.

Example output

MALICIOUS - phishing report from dana.k@acme.com Original sender: security-alert@micros0ft-verify[.]com Subject: Unusual sign-in activity on your account 2 links scanned, 1 skipped (internal acme.com link) - hxxps://micros0ft-verify[.]com/login/reset Verdict: malicious, score 85, impersonating Microsoft Scan report: https://urlscan.io/result/01f4a3b2-0000-0000-0000-000000000000/ - hxxps://cdn-track[.]net/px?id=99 Verdict: no malicious findings, score 0 Scan report: https://urlscan.io/result/7c22e910-0000-0000-0000-000000000000/ Assessment: the sender domain is a lookalike of microsoft.com using a zero in place of the letter o, the body pressures the reader to act within 24 hours, and the first link renders a credential form styled as a Microsoft sign-in page. Recommend blocking the domain and resetting Dana's password if she entered credentials.

What does this prompt do?

  • Checks your phishing report mailbox every 20 minutes during business hours for emails staff have forwarded in
  • Reads each report in full, pulls out every link, and scans them privately in a safe sandbox so internal links are never exposed to strangers
  • Weighs the scan findings against who sent the email and what it actually says, then posts one clear verdict per report: malicious, benign, or needs a human look
  • Writes links in a deactivated form so nobody on the team can click a dangerous one by accident
  • Marks each report as handled so the same email is never triaged twice

What do I need to use this?

  • A Gmail account for the mailbox your phishing reports land in, with a label applied to those reports (for example "Phishing Reports")
  • Permission for the workflow to read that mailbox and update labels on it
  • A urlscan.io account and its API key
  • A Slack workspace and the security channel where verdicts should be posted
  • Optional but recommended: a list of your own company domains and trusted senders whose links should be skipped

How can I customize it?

  • Change the schedule: run every 20 minutes during business hours, or switch to hourly, or around the clock if your team works nights
  • Adjust the skip list of company domains and trusted senders to control how much of your scan quota gets used
  • Reword the verdict categories or change where they go, for example routing anything malicious to a separate high priority channel
  • Change which label marks a report as handled, or have the workflow archive the message instead

FAQs

Will the links we scan be visible to other people?
No. Every scan is submitted privately, so results are visible only to your own account. This matters more than it sounds: reported phishing emails often contain password reset links, account confirmation links, and internal document links. Scanning services default to publishing results, and real companies have leaked exactly this kind of link that way, so this workflow always sets scans to private.
Can someone accidentally click a dangerous link in the Slack alert?
No. Every suspicious link is rewritten in a deactivated form before it reaches Slack, so it shows up as plain text rather than something clickable. Only the safe link to the scan report itself stays clickable.
What happens if a scan has not finished when the workflow checks?
Scans take roughly ten to thirty seconds. The workflow knows a not ready response is normal rather than a failure, so it waits and checks again instead of reporting an error.
Will the same email get triaged twice?
No. Once a verdict has been posted to Slack, the workflow labels that message as triaged, so later runs skip over it.
Do we need a paid urlscan.io account?
You can get started on a free account. Higher scan volumes and a few of the more advanced result fields require a paid plan, so busy mailboxes will get more out of an upgrade.
Does this replace our security analysts?
No, it removes the repetitive first pass. Clear cut cases get an immediate verdict, and anything ambiguous is explicitly flagged as needing a human look, with the evidence already gathered so the analyst starts from a full picture.

Related templates

Build a credential rotation checklist when someone leaves

When someone leaves, we check which shared passwords they used in their final months and post a ranked rotation list to your security channel.

1Password
Rippling
Slack Bot
+1
Agentic Task
Trace phishing emails to the sending IP and report abuse

Every 15 minutes, forwarded phishing reports get traced back to the server that really sent them, with a verdict in Slack and the worst senders reported.

AbuseIPDB
Gmail
Slack
Agentic Task
Weekly Amazon S3 bucket security audit posted to Slack

Every Monday, check every S3 bucket for public exposure, missing encryption and weak backup settings, then get the risks ranked in Slack.

Amazon S3
Slack Bot
Google Sheets
Agentic Task
Log Agorapulse social conversations to HubSpot contacts

Twice every weekday, the conversations from your social inbox land on the right HubSpot contact timelines, with a Slack recap for sales.

Agorapulse
HubSpot
Slack Bot
Agentic Task
Clean up HubSpot contacts from your Amazon SES suppression list

Every morning, find the addresses that hard bounced or filed a spam complaint, update the matching HubSpot contacts, and post a short Slack recap.

Amazon SES
HubSpot
Slack Bot
Agentic Task
Draft polite follow-ups for emails that never got a reply

Every weekday at 4pm, spot the threads that went quiet, stage a ready-to-send nudge in your mailbox, and get a ranked Slack recap.

Aurinko
Google Sheets
Slack Bot
Agentic Task

Stop hand-checking every reported phishing email.

Let your security channel receive a finished verdict on every staff report, with the links already scanned and made safe to read.