Quarantine phishing-pattern emails
Flag suspicious sender and link patterns into a review label so they never sit in the active inbox.
Published Feb 3, 2026
Northwind has been spear-phished twice — once a fake invoice, once a “your mailbox is full, reset your password” email that looked close enough to the real thing. Both got read and very nearly acted on because they were sitting in the inbox alongside genuine work, carrying the same weight as everything else.
This script adds a quiet layer of defence. Every few minutes it checks new
inbox mail against a set of phishing red-flags — known spoofed-domain
spellings, classic scam phrasings, and a same-domain impersonation check — and
anything matching is moved out of the inbox into a quarantine label. It does
not delete and it does not block; it just gets suspicious mail off the main
view so it can be reviewed deliberately rather than reacted to in a hurry.
What you’ll need
- A Gmail account to protect — typically the shared or owner mailbox most exposed to outside senders.
- Nothing else. The script creates the
quarantinelabel itself on first run. - A few minutes to tune
RED_FLAGSandSPOOFED_DOMAINSto the kinds of attack Northwind actually sees.
The script
// Body phrases that commonly appear in phishing attempts.
const RED_FLAGS = [
/verify your account/i,
/reset your password.+(click|tap)/i,
/wire transfer.+urgent/i,
/gift card/i,
];
// Look-alike spellings of well-known domains (note the digit/letter swaps).
const SPOOFED_DOMAINS = ['rnicrosoft', 'g00gle', 'paypa1'];
// The label suspicious mail is moved into for review.
const QUARANTINE_LABEL = 'quarantine';
// Your own domain — used to catch outsiders impersonating internal staff.
const OWN_DOMAIN = 'northwind.studio';
/**
* Scans recent inbox mail for phishing red-flags and moves anything
* suspicious into the quarantine label, out of the inbox.
*/
function quarantineSuspicious() {
// 1. Get (or create) the quarantine label.
const quarantine = GmailApp.getUserLabelByName(QUARANTINE_LABEL)
|| GmailApp.createLabel(QUARANTINE_LABEL);
// 2. Look only at inbox mail from the last day not already quarantined.
const threads = GmailApp.search(
'in:inbox newer_than:1d -label:' + QUARANTINE_LABEL
);
if (!threads.length) {
Logger.log('No new inbox mail to scan.');
return;
}
// 3. Quarantine every thread whose first message looks suspicious.
let moved = 0;
for (const thread of threads) {
const msg = thread.getMessages()[0];
if (!suspicious(msg)) continue;
thread.addLabel(quarantine);
thread.moveToArchive();
moved++;
}
Logger.log('Quarantined ' + moved + ' thread(s).');
}
/**
* Returns true if a message trips any phishing red-flag: a spoofed
* sender domain, a scam phrase in the body, or an outsider claiming
* to be an internal address.
*/
function suspicious(msg) {
const from = msg.getFrom().toLowerCase();
const body = msg.getPlainBody();
// a. Sender domain is a known look-alike spelling.
if (SPOOFED_DOMAINS.some((d) => from.includes(d))) return true;
// b. Body contains a classic phishing phrase.
if (RED_FLAGS.some((re) => re.test(body))) return true;
// c. An outside sender, but the body name-drops our own domain —
// a hallmark of impersonation ("this is Awadesh from Northwind").
const senderDomain = (from.match(/@([\w.-]+)/) || [, ''])[1];
if (
senderDomain &&
senderDomain !== OWN_DOMAIN &&
body.includes('@' + OWN_DOMAIN)
) {
return true;
}
return false;
}
How it works
quarantineSuspiciousfetches (or creates) thequarantinelabel, then searches the inbox for mail from the last day that is not already quarantined. If nothing is new, it stops.- For each thread it reads the first message and passes it to
suspicious. suspiciousruns three independent checks and returnstrueif any one of them trips:- Spoofed domain — the
Fromaddress contains a known look-alike spelling such asrnicrosoft(an “rn” posing as an “m”) orpaypa1(a digit “1” for the letter “l”). - Red-flag phrase — the body matches a scam phrasing like “verify your account” or “wire transfer … urgent”.
- Impersonation — the sender is from an outside domain but the body
mentions a
@northwind.studioaddress, a common trick for a stranger pretending to be a colleague.
- Spoofed domain — the
- A thread that trips any check is labelled
quarantineand archived, which removes it from the inbox in one move. It is not deleted — it is simply out of the way. - The function logs how many threads were moved so you can see at a glance whether a run did anything.
Example run
Three emails arrive in the inbox in the last hour:
| From | Subject | Outcome |
|---|---|---|
| [email protected] | Your monthly invoice | Left in inbox — no red-flags |
| [email protected] | Verify your account now | Quarantined — spoofed domain and red-flag phrase |
| [email protected] | Quick favour | Quarantined — outsider name-dropping @northwind.studio in the body |
After the run, the genuine invoice is untouched while both suspicious threads
have moved to the quarantine label and out of the inbox, ready for a
deliberate review.
Trigger it
Run this on a frequent time-driven trigger so suspicious mail is pulled out before anyone has a chance to act on it:
- In the Apps Script editor, open Triggers (the clock icon).
- Click Add trigger.
- Choose function
quarantineSuspicious, event source Time-driven, type Minutes timer, every 10 minutes.
Ten minutes keeps the window of exposure small while staying comfortably within Gmail quota.
Watch out for
- False positives are inevitable. A genuine email from IT really might say
“reset your password”, and a real supplier might mention a Northwind address.
Review the
quarantinelabel regularly — at least weekly — and never delete from it automatically. - This is a tripwire, not a filter. It catches patterns, not intent. A well-crafted phish that avoids these phrases will sail straight through; treat the script as one layer, alongside Gmail’s own filtering and basic staff awareness.
- Only the first message is scanned. A clean opener followed by a malicious reply in the same thread is not caught. For high-risk mailboxes, loop over every message in the thread.
- Tune the lists to your reality. The default
SPOOFED_DOMAINSandRED_FLAGSare starting points. Add the look-alikes and phrasings from phishing attempts Northwind has actually received — those are the patterns most likely to return. - Archiving is reversible but quiet. Quarantined threads leave the inbox with no notification. If a senior colleague needs to know mail was held, add a summary email or a Chat message at the end of the run.
- HTML-only links are invisible here.
getPlainBodydrops markup, so a phishing link hidden behind a styled button has no surrounding text forRED_FLAGSto match. Inspect raw content if link-based attacks are your main threat.
Related
Convert long email threads into a summary note
Collapse a thread's history into a Doc for handover — perfect for client transitions or vacation cover.
Updated Jun 6, 2026
Pull event RSVPs from emails into a Sheet
Parse yes/no replies to event invites and tally attendance automatically.
Updated Jun 2, 2026
Turn forwarded emails into project tasks
Forward to [email protected] and a row lands in the Projects sheet under the right client.
Updated May 30, 2026
Turn starred emails into a task list
Sync every starred thread into the Northwind Tasks sheet automatically.
Updated May 26, 2026
Alert when a label hits a backlog threshold
Warn the Northwind team in Slack when a Gmail label has more than N unread threads.
Updated Mar 31, 2026