How to Index Emailed Spreadsheet Reports into a Knowledge Collection
Point a recurring Excel report at a Spojit Mailhook address, pull the spreadsheet bytes with the Attachment node, and embed each one as an Excel document into a persistent Knowledge collection you can query later.
What This Integration Does
Plenty of business systems can email a report but cannot push it anywhere else: a finance tool that sends a weekly sales workbook, a warehouse system that mails a nightly stock count, or a vendor portal that drops a monthly statement in your inbox. Those spreadsheets pile up and nobody can ask a question across them. This workflow turns that stream of emailed Excel files into a searchable archive. Each time a report lands, Spojit captures the attachment and embeds it into a persistent Knowledge collection, so weeks or months later you (or another workflow) can ask plain-language questions like "what were the highest-margin lines in March" and get an answer grounded in the actual spreadsheets.
The run model is push-based and per-email. A Mailhook trigger gives you a unique address; any mail to it starts a run within seconds, with no mailbox or OAuth to manage. The Attachment node fetches the real bytes of the matching .xlsx file, and the Knowledge node in Embed mode writes those bytes into a named, workspace-scoped collection that survives across runs. Because the collection is persistent, every report you receive adds to the same archive rather than replacing it. Re-running on the same email is safe: Mailhook deduplicates per message, and using a deterministic file name per report means a repeat simply overwrites that one document instead of creating duplicates.
Prerequisites
- A workflow in the Spojit Workflow Designer where you can add a Trigger, an Attachment node, and a Knowledge node.
- A persistent Knowledge collection created ahead of time in the Knowledge section of the sidebar (for example, named
Sales Reports). Note its embedding model: you will reuse the same one whenever you query. - The source system or a forwarding rule that can email the report to a Spojit-generated address. You control where the mail is sent, which is exactly when Mailhook is the right trigger.
- Reports delivered as real Excel attachments (
.xlsxor.xls), each under the 10 MB per-attachment limit. - No connector or connection is required: Mailhook, Attachment, and Knowledge are all built into Spojit.
Step 1: Add a Mailhook trigger and generate the address
Add a Trigger node and set Trigger Type to Mailhook. Optionally set an Address prefix (1 to 24 characters, default mh) so the address is recognizable, for example sales-reports. Click Generate email address to create a unique address in the form sales-reports-<random16>@mailhook.spojit.com, then copy it and configure your reporting system to send there. The trigger fires whether the address appears in To, Cc, or Bcc. The full email is available downstream as {{ input }}, including {{ input.subject }}, {{ input.from }}, {{ input.replyTo }}, and the attachment references in {{ input.attachments }}, where each reference is { id, filename, contentType }.
Step 2: Filter out everything that is not your report
On the same Mailhook trigger, narrow what counts as a valid report so noise and reply-all chatter do not trigger embeds. Add a From allowlist containing only the sender address your reporting system uses, and add a Subject regex that matches the report subject line, for example:
^Weekly Sales Report - \d{4}-\d{2}-\d{2}$
Only emails passing both filters start a run, so the rest of the workflow can assume it is looking at a genuine report. If you later need a fresh address (for instance, the old one leaked to a mailing list), use Regenerate address; the previous address stops working instantly.
Step 3: Fetch the spreadsheet bytes with the Attachment node
Add an Attachment node after the trigger. The designer only allows an Attachment node when the workflow uses a Mailhook trigger, so place it downstream of Step 1. Configure it to grab the single Excel file:
- Mode:
Singleso the output is one object you can feed straight into the Knowledge node. - Filename pattern:
*.xlsx(add a second node or widen the glob if your source also sends.xls). - Content type filter (optional):
application/vnd.openxmlformats-officedocument.spreadsheetml.sheetto be strict about Excel. - Fail if no attachment matches: turn this on so a report email that arrives without its spreadsheet fails loudly instead of silently embedding nothing.
In Single mode the node outputs { filename, contentType, size, content }, where content is the base64 bytes of the file. Reference the output as, for example, {{ attachment.content }} and {{ attachment.filename }} in the next step.
Step 4: Build a stable document name for the report
Embedding into a persistent collection overwrites any document that already has the same File Name, so a deterministic name keeps your archive clean and makes re-runs idempotent. Add a Transform node (or use the attachment's own filename if it already contains the date) to produce a consistent name such as:
sales-report-{{ input.receivedAt }}.xlsx
If your subject line carries the report date and the raw filename is generic (like export.xlsx), derive the name from {{ input.subject }} instead so each weekly report becomes its own document. Either way, aim for one stable name per logical report period: the same report re-sent updates one entry rather than spawning duplicates.
Step 5: Embed the spreadsheet into the persistent collection
Add a Knowledge node and set its mode to Embed. Configure it as follows:
- Collection: pick your persistent collection, for example
Sales Reports(do not pick Transient, which would be discarded at the end of the run). - File Name: the stable name from Step 4, for example
{{ report_name }}. - Document Type:
Excel, so Spojit parses the workbook sheets correctly. - Document Input:
{{ attachment.content }}, the base64 bytes from the Attachment node. - Embedding Model: leave at the collection default. Always embed and query a collection with the same embedding model.
- Output Variable: capture it (for example
embed_result) to read back the chunk count and metadata.
On completion the document appears in the collection's document table with a status of PROCESSING and then READY, alongside its type, size, and chunk count.
Step 6: Confirm and optionally notify
Add a Send Email node so each ingest produces a receipt. Since Mailhook never replies to the sender, this is how you close the loop. Set Recipients to your ops inbox (or template the original sender with {{ input.replyTo }} if you want to acknowledge them), a templated Subject like Indexed: {{ report_name }}, and a Body that reports the result, for example "Embedded {{ report_name }} into the Sales Reports collection ({{ embed_result.chunkCount }} chunks)." External recipients must be on your org allowlist under Settings - General - Email recipients. To later ask questions across the archive, add a second workflow with a Knowledge node in Query mode pointed at the same Sales Reports collection, a natural-language Prompt, and an Output Variable for the answer.
Tips
- Use a recognizable Mailhook Address prefix per report type (for example
sales-reportsversusstock-counts) so you can route different reports into different collections from separate workflows. - If a single email carries several spreadsheets, switch the Attachment node to
Multiplemode and wrap the Knowledge node in a Loop over{{ attachment.attachments }}, embedding each file with its own name. - Ask Miraxa, the intelligent layer across your automation, to scaffold the chain for you: "Build a workflow that watches a mailhook, fetches the Excel attachment, and embeds it into my Sales Reports collection." Then fine-tune fields in the properties panel.
- Keep a single embedding model per collection. Mixing models across embeds and queries produces poor matches.
Common Pitfalls
- Choosing Transient by mistake. A transient collection is auto-cleaned when the run completes, so your reports would vanish. For a long-lived archive you must select the named persistent collection.
- Non-unique file names. Random or identical file names either create duplicate documents or overwrite the wrong one. Derive a stable, period-specific name (Step 4) so re-sends update exactly one entry.
- Oversized or inline reports. Attachments are capped at 10 MB each and 25 MB per run by default, and a report pasted into the email body is not an attachment at all. The Attachment node only fetches real attached files.
- Wrong Document Type. Leaving the Knowledge node on a non-spreadsheet type for an
.xlsxfile yields poor parsing. Set Document Type toExcelfor workbooks. - Retention window. Received emails are retained for 30 days, so backfilling old reports requires re-sending them; the workflow only embeds what currently arrives.
Testing
Before pointing your production reporting system at the address, send yourself one real Excel report to the generated Mailhook address from an allowlisted sender with a subject that matches your regex. Open the run in execution history and confirm the Attachment node output shows the expected filename, contentType, and a non-zero size, and that the Knowledge node returned a chunk count. Then open the Sales Reports collection in the Knowledge sidebar and verify the document is listed with status READY. Finally, run a quick Query-mode Knowledge node against the collection with a prompt you know the answer to, to confirm the content is retrievable. Once that round trip works, enable the workflow.