Skip to main content
Back to blog
April 3, 20265 min read

Email Triage Automation with InboxWatch

Three architectures for routing emails by threat level. Block, quarantine, or pass based on a single API call. Works with any webhook pipeline, Slack bot, or SOAR platform.

> 70

Block

40 - 70

Quarantine

< 40

Pass

The problem

Most security teams triage reported emails manually. An analyst opens the message, checks the headers, looks up the sending domain, evaluates the authentication results, and makes a judgment call. For a small team handling 50 or more reported emails per day, this is hours of repetitive work.

The InboxWatch API can handle the analysis step in under 200 milliseconds. The question is how to wire it into your existing workflow so that human analysts only review the ambiguous cases.

Threat score routing

The API returns a threatScore from 0 to 100. This score maps naturally to three triage buckets:

  • Score above 70: Block. The email has multiple high-severity indicators. Domain spoofing, failed authentication, BEC language patterns, or known phishing infrastructure. Auto-delete or move to a quarantine that requires admin release.
  • Score 40 to 70: Quarantine. The email has some suspicious indicators but is not clearly malicious. Hold for analyst review. These are the emails where human judgment adds the most value.
  • Score below 40: Pass. Low risk. The authentication checks passed, the domain is legitimate, and no BEC patterns were detected. Let it through or mark as reviewed.

These thresholds are a starting point. Adjust them based on your organization's risk tolerance and false positive rate. A financial institution might block at 60. A university might set the pass threshold at 30.

The API call

Every architecture below uses the same core API call. Extract the headers from the email, POST them to the analysis endpoint, and route based on the threat score:

POST https://inboxwatch.ai/api/mcp/analyze
Authorization: Bearer iw_live_your_api_key_here
Content-Type: application/json

{
  "from": "CFO <cfo@yourcompany-finance.com>",
  "replyTo": "cfo.payments@gmail.com",
  "subject": "Wire transfer - urgent approval needed",
  "authenticationResults": "spf=none; dkim=none; dmarc=none",
  "recipientDomain": "yourcompany.com"
}

Response:

{
  "threatScore": 88,
  "threatLevel": "critical",
  "verdict": "HIGH RISK: 3 critical threat indicator(s) detected.",
  "indicators": [
    {
      "type": "bec_pattern",
      "severity": "critical",
      "description": "Subject contains urgent financial language"
    },
    {
      "type": "domain_spoofing",
      "severity": "critical",
      "description": "From domain resembles recipient domain with added suffix"
    },
    {
      "type": "reply_to_mismatch",
      "severity": "high",
      "description": "Reply-To uses free email provider"
    }
  ]
}

Score 88. This email goes straight to the block bucket. No analyst time required.

Architecture 1: Webhook pipeline

The simplest architecture. Your email gateway (Google Workspace, Microsoft 365, or a third-party filter) sends a webhook when a new email arrives or is reported by a user. A lightweight function receives the webhook, extracts the headers, calls InboxWatch, and takes action.

# Pseudocode: webhook handler

def handle_reported_email(webhook_payload):
    headers = extract_headers(webhook_payload)

    result = requests.post(
        "https://inboxwatch.ai/api/mcp/analyze",
        json=headers,
        headers={"Authorization": f"Bearer {API_KEY}"},
    ).json()

    score = result["threatScore"]

    if score > 70:
        quarantine_and_block(webhook_payload["message_id"])
        notify_soc(result, action="blocked")
    elif score > 40:
        hold_for_review(webhook_payload["message_id"])
        notify_soc(result, action="quarantined")
    else:
        mark_as_safe(webhook_payload["message_id"])
        log_result(result)

This runs well on AWS Lambda, Google Cloud Functions, Vercel Functions, or any serverless platform. The entire function executes in under a second.

Architecture 2: Slack bot

For teams that already use Slack for incident response. Users forward suspicious emails to a dedicated channel (or use a Slack workflow to submit them). A bot listens for new messages, extracts the headers from the forwarded email, calls InboxWatch, and posts the analysis back to the channel.

# Slack bot message handler

