How to Classify and Triage Emailed Vendor Alerts with a Mailhook

Point your vendors' system-alert emails at a Spojit Mailhook, have an agent classify each one by severity, then route critical alerts to the right Slack channel and store everything in MongoDB for later analysis.

What This Integration Does

Most monitoring and SaaS vendors send operational alerts by email: an uptime monitor flags a degraded endpoint, a payment gateway warns about declining authorisation rates, a backup tool reports a failed job. These land in a shared inbox where they are easy to miss and impossible to prioritise. This workflow gives those emails a dedicated front door. Spojit generates a unique Mailhook address, you add a forwarding rule (or point the vendor's notification settings) at it, and every inbound alert is read, classified by severity, and triaged automatically: high-severity alerts get posted to an incident Slack channel within seconds, while everything else is logged quietly to a database you can report on.

The run model is push-based. A Mailhook trigger receives the email seconds after it is sent (no mailbox or OAuth required), exposing the parsed message as {{ input }}. A Connector node in Agent mode reads the subject and body and returns a structured severity verdict. A Condition node branches on that verdict: critical alerts flow to a Slack send-message call, everything else skips straight to storage. Finally every alert (regardless of severity) is written to MongoDB with insert-documents so you keep a complete, queryable history. Each email is deduplicated by message id, so a vendor that retries delivery will not double-post. Runs are always asynchronous: the sender gets no reply, which is exactly what you want for machine-generated mail.

Prerequisites

  • A Slack connection (OAuth) with permission to post messages, and the channel id or name of your incident channel (for example #vendor-alerts).
  • A MongoDB connection, plus the target database and collection name (for example database ops, collection vendor_alerts).
  • Access to your vendors' notification settings or a mailbox forwarding rule so you can point alert emails at the generated Mailhook address.
  • A workspace AI model available for Agent mode (used to classify severity). Agent mode consumes AI credits per run.

Step 1: Receive alerts with a Mailhook trigger

Create a new workflow and open the Trigger node. Set Trigger Type to Mailhook. Optionally set an Address prefix (1 to 24 characters, default mh) such as vendor-alerts, then click Generate email address. Spojit produces a unique address in the form vendor-alerts-<random16>@mailhook.spojit.com. Copy it and point your vendor notifications or an inbox forwarding rule at it. The Mailhook fires whether the address is in To, Cc, or Bcc.

The trigger output is available downstream as {{ input }} with fields including {{ input.from }}, {{ input.subject }}, {{ input.text }}, {{ input.html }}, and {{ input.receivedAt }}. To keep noise out, open the optional From allowlist and add your vendor domains, and set a Subject regex if you only care about messages matching a pattern such as (alert|alarm|incident|warning).

Step 2: Classify severity with a Connector node in Agent mode

Add a Connector node and switch it to Agent mode. Agent mode lets the agent read the email and reason about it rather than forcing a fixed lookup. Give it a prompt that passes the raw email content, for example:

You are triaging an automated vendor system alert.
From: {{ input.from }}
Subject: {{ input.subject }}
Body:
{{ input.text }}

Classify the alert's severity and summarise it for an on-call engineer.

To make the output reliable to branch on, define a Response Schema so the agent returns JSON instead of prose:

{
  "type": "object",
  "properties": {
    "severity": { "type": "string", "enum": ["critical", "warning", "info"] },
    "vendor": { "type": "string" },
    "summary": { "type": "string" },
    "actionRequired": { "type": "boolean" }
  },
  "required": ["severity", "summary"]
}

Set the node's Output Variable to triage so later steps can read {{ triage.severity }}, {{ triage.summary }}, and {{ triage.vendor }}.

Step 3: Branch on severity with a Condition node

Add a Condition node after the classifier. Configure the test to compare {{ triage.severity }} against the value critical. The true branch handles urgent alerts that need a human looking now; the false branch covers warnings and info that only need to be recorded. You will connect the true branch to Slack in the next step, and both branches will eventually reach the MongoDB store so nothing is lost.

Step 4: Post critical alerts to Slack

On the Condition node's true branch, add a Connector node in Direct mode for the Slack connector and pick the send-message tool. Direct mode is the right choice here: it is a single deterministic call with no AI cost. Map the channel to your incident channel and build the message from the triage output:

{
  "channel": "#vendor-alerts",
  "text": ":rotating_light: *{{ triage.severity }}* alert from {{ triage.vendor }}\n{{ triage.summary }}\nSubject: {{ input.subject }}\nReceived: {{ input.receivedAt }}"
}

If you also want to reach off-Slack responders, add a Send Email node on the same branch. It sends from Spojit's built-in mail service with no connection needed; set Recipients to your on-call address, a templated Subject like [CRITICAL] {{ triage.vendor }} alert, and a body built from {{ triage.summary }}. External recipients must be on your org allowlist under Settings -> General -> Email recipients.

Step 5: Store every alert in MongoDB

Merge both Condition branches into a single Connector node in Direct mode for the MongoDB connector, using the insert-documents tool. This runs for critical and non-critical alerts alike so your history is complete. Set the database and collection (for example ops / vendor_alerts) and pass a document assembled from the trigger and triage data:

{
  "database": "ops",
  "collection": "vendor_alerts",
  "documents": [
    {
      "from": "{{ input.from }}",
      "subject": "{{ input.subject }}",
      "vendor": "{{ triage.vendor }}",
      "severity": "{{ triage.severity }}",
      "summary": "{{ triage.summary }}",
      "actionRequired": "{{ triage.actionRequired }}",
      "messageId": "{{ input.messageId }}",
      "receivedAt": "{{ input.receivedAt }}"
    }
  ]
}

Including {{ input.messageId }} gives you a stable key per alert, which makes later de-duplication queries and reporting straightforward. You can read this collection back with find-documents or aggregate from a separate scheduled report workflow.

Step 6: Save, enable, and route a test alert

Save the workflow and enable it. Because the trigger is a Mailhook, there is no further wiring: any email reaching the generated address starts a run within seconds. Confirm your vendor notification setting (or forwarding rule) is pointed at the exact address you copied in Step 1. If you ever need to cut off the current address (for example after sharing it too widely), use Regenerate address on the trigger to rotate it; the old address stops working instantly.

Tips

  • Keep the classifier prompt tight and feed it {{ input.text }} rather than {{ input.html }} when possible: plain text is cheaper to process and less noisy for severity reasoning.
  • Use the Response Schema enum for severity so the Condition node always compares against a known set of values and never sees free-form text.
  • Add a second Condition test or a severity == "warning" branch if you want a middle tier that posts to a lower-priority Slack channel instead of paging on-call.
  • If a vendor sends alerts as a PDF or log attachment, add an Attachment node (Mailhook workflows only) to fetch the bytes, then feed {{ attachment.content }} into a Knowledge node in Embed mode so the agent can reason over the attachment contents too.

Common Pitfalls

  • Branching on prose instead of structured output. Without a Response Schema the classifier may return a sentence, and the Condition test will not match critical reliably. Always force JSON.
  • Storing only critical alerts. If the MongoDB node sits on the true branch alone, you lose all warning and info history. Merge both branches into the store node.
  • Mailhook attachments expire. Received emails (and their attachments) are retained for 30 days, so do not rely on re-fetching old messages; persist what you need to MongoDB at run time.
  • Forgetting the From allowlist. Without it, anyone who learns the address can trigger runs and consume AI credits. Restrict to your vendor domains and add a Subject regex.

Testing

Before pointing real vendor notifications at the Mailhook, send a single test email from your own address to the generated Mailhook address with a realistic alert subject and body. Open the execution in your run history and confirm the trigger captured {{ input.subject }} and {{ input.text }}, that the Agent mode node produced a valid triage object with a severity value, that the Condition node took the branch you expected, and that a document landed in your vendor_alerts collection. Send one email crafted to read as critical and one as informational to verify both routes. Only after both paths behave should you switch the vendor's real alerts over to the address.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.