How to Extract and Store Knowledge From Email Attachments Into MongoDB
Build a Spojit workflow where an Outlook email trigger reads an attached document, a transient Knowledge query pulls out the structured fields you care about, and the MongoDB insert-documents tool stores the result as a clean record.
What This Integration Does
Plenty of important data still arrives as a document stapled to an email: a signed agreement, a supplier statement, a quote, a registration form. Re-keying those fields into a database by hand is slow and error prone. This workflow turns every qualifying email into a structured MongoDB document automatically. When a message lands in your connected Outlook mailbox, Spojit reads its attachment, asks the intelligent layer to extract the exact fields you define, and writes a single tidy record you can query later.
The run starts when the Email trigger polls your Outlook mailbox and finds a new message that matches your filters. The attachment bytes flow into a transient Knowledge collection that is created just for this run, the Knowledge node queries that collection and returns JSON shaped by a Response Schema, and the MongoDB Connector node inserts that JSON. The transient collection is discarded automatically when the run completes, so nothing is left behind. Each email produces its own run, so re-running or replaying a message simply produces another insert against the same MongoDB collection.
Prerequisites
- An Outlook (trigger) connection added under Connections -> Add connection, with read access to the mailbox that receives the documents. Read-only is enough unless you want Spojit to mark messages read or move them after processing.
- A MongoDB connection with write access to the target database, and a collection name in mind (for example
extracted_documents). - Senders, a subject pattern, or a folder you can use to narrow the trigger so only the intended emails start a run.
- A clear list of the fields you want to extract (for example party name, document date, reference number, total amount). You will encode these in the Knowledge Response Schema.
Step 1: Start with an Email trigger on your Outlook mailbox
Add a Trigger node and set its type to Email. Pick your Outlook (trigger) connection, choose the folder to watch (such as Inbox), and set a Poll interval (1 to 60 minutes; the default is 2). Narrow the trigger with an optional From allowlist and a Subject regex so unrelated mail is ignored. The trigger output gives you fields like {{ input.subject }}, {{ input.from }}, {{ input.textBody }}, {{ input.receivedAt }}, and an {{ input.attachments }} list where each entry is a reference (filename, contentType, and an id) rather than the file bytes.
Note that the dedicated Attachment node is only available on Mailhook workflows. With the Email trigger you fetch attachment content directly inside the Knowledge node using its Document Input field, which is covered in Step 3.
Step 2: Embed the attachment into a transient Knowledge collection
Add a Knowledge node and set its mode to Embed. In the Collection dropdown choose Transient: a per-run collection that is created on the fly, shared across Knowledge nodes in the same run, and cleaned up automatically when the run ends. Transient mode needs no File Name and no embedding model selection, which makes it ideal for one-off "embed then query then discard" extraction on a single document.
Set Document Type to match the attachment (for example PDF, Word, Excel, or Plain Text). For the Document Input, point at the first attachment from the trigger, for example {{ input.attachments.0.content }}; Spojit fetches the attachment bytes on demand. Give the node an Output Variable such as embedResult so you can confirm the chunk count downstream.
Step 3: Query the collection and force structured output
Add a second Knowledge node, set its mode to Query, and choose Transient again so it reads the document you just embedded in this run. Write a focused Prompt that asks for exactly the fields you need, and pick a Model for synthesis. Keep Result Count at the default unless the document is long. A prompt might read:
Extract the following fields from this document and return them as JSON:
- party: the counterparty or company name
- documentDate: the document date in YYYY-MM-DD
- referenceNumber: the reference, invoice, or quote number
- totalAmount: the total amount as a number
- currency: the three letter currency code
If a field is missing, return null for it.
To guarantee clean, machine-readable output, fill in the Response Schema so the intelligent layer returns JSON in a fixed shape instead of prose:
{
"type": "object",
"properties": {
"party": { "type": ["string", "null"] },
"documentDate": { "type": ["string", "null"] },
"referenceNumber": { "type": ["string", "null"] },
"totalAmount": { "type": ["number", "null"] },
"currency": { "type": ["string", "null"] }
},
"required": ["party", "documentDate", "referenceNumber", "totalAmount", "currency"]
}
Set the Output Variable to extracted. Downstream you can reference its fields as {{ extracted.party }}, {{ extracted.totalAmount }}, and so on.
Step 4: Skip incomplete extractions with a Condition node
Add a Condition node so you only store records that came back usable. A sensible check is whether the reference number was found, for example {{ extracted.referenceNumber }} is not empty. Wire the true branch onward to the insert step. On the false branch you can route to a Send Email node that flags the message for a human to review, using {{ input.subject }} and {{ input.from }} in the body so the reviewer knows which email needs attention. This keeps half-empty documents out of your database.
Step 5: Insert the record into MongoDB
Add a Connector node, choose the MongoDB connector, and use Direct mode with the insert-documents tool. Direct mode is the right choice here because the call is a single, predictable write with no AI cost. Set collection to your target collection name (for example extracted_documents) and map the documents input to an array holding one object built from the extracted fields plus a little provenance from the trigger:
{
"collection": "extracted_documents",
"documents": [
{
"party": "{{ extracted.party }}",
"documentDate": "{{ extracted.documentDate }}",
"referenceNumber": "{{ extracted.referenceNumber }}",
"totalAmount": {{ extracted.totalAmount }},
"currency": "{{ extracted.currency }}",
"sourceSubject": "{{ input.subject }}",
"sourceFrom": "{{ input.from }}",
"receivedAt": "{{ input.receivedAt }}",
"sourceFilename": "{{ input.attachments.0.filename }}"
}
]
}
The tool returns insertedCount and insertedIds, so you can confirm the write succeeded. If you would rather build the document with custom shaping or defaults, drop a Transform node before this step and feed its output into documents.
Step 6: Confirm the run and optionally notify
To round out the workflow, add a Send Email node after the insert that confirms the record was stored, for example a short body that includes {{ extracted.referenceNumber }} and the returned id. Spojit sends this from its built-in mail service with no extra connection. If you want the confirmation to come from your own domain instead, use the Resend or SMTP connector. Save the workflow, then enable it so the Outlook trigger begins polling.
Tips
- Use a transient collection rather than a persistent one for single-document extraction: it needs no file name or embedding model and cleans itself up, which keeps your Knowledge section uncluttered.
- Always pair an Embed Knowledge node with a Query Knowledge node in the same run when using Transient, since the query reads only what was embedded in that run.
- Store the source subject, sender, and received time alongside the extracted fields so you can trace any MongoDB record back to the original email.
- Keep the trigger poll interval no shorter than you need: a 2 to 5 minute interval is usually plenty and avoids hammering the mailbox.
Common Pitfalls
- Without a Response Schema on the Query node, the intelligent layer may return prose instead of JSON, which breaks the MongoDB mapping. Define the schema and mark fields required.
- Numeric fields like
totalAmountshould not be wrapped in quotes in thedocumentspayload, or MongoDB stores them as strings. Reference them without quotes as shown above. - Set the Knowledge Document Type to match the real attachment. A PDF embedded as Plain Text, or a scanned image not set to the Images (OCR) type, yields poor extraction.
- If an email arrives with no attachment,
{{ input.attachments.0.content }}resolves to nothing. Add a Condition ahead of the embed step that checks the attachments list is not empty, or tighten the trigger filters so only emails with documents start a run.
Testing
Before enabling the trigger for the whole mailbox, narrow the From allowlist to a single test address and send yourself one representative document. Watch the run in the execution history and open each step: confirm the embed step reports a chunk count, the query step returns JSON matching your Response Schema, the Condition takes the expected branch, and the MongoDB step reports insertedCount of 1. Query the collection with the find-documents tool or your usual MongoDB client to verify the stored fields and types look right, then widen the trigger filters and enable the workflow.