Email triggers
Scripts and flows can be triggered by email messages sent to a specific email address, leveraging SMTP.
Email triggers on Windmill Community Edition are limited to 100 emails per day.
Configuration
Email triggers is available on both cloud and self-hosted instances.
Cloud
On cloud instances, Email triggers is already configured. You can try it from demo
workspace.
Self-hosted
First, make sure that the port 25 is exposed either on your instance public IP or a separate IP and that it redirects to the Windmill app on port 2525. The Caddyfile already contains the necessary configuration for this. For Kubernetes, you will find example configurations for some providers on the Windmill helm charts repository.
In addition, you will need to create one or two records in your DNS provider depending on your setup.
If the port 25 is exposed on the same IP as the Windmill instance (e.g. docker-compose with Caddy):
- An MX record from
mail.<instance domain>
to<instance domain>
.
If the port 25 is exposed through a different IP (e.g. Kubernetes):
- An A/CNAME record that points to the IP of the Windmill instance with port 25 exposed (for example
mail_server.<instance domain>
). - An MX record from
mail.<instance domain>
to the record defined above (mail_server.<instance domain>
if following the example).
You can choose any email domain, we suggest using mail.<instance domain>
.
Once you have defined the DNS settings, set the email domain in the instance settings under the "Core" tab.
How to use
You will now find the specific email address to use in the webhooks panels for each script and flow.
The email address takes the form <path/hash>+<workspace+path/hash+token base32 encoded>@<email domain>
.
Your script will receive two arguments:
raw_email
: the raw email as a stringparsed_email
the parsed email with the following attributes:headers
a dictionary with the email headers (e.g.From
,To
,Subject
,Date
)text_body
the text body of the email (or textified html body if none)html_body
the html body of the email (or htmlified text body if none)attachments
list of attachments with the following attributes:headers
a dictionary with the attachment headersbody
the attachment data
Attchments are uploaded to the workspace object storage (s3) and are replaced in parsed_email
by s3 objects ({ s3: "path/to/key" }
).
A workspace object storage is required for attachments to be handled.
Here's an example script:
export async function main(raw_email: string, parsed_email: any) {
// do something with the email
}
And if you use a preprocessor, the script could look like this:
export async function preprocessor(
raw_email: string,
parsed_email: any,
wm_trigger: {
kind: "email",
},
) {
// return what you want to pass to the main function, for instance the sender email address and the email body
return {
sender_address: parsed_email.headers["From"][0].address,
email_body: parsed_email.text_body
}
}
export async function main(sender_address: string, email_body: string) {
// do something with the sender email address and the email body
}
From a script or flow deployed page, you will find on the "Details & Triggers" - "Email" tab the email address to use.