How to Auto-Embed Mailhook PDF Attachments Into a Knowledge Collection

Forward PDFs to a Spojit Mailhook address and have each one fetched, indexed into a persistent Knowledge collection, and confirmed in Slack, with no manual uploads.

What This Integration Does

Teams accumulate reference documents (contracts, spec sheets, policy PDFs, vendor data sheets) that arrive by email and end up scattered across inboxes. This workflow turns a single email address into a self-updating, searchable archive: anyone who emails a PDF to your Mailhook address has it added to a workspace-scoped Knowledge collection within seconds, ready for later AI queries by any workflow. The result is a living knowledge base that grows as documents arrive, instead of a one-time bulk import that goes stale.

The run model is push-based. A Mailhook trigger generates a unique address; any mail sent to it starts a run seconds later, with no mailbox or OAuth to manage. The Attachment node fetches the actual PDF bytes that the trigger only references, the Knowledge node in Embed mode indexes those bytes into your persistent collection, and a Connector node posts a confirmation to Slack. Each message is deduplicated, so re-sends of the same email do not double-index. Embedding the same file name again overwrites the prior copy, so corrected re-sends update the archive cleanly. The collection persists across runs and is readable by any other workflow in the workspace.

Prerequisites

  • A persistent Knowledge collection created ahead of time in the Knowledge section of the sidebar (New Collection): give it a name such as reference-docs and note that the embedding model is fixed at creation.
  • A Slack connection added under Connections, with permission to post to the channel you want confirmations in.
  • The Slack channel ID (or name) where uploads should be announced, for example #doc-intake.
  • Knowledge that Mailhook attachments default to a 10 MB per-attachment and 25 MB per-run limit, and that received emails are retained for 30 days.

Step 1: Add the Mailhook trigger and generate an address

Create a new workflow and add a Trigger node. Set Trigger Type to Mailhook. Optionally set an Address prefix (1 to 24 characters, default mh) such as docs, then click Generate email address. Spojit produces a unique address in the form docs-<random16>@mailhook.spojit.com. Copy it and point your senders or forwarding rules at it. Because Mailhook is always asynchronous, the sender gets no automatic reply; if you want to acknowledge senders, you can add a Send Email node later that replies to {{ input.replyTo }}.

The trigger output is available as {{ input }} and includes from, subject, text, receivedAt, and an attachments array where each entry is a reference of the shape { id, filename, contentType }. The bytes are not in the trigger output; you fetch them in the next step.

Step 2: Restrict the trigger to PDFs and trusted senders

Still in the Mailhook trigger, set the optional From allowlist to the addresses or domains you trust to feed the archive (for example your vendors or internal distribution lists), and optionally set a Subject regex to only accept matching subjects. These filters stop unrelated mail from triggering runs. Filtering on sender and subject here is cheaper and more reliable than filtering later, because runs that do not match never start.

Step 3: Fetch the PDF bytes with an Attachment node

Add an Attachment node after the trigger. (The designer only allows an Attachment node when the workflow uses a Mailhook trigger.) Configure it to pull just the PDFs:

  • Mode: choose Single to grab the first matching attachment as one object, or Multiple if a single email may carry several PDFs.
  • Content type: application/pdf
  • Filename pattern: *.pdf
  • Fail if no attachment matches: turn this on so emails with no PDF stop cleanly instead of indexing nothing.

In Single mode the output is one object: { filename, contentType, size, content }, where content is the base64 body you feed into Knowledge. In Multiple mode the output is { attachments: [...], count, totalBytes }, which you iterate over with a Loop node in Step 4.

Step 4: Embed the PDF into your persistent collection

Add a Knowledge node set to Embed mode. Configure it to write into your long-lived archive:

  • Collection: pick the persistent collection you created, for example reference-docs. Do not pick Transient: transient collections are auto-cleaned at the end of the run, which would discard the document you just indexed.
  • File Name: use the incoming file name, {{ attachment.filename }}. If a document with that name already exists in the collection, it is overwritten, so a corrected re-send updates the archive in place.
  • Document Type: PDF
  • Document Input: {{ attachment.content }} (the base64 body from the Attachment node).
  • Output Variable: name it embedResult so you can reference the returned chunk count later.

If you chose Multiple mode in Step 3, wrap this Knowledge node inside a Loop node iterating {{ attachment.attachments }}, and reference the current item's filename and content inside the loop body so every PDF in the email is embedded.

Step 5: Confirm the upload in Slack

Add a Connector node, choose the Slack connector in Direct mode, and select the send-message tool. Direct mode is the right choice here: it is one deterministic call with no AI cost. Map the inputs:

  • channel: #doc-intake (or your channel ID).
  • text: a templated summary, for example:
Indexed "{{ attachment.filename }}" from {{ input.from }} into the reference-docs collection ({{ embedResult.chunkCount }} chunks). Received at {{ input.receivedAt }}.

This gives your team a real-time feed of what entered the archive and from whom, which doubles as an audit trail. If you prefer email over chat, swap this step for a Send Email node instead.

Step 6: Query the archive from any workflow

Once documents are flowing in, any workflow in the workspace can read the collection. In a separate workflow, add a Knowledge node in Query mode, set Collection to reference-docs, supply a natural-language Prompt (for example What is the warranty period in the latest vendor data sheet?), and set a Result Count. Because collections are workspace-scoped, you build the archive once here and reuse it everywhere. You can also ask Miraxa, the intelligent layer across your automation, to scaffold a query workflow for you: try a prompt like "Add a Knowledge node in Query mode that searches the reference-docs collection and posts the answer to Slack."

Tips

  • Always embed and query a collection with the same embedding model. The model is fixed when you create the collection, so all documents added through this workflow stay consistent automatically.
  • Use a descriptive Address prefix per intake (for example contracts vs specs) so people can tell at a glance what each Mailhook address feeds.
  • Reference {{ embedResult.chunkCount }} in your Slack message: a chunk count of zero is a strong signal the PDF was empty or image-only and may need OCR handling.
  • If senders forward large scanned PDFs, watch the 10 MB per-attachment and 25 MB per-run limits and split very large files at the source.

Common Pitfalls

  • Choosing Transient instead of a persistent collection. Transient collections are wiped when the run finishes, so the document vanishes. For an archive, always select the named persistent collection.
  • Feeding the trigger attachment reference into Knowledge. The trigger only exposes { id, filename, contentType }, not bytes. You must route through the Attachment node and use {{ attachment.content }} as the Document Input.
  • Forgetting Multiple-mode looping. In Multiple mode the Attachment output is a list under attachments; embedding it directly will not work. Wrap the Knowledge node in a Loop over {{ attachment.attachments }}.
  • Relying on file-name uniqueness for versioning. Embedding the same File Name overwrites the prior copy. If you need to keep every revision, include a timestamp such as {{ input.receivedAt }} in the file name.

Testing

Before announcing the address widely, test with one trusted sender and one small PDF. Email a single document to your Mailhook address, then open the workflow's execution history and confirm the Attachment node returned a non-zero size and the Knowledge node reported chunks in embedResult. Open the collection in the Knowledge section and verify the document appears with status READY and the expected chunk count. Confirm the Slack message landed in your channel. Finally, re-send the exact same email to confirm deduplication prevents a second run, and send a non-PDF to confirm your filters stop it. Once those checks pass, share the address with your wider team.

Learn More

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