Skip to content

Email Import Node

Email Import gives each canvas node its own inbound email address. You send plaintext or attachments to that address, and Fontana starts the workflow as its owner, no manual click required.

  • Real inbound mail - Fontana receives SMTP on the install host (platform Haraka on TCP 25) for addresses on @<tenant>.<env>.<baseDomain>, not a polled mailbox
  • One address per node - the local part is server-generated and opaque; it is never derived from your workflow id or username
  • Owner-triggered runs - the run fires with your workflow’s owner identity, the same identity a scheduled cron run uses
  • Inbox mode - each new email triggers one run that contains your entire inbox as a datagrid: one row per email, newest first, up to maxEmails rows (default 100)
  • Structured dataset rows - each row has typed columns (from, sent, subject, body, to, cc, messageId) plus an attachments array
  • Parsed attachments - Docling-supported files contribute markdown; CSV/TSV/PSV contribute tabular rows; other types soft-fail with parseError without blocking the run

On the canvas node (full card and compact / graph simplified view) a pause / play control toggles whether new mail starts runs. Pause sets the node disabled (common.execution.enabled: false); inbound SMTP then fail-closes for that node with no run. Resume turns triggers back on. You can still open the node and replay past messages manually while paused.

Save the workflow, then open the Email Import tab on the node. Fontana provisions the address the first time you open the tab and shows it once ready:

<opaque-local-part>@<your-tenant>.<your-environment>.<baseDomain>

Example: wf-….@demo.flow-dev.fontana-ai.com. You always see the address your deployment actually has, never a client-guessed value. If your deployment has not enabled inbound email, the tab tells you so instead of showing a broken address.

  1. The sender’s MTA delivers to MX for your tenant mail hostname; the install host accepts SMTP on TCP 25 (STARTTLS) into the platform Haraka adapter.
  2. The adapter asks that tenant’s Convex control plane which workflow and node the opaque local-part maps to (EMAIL_INGEST_KEY, metadata only).
  3. MIME body, structured metadata (email-meta.json), and attachment bytes are written straight into the tenant workflow-engine upload directory (same store as File Input), using a dedicated upload key. Convex does not store or transit the MIME bytes.
  4. Convex ingest collects file references for all previous emails received on this node, merges in the new email’s references, and sorts everything newest-first up to maxEmails (default 100). If a run is already queued but not yet started, its file references are replaced with the updated inbox. If the engine is processing a previous run, a new run is queued to start after it finishes.
  5. The engine preload step groups file references by email, reads each email’s body and metadata, and writes one structured row per email to the node’s output port before any node in the workflow runs.
  6. Each attachment is parsed on that run (Docling markdown, tabular rows, or soft-fail parseError) and nested under attachments[].
  7. A run starts using the workflow owner’s identity for connectors and secrets, exactly as a scheduled cron run would.

The output port is a multi-row datagrid with one row per email in your inbox, newest first:

Column Type Notes
from string MIME From
sent string UTC sent stamp (same shape historically used on the canonical Sent: line)
subject string MIME Subject
body string Plaintext body only (no header block)
to string[] MIME To addresses (empty when absent)
cc string[] MIME Cc addresses (empty when absent)
messageId string Normalized Message-ID (empty when absent)
attachments object[] Per-file metadata and parse results

Each attachments[] element includes name, extension, size, contentType, storedName, parseEngine (docling | tabular | none), and optional markdown, rows, or parseError. BCC is not exposed on output.

Row order is newest-first. The number of rows is capped by maxEmails (default 100). When a new email arrives, the entire inbox snapshot is re-materialized as the output dataset for that run.

This shape is Email Import only. File Input Paste mode still uses a single body column with an Outlook-style header block when you paste mail into Paste.

Read native columns (from, sent, subject, to, cc, messageId, attachments) directly from Email Import. Wire a Template node only when you need fields embedded inside the plaintext body (for example Client / Order / Qty lines), then a Schema node for typed shapes. The email-structured-data-extract skill still builds Paste → Template → Schema for File Input Paste corpora; for inbound Email Import it prefers native header columns and Jinja for body-field extraction only.

Explore ships an Inbound Email Showcase community template with Email Import → Template (body fields) → Schema → Operation SWITCH siphons (rush vs standard by Qty) → separate Save File exports.

On the Email Import tab, below the provisioned address, the Inbox panel lists every email this node has received (subject, sender, date). Click any row to expand it and read the body text. The body is fetched directly from the workflow-engine file store when you open the row; Convex is not in that path.

New runs start automatically when mail arrives. You do not need to replay or refresh; use the canvas Run button for a manual run.

Inbound email files are not listed on File Input Engine Files; the Inbox panel on this node is the only UI for these messages.

The maxEmails setting in the Settings tab caps how many recent messages are packed into each run as rows (default 100). When your inbox exceeds the cap the oldest emails are dropped from the run; the Inbox panel still shows every received message. The other Settings fields (markAsRead, includeAttachments, autoReconnect) are stored on the node but not yet read by ingest.

  • It does not poll an IMAP mailbox or accept mailbox credentials
  • It does not map the sender’s address to a Fontana user; the run always fires as the workflow owner
  • It does not accept mail from third-party inbound webhook providers
  • It does not see BCC’d or envelope-only recipients: your provisioned address is matched against the message’s To and Cc headers only. Mail addressed to your provisioned address solely through BCC does not trigger a run.

Inbound email is an operator-enabled deployment feature. You enable the platform Haraka chart via the host fontana.yaml email.inbound block (domain, optional requireTls), point MX for each <tenant>.<domain> at the install host, and run fontana apply. Apply seeds per-tenant Convex ingest and engine upload credentials into the platform registry and publishes host TCP 25 to the platform inbound-smtp Service. STARTTLS reuses the Caddy ACME certificates already issued for those Flow tenant hosts; you do not supply separate mail PEMs. Apply fails closed if host TCP 25 cannot be published, or if requireTls is true and those Caddy certs are missing. See the Fontana CLI reference, docs/SECRET_HANDLING.md for the inbound email keys, and RUNBOOK_K8S.md for enable steps.

  • File Input - Paste mode still uses the Outlook-style body header block; Docling on document attachments
  • Template - extracts fields from plaintext body when native columns are not enough
  • Workflow schema - Full schema reference