def on_message(event):
    email_headers = parse_forwarded_email(event["text"])
    if not email_headers:
        return

    result = analyze_with_inboxwatch(email_headers)
    score = result["threatScore"]
    level = result["threatLevel"]
    indicators = result.get("indicators", [])

    blocks = [
        header(f"Threat Analysis: {score}/100 ({level.upper()})"),
        section(result["verdict"]),
    ]

    for ind in indicators:
        blocks.append(
            section(f"*[{ind['severity'].upper()}]* {ind['description']}")
        )

    if score > 70:
        blocks.append(actions([
            button("Block Sender", "block", style="danger"),
            button("Quarantine", "quarantine"),
        ]))
    elif score > 40:
        blocks.append(actions([
            button("Quarantine", "quarantine"),
            button("Mark Safe", "safe"),
        ]))

    post_to_channel(event["channel"], blocks)

The Slack bot gives analysts context without switching tools. They can review the threat analysis and take action with one click, directly from the Slack channel.

Architecture 3: SOAR integration

For organizations running a SOAR platform (Splunk SOAR, Palo Alto XSOAR, Tines, Swimlane, or similar). The InboxWatch API becomes a step in your existing playbook.

The integration pattern:

  1. Trigger: A user reports a phishing email, or a detection rule fires in your email gateway.
  2. Extract: The SOAR playbook extracts email headers from the reported message (using the email gateway API or an EML parser).
  3. Analyze: The playbook calls POST /api/mcp/analyze with the extracted headers. This is a standard HTTP action available in every SOAR platform.
  4. Route: Based on the threat score, the playbook branches:
    • Score above 70: auto-remediate (block sender, remove from all inboxes, create incident)
    • Score 40 to 70: create a case for analyst review with the analysis attached
    • Score below 40: auto-close the report, send a "safe" response to the reporter
  5. Enrich: Use the indicators array to add context to your incident. Each indicator includes a type, severity, description, and evidence field that maps directly to SOAR enrichment fields.
# SOAR playbook step (HTTP action)

Method: POST
URL: https://inboxwatch.ai/api/mcp/analyze
Headers:
  Authorization: Bearer {{ vault.inboxwatch_api_key }}
  Content-Type: application/json
Body:
  {
    "from": "{{ artifact.email_from }}",
    "replyTo": "{{ artifact.email_reply_to }}",
    "subject": "{{ artifact.email_subject }}",
    "authenticationResults": "{{ artifact.auth_results }}",
    "recipientDomain": "{{ config.org_domain }}"
  }

# Decision node
if response.threatScore > 70:
    run_playbook("auto_remediate_phishing")
elif response.threatScore > 40:
    create_case(severity="medium", analyst_queue="email_triage")
else:
    close_alert(resolution="benign", notify_reporter=true)

Choosing your thresholds

The 70/40 split is a reasonable default. Here is how to tune it for your environment:

  • Start conservative. Set the block threshold at 80 and the pass threshold at 30. Review everything in between manually for two weeks.
  • Track false positives. If the quarantine queue is full of legitimate emails scoring 45 to 55, raise your quarantine threshold to 55.
  • Track false negatives. If confirmed phishing emails are slipping through with scores of 35 to 40, lower your pass threshold.
  • Adjust by sender type. Internal senders with valid authentication should consistently score below 20. If they do not, check your SPF and DKIM configuration.

Rate limits for automation

Automated pipelines need predictable throughput. The API tiers:

  • Free tier (with API key): 100 requests per minute. Handles about 6,000 emails per hour. Sufficient for most mid-market organizations.
  • Paid tier: 1,000 requests per minute. Handles about 60,000 emails per hour. For large enterprises or MSSPs processing multiple tenants.

The API returns X-RateLimit-Remaining and X-RateLimit-Resetheaders with every response. Use these to implement backpressure in your pipeline rather than hitting 429 errors.

Go further: continuous account protection

The API analyzes individual email headers. For full account protection, InboxWatch monitors your entire Gmail or Microsoft 365 configuration continuously: forwarding rules, delegates, OAuth apps, sign-in activity, and 100+ security checks running every 30 minutes.

Sign up at inboxwatch.ai/check for a free scan. 15 scans free, then $0.10 each. For the Python building blocks, see our phishing detector tutorial. For the full API reference, see the API walkthrough.

Protect your entire inbox

API triage handles individual emails. A full InboxWatch scan checks your entire account: 100+ security checks, continuous monitoring, instant alerts. 15 free scans, then $0.10 each.

Start Free Scan

15 free scans. No credit card to start. $0.10/scan after.

Written by Nicholas Papadam, founder of InboxWatch. Senior Analyst with 6+ years in enterprise security operations.