fix: route email trigger path through standard info channel (#8996)

* docs(skill): document email triggers and S3 attachments

Add an "Email triggers" section to the triggers skill covering the
local-part config, the parsed_email/raw_email/email_extra_args payload,
the URL-style extras convention, where to find trigger_path (only with
a preprocessor, at event.trigger_path), and — most importantly — that
binary attachments are uploaded to the workspace S3 bucket and surface
as `{ s3: "windmill_emails/<job_id>/attachments/<filename>" }`. Scripts
must use wmill.loadS3File / wmill.load_s3_file to read them.

Also pulls EmailTrigger into the schema mappings so a real
`email_trigger.schema.yaml` is generated, and adds Email/Azure to the
trigger kinds list in the CLI agent guidance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref for email trigger path fix

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 26184ab7a4aadfc529dcedf038aa08d36c7ad381

This commit updates the EE repository reference after PR #553 was merged in windmill-ee-private.

Previous ee-repo-ref: 318a46897a605dc9be3817901f35ba5a99a0a525

New ee-repo-ref: 26184ab7a4aadfc529dcedf038aa08d36c7ad381

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
hugocasa
2026-05-01 18:23:09 +02:00
committed by GitHub
parent 9cb777a6b6
commit 21411282bb
9 changed files with 267 additions and 4 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ When a new app needs to be created, YOU run \`wmill app new\` yourself with \`--
## Triggers
You MUST use the \`triggers\` skill to configure HTTP routes, WebSocket, Kafka, NATS, SQS, MQTT, GCP, or Postgres CDC triggers.
You MUST use the \`triggers\` skill to configure HTTP routes, WebSocket, Kafka, NATS, SQS, MQTT, GCP, Azure, Email, or Postgres CDC triggers.
## Schedules
+109
View File
@@ -5563,6 +5563,49 @@ Examples:
- \`u/user/webhook.http_trigger.yaml\`
- \`f/data/kafka_consumer.kafka_trigger.yaml\`
- \`f/sync/postgres_cdc.postgres_trigger.yaml\`
- \`f/inbound/orders.email_trigger.yaml\`
## Email Triggers
An email trigger routes incoming emails to a script or flow. Each trigger reserves a local-part: emails sent to \`<local_part>@<windmill_email_domain>\` are delivered to the configured runnable. Set \`workspaced_local_part: true\` to namespace it per workspace (the actual recipient becomes \`<workspace_id>-<local_part>@…\`); on Windmill Cloud this is required.
Senders may append URL-style extras to the local-part with \`+\`: \`mytrigger+foo=bar+baz=qux@…\`. They flow through to the script as \`email_extra_args\` (see below).
### Payload
The runnable receives:
- \`parsed_email\`\`{ headers, text_body, html_body, attachments[] }\`. Each \`attachment\` has \`{ headers, body }\`.
- \`raw_email\` — the raw RFC 822 message as a string, **or** an S3 object (\`{ s3: "windmill_emails/<job_id>/raw.eml" }\`) if the message exceeds 1 MiB.
- \`email_extra_args\` (optional, only when sender appended \`+key=value\` extras) — a flat object of the parsed extras.
With a preprocessor, all of the above are nested under \`event\` along with \`event.kind = "email"\` and \`event.trigger_path\` (the trigger's path). Without a preprocessor, \`trigger_path\` is **not** exposed — add a preprocessor if you need it.
### Attachments are S3 objects
Binary attachments are uploaded to the workspace S3 bucket and surface in \`parsed_email.attachments[i].body\` as:
\`\`\`json
{ "s3": "windmill_emails/<job_id>/attachments/<filename>" }
\`\`\`
To read the bytes inside a script, use the wmill SDK:
\`\`\`ts
// TypeScript
import * as wmill from "windmill-client"
const file = await wmill.loadS3File(parsed_email.attachments[0].body)
\`\`\`
\`\`\`python
# Python
import wmill
data = wmill.load_s3_file(parsed_email["attachments"][0]["body"])
\`\`\`
If the workspace has no S3 resource configured (Workspace Settings Object storage), \`body\` falls back to the string \`"configure s3 in the workspace settings to handle attachments"\`. The same applies to large \`raw_email\` bodies. Email attachment storage requires the server to be built with the \`parquet\` feature.
Text/HTML/inline parts are placed inline in \`body\` as strings.
## CLI Commands
@@ -7180,6 +7223,71 @@ required:
- azure_mode
- scope_resource_id
- subscription_name
`,
"email_trigger": `type: object
properties:
script_path:
type: string
description: Path to the script or flow to execute when triggered
permissioned_as:
type: string
description: The user or group this trigger runs as (permissioned_as)
is_flow:
type: boolean
description: True if script_path points to a flow, false if it points to a script
labels:
type: array
items:
type: string
local_part:
type: string
workspaced_local_part:
type: boolean
error_handler_path:
type: string
error_handler_args:
type: object
description: The arguments to pass to the script or flow
retry:
type: object
properties:
constant:
type: object
description: Retry with constant delay between attempts
properties:
attempts:
type: integer
description: Number of retry attempts
seconds:
type: integer
description: Seconds to wait between retries
exponential:
type: object
description: Retry with exponential backoff (delay doubles each time)
properties:
attempts:
type: integer
description: Number of retry attempts
multiplier:
type: integer
description: Multiplier for exponential backoff
seconds:
type: integer
minimum: 1
description: Initial delay in seconds
random_factor:
type: integer
minimum: 0
maximum: 100
description: Random jitter percentage (0-100) to avoid thundering herd
retry_if:
$ref: '#/components/schemas/RetryIf'
description: Retry configuration for failed module executions
required:
- script_path
- permissioned_as
- is_flow
- local_part
`,
"gcp_trigger": `type: object
properties:
@@ -8116,6 +8224,7 @@ export const SCHEMA_MAPPINGS: Record<string, SchemaMapping[]> = {
{ name: "SqsTrigger", schemaKey: "sqs_trigger", filePattern: "*.sqs_trigger.yaml" },
{ name: "GcpTrigger", schemaKey: "gcp_trigger", filePattern: "*.gcp_trigger.yaml" },
{ name: "AzureTrigger", schemaKey: "azure_trigger", filePattern: "*.azure_trigger.yaml" },
{ name: "EmailTrigger", schemaKey: "email_trigger", filePattern: "*.email_trigger.yaml" },
],
"schedules": [
{ name: "Schedule", schemaKey: "schedule", filePattern: "*.schedule.yaml" },