How to Route Inbound Document Emails Into Knowledge Collections by Subject
Build a Spojit workflow where a Mailhook trigger reads each incoming email's subject, a Condition routes the attached document to the matching department's Knowledge collection, and Slack logs every routing decision.
What This Integration Does
Teams often funnel documents to a shared inbox: contracts to legal, invoices to finance, signed forms to HR. Manually opening each email, downloading the attachment, and filing it in the right place is slow and easy to get wrong. This Spojit workflow turns that inbox into an automatic filing clerk. People email a document to a dedicated address with a subject line that names the department, and Spojit embeds the attachment into the correct persistent Knowledge collection so it becomes searchable by the rest of your automation.
The workflow runs on a Mailhook trigger: every email sent to the generated address starts a run within seconds, with no mailbox or OAuth to manage. The trigger exposes the parsed message as {{ input }}, including the subject and a list of attachment references. An Attachment node fetches the document bytes, a Condition node inspects {{ input.subject }} to choose a department, a Knowledge node in Embed mode writes the document into that department's persistent collection, and a Slack connector node posts a routing log. Each email is processed once (the Mailhook deduplicates per message), and because the collections are persistent, every embedded document accumulates in a long-lived, workspace-scoped archive that any other workflow can query later.
Prerequisites
- A Slack connection added under Connections, with access to the channel you want routing logs posted to (you will need the channel name or ID).
- One persistent Knowledge collection per department you want to route to (for example
legal-docs,finance-docs,hr-docs). Create each one in the Knowledge section of the sidebar with New Collection. The embedding model is fixed at creation, so use the same model for all of them if you ever plan to query across collections. - Agreement with senders on a subject convention that names the department, for example a subject that starts with
Legal:,Finance:, orHR:. - The document file types you expect (PDF, Word, Excel, and so on), so you can set the matching Document Type on the Knowledge node.
Step 1: Start the workflow with a Mailhook trigger
Create a new workflow and add a Trigger node. Set Trigger Type to Mailhook. Optionally set an Address prefix (1 to 24 characters, for example docs), then click Generate email address. Spojit produces a unique address like docs-9f3a1c7b5e2d4a60@mailhook.spojit.com. Copy it and share it with the people or systems that will send documents, or point a forwarding rule at it.
To keep noise out, you can add an optional From allowlist so only approved senders trigger runs, and a Subject regex if you want to require the department prefix at the trigger level. The trigger fires whether the address is in To, Cc, or Bcc, and never replies to the sender. After a run you can read the full message through {{ input }}, including {{ input.subject }} and the {{ input.attachments }} list where each entry looks like:
{ "id": "att_01", "filename": "Q3-contract.pdf", "contentType": "application/pdf" }
Step 2: Fetch the document with an Attachment node
Add an Attachment node directly after the trigger. This node only works in Mailhook workflows and pulls the actual bytes of the file the Mailhook trigger only references. Set Mode to Single so it returns the first matching attachment as one object. Use the Content type filter or Filename pattern to keep it to real documents, for example a content-type filter of application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document or a filename pattern of *.pdf.
Turn on Fail if no attachment matches if a document is mandatory, so emails with nothing to file stop cleanly rather than embedding an empty record. Name the output variable, for example doc. In Single mode the node returns:
{ "filename": "Q3-contract.pdf", "contentType": "application/pdf", "size": 184320, "content": "" }
The {{ doc.content }} value is base64 and feeds straight into the Knowledge node in the next steps. Remember the default limits: 10 MB per attachment and 25 MB per run.
Step 3: Route by subject with a Condition node
Add a Condition node and wire the Attachment node into it. The Condition gives you a true branch and a false branch, so chain conditions to fan out into one branch per department. Configure the first Condition to test whether {{ input.subject }} contains or starts with your finance marker, for example checks that {{ input.subject }} starts with Finance:.
Connect the false output to a second Condition node that tests for Legal:, and its false output to a third that tests for HR:. The final false output is your fallback for anything that does not match a known department. Keep the markers consistent with the subject convention from your prerequisites. If you prefer one expression instead of a chain, you can branch on a normalized value, but a short chain of Condition nodes keeps the routing easy to read on the canvas.
Step 4: Embed the document into the matching collection
On each true branch, add a Knowledge node set to Embed mode. In Collection, pick the persistent collection for that branch (for example the finance branch points at finance-docs). Set Document Input to {{ doc.content }} from the Attachment node, and set Document Type to match the file (for example PDF or Word).
Set File Name to something stable and descriptive so you can find it later and so re-sends overwrite cleanly rather than duplicating, for example:
{{ doc.filename }}
Leave Embedding Model at the collection's default. Name the Output Variable, for example embedResult, which returns the chunk count and document metadata. Repeat this Knowledge node on the legal and HR branches, each pointed at its own collection. On the fallback branch you can either embed into a catch-all collection like unsorted-docs or skip embedding and only notify a human to file it manually.
Step 5: Log the routing decision to Slack
After each Knowledge node, add a Connector node for Slack in Direct mode and choose the send-message tool. Direct mode is deterministic and uses no AI credits, which is what you want for a simple log line. Map the channel (by name or ID) and build the message text from your variables, for example:
Filed "{{ doc.filename }}" into finance-docs ({{ embedResult.chunkCount }} chunks). From: {{ input.from }} | Subject: {{ input.subject }}
Give each branch its own send-message call so the log names the correct collection. For the fallback branch, post a message that flags the email for manual filing and includes {{ input.subject }} and {{ input.from }} so a person can act on it. If you want a reply to the original sender as well, add a Send Email node addressed to {{ input.replyTo }} confirming the document was received.
Step 6: Confirm the run model and save
Save the workflow and enable it. Because the trigger is a Mailhook, there is no schedule or polling to configure: each inbound email pushes a run within seconds, and duplicate copies of the same message are ignored automatically. Received emails are retained for 30 days, so you can inspect recent runs in execution history if a document does not land where you expect. If you ever need to change the address (for example after sharing it too widely), use Regenerate address on the trigger, which rotates it and kills the old one instantly.
Tips
- Use the same embedding model across all department collections if you might later run a single query that spans them. Mismatched models cannot be queried together reliably.
- Normalize the subject before matching: a small Transform node that lowercases
{{ input.subject }}lets your Condition nodes matchfinance:regardless of how the sender capitalized it. - If senders attach several files at once, switch the Attachment node to
Multiplemode and wrap the embed step in a Loop over{{ doc.attachments }}so each file is filed individually. - Keep File Name deterministic (for example based on
{{ doc.filename }}) so re-sent documents overwrite the previous version instead of piling up duplicates in the collection.
Common Pitfalls
- Forgetting the Attachment node. The Mailhook trigger only gives you attachment references, not bytes. The Knowledge node needs
{{ doc.content }}, so the Attachment node must run first. The designer also refuses to save an Attachment node unless the workflow uses a Mailhook trigger. - Oversized files. The defaults cap an attachment at 10 MB and a run at 25 MB. A large scanned PDF can exceed this and the document will not be fetched, so set a sensible Max size and decide whether to fail or skip.
- Unmatched subjects silently disappearing. If every Condition branch is for a known department and there is no fallback, a misnamed subject embeds nothing and no one is told. Always wire the final false branch to a Slack
send-message(or a Human node) so nothing is lost. - Wrong Document Type. Setting the type to
PDFwhile someone emails a Word file produces poor or empty chunks. If your inbox receives mixed formats, branch on{{ doc.contentType }}or{{ doc.filename }}and set the matching type per branch.
Testing
Before announcing the address, test with one department. Send yourself an email to the generated Mailhook address with a small sample PDF and a subject like Finance: test invoice. Watch the run appear in execution history, confirm the Attachment node returned a non-zero size, and open the finance-docs collection in the Knowledge sidebar to verify the document shows a READY status with a sensible chunk count. Check that the Slack log message named the correct collection. Then send a deliberately misnamed subject and confirm the fallback branch fires. Once one branch is solid, repeat for legal and HR, and only then share the address widely. If anything is unclear while you build, ask Miraxa, the intelligent layer across your automation, something like "Why did my last run skip the embed step?" and it will investigate the run in context.
Learn More
- Mailhook trigger reference
- Attachment node reference
- Knowledge collections and the Knowledge node
- Slack connector reference
- Setting Up a Mailhook Trigger
- Using Knowledge Nodes
- Using Condition Nodes
- How to Extract and Store Invoice Data in a Knowledge Collection
- How to Auto-Index Incoming Emails into Your Knowledge Base