Send email
Step · Stable
Send an email through the best connected account (Gmail / Microsoft 365 / Resend).
Delivers email through the workspace’s mail carrier: a connected Gmail or Microsoft 365 account, or the Resend transactional sender. The carrier resolves automatically (step-level via override → workspace default → the single connected account, else Resend). to, subject, and body accept Jinja2 templates rendered against the run context. to takes one address or several — comma / semicolon / newline separated, or a reference that resolves to a list — and everyone named receives the same email on one To line; cc and bcc take the same shapes, cc visible to everyone and bcc visible to nobody but the audit trail. attachments takes document-store ids (comma-separated or a JSON list) and attaches the stored files, capped at ~10 MB total. Delivery failure logs a warning but does not halt the run; a disconnected carrier fails the step with a reconnect error instead of silently switching sender.
When to use
Section titled “When to use”Use whenever a workflow step needs to deliver a message to an email address — a weekly digest, an invoice notification, an approval confirmation. The to, subject, and body all accept {{ template }} references so you can slot in any upstream output directly.
When not to use
Section titled “When not to use”For an in-app alert visible in the bell panel, use Send notification. For a WhatsApp message, use Send WhatsApp. If you need to receive an email (not send one), use the Incoming email trigger.
Inputs
Section titled “Inputs”string · required
The recipient email. A literal address, or a {{ reference }} to one produced upstream (e.g. a contact lookup or the invoking user). Use {{ user.email }} to email the person who ran the flow. Several recipients go in this one field — separate them with commas (semicolons and newlines work too), mix literals and refs freely, or point at a {{ ref }} that resolves to a list of addresses. Everyone named gets one email and sees the others in the To line; to keep them apart, loop with For each and send one email per recipient.
Example: jakub@example.com, ops@firma.cz
- ✓
ops@firma.cz— literal address - ✓
{{ user.email }}— the invoking user - ✓
{{ find_contact.email }}— from an upstream contact lookup - ✓
ops@firma.cz, {{ user.email }}— two recipients — commas separate them, literals and refs mix - ✓
{{ find_contacts.emails }}— a ref that resolves to a list of addresses — all of them are used - ✗
Jakub— a name is not an address — use the email or a {{ ref }} - ✗
ops@firma.cz a ucetni@firma.cz— recipients must be separated by a comma, not prose
string · optional
Optional. Anyone here receives the email and is visible to every other recipient — use it when being copied is part of the point (a manager on an approval, a shared mailbox on a customer reply). Takes the same shapes as To: one address, several separated by commas, or a {{ ref }} that resolves to a list. Leave it empty and no Cc line is sent at all.
Example: sef@firma.cz
- ✓
sef@firma.cz— copy one colleague - ✓
ucetni@firma.cz, {{ user.email }}— copy the accountant and whoever ran the flow - ✗
{{ deal.owner }}— that is a name/id, not an address — reference the email field ({{ deal.owner_email }})
string · optional
Optional. Anyone here receives the email without any other recipient seeing that they did — the usual use is an archive or compliance mailbox. The send is still recorded in full on the mail.sent event, so blind means blind to the recipients, never to your own audit trail. Same shapes as To.
Example: archiv@firma.cz
- ✓
archiv@firma.cz— silent archive copy - ✗
{{ contact.email }}— do not hide the actual recipient in Bcc — that is what To is for
subject
Section titled “subject”string · optional
Plain text or a template — {{ weather.headline }} reuses a prepared summary.
Example: Týdenní souhrn
- ✓
Týdenní souhrn— literal subject - ✓
Počasí v {{ geo.location }}— templated subject
string · required
The email body. Mix literal text and {{ refs }}; a module that pre-formats text (e.g. weather.report) can be dropped in whole. Required — an email with no text/html is rejected by the provider.
Example: Dobrý den, {{ report.text }} S pozdravem
- ✓
{{ weather.report }}— a ready-made body from weather - ✓
Ahoj {{ user.firstName }}, hotovo!— literal + ref
attachments
Section titled “attachments”string · optional
Optional. Attach stored documents to the email by their document-store id — the id Render document, Document store, and the incoming-email attachment refs produce. Several ids: separate with commas or pass a JSON list. An unknown id fails the step, and so does a configured reference that resolves to nothing (a typo’d {{ ref }} must scream, not silently send without the attachment); total size is capped at ~10 MB — anything past the cap is skipped with a warning (see attachments_skipped in the step output).
Example: {{ render.document_id }}
- ✓
{{ render.document_id }}— attach the PDF a Render document step just produced - ✓
{{ render.document_id }}, {{ trigger.memory_item_id }}— two stored documents, comma-separated - ✗
/tmp/report.pdf— a file path is not a document id — attachments resolve from the document store only
choice · optional · one of automatic, resend, gmail, o365
The mail carrier. Automatic follows the workspace default; an explicit choice pins this one step to that service. Gmail / Microsoft 365 send as the connected account itself, so the recipient sees a real mailbox, not a platform sender.
- ✓
automatic— default — let the workspace decide - ✓
gmail— user explicitly asked “send it from my Gmail” - ✗
gmail— do not pin a carrier the user never mentioned — leave automatic
in_reply_to
Section titled “in_reply_to”string · optional
Blank is automatic: on a flow fired by the Incoming email trigger, the reply threads onto the email that fired it, which is what a person expects when they write in and get an answer. On any other trigger blank sends a new conversation, because there is no message to answer. Type “none” to force a new conversation even on an email-triggered flow — a bulk notice that happens to be triggered by mail, say. The step reports which message it threaded onto as threaded_to.
- ✓ “ — the default — answer whatever wrote in
- ✓
none— deliberately a new conversation, not a reply - ✓
{{ message_id }}— the same thing blank does, spelled out - ✗
{{ send_first.delivery_id }}— a delivery id is ours, not an RFC Message-Id — use {{ send_first.message_id }}
Outputs
Section titled “Outputs”Requires
Section titled “Requires”modules module_send_email
Auto-generated from the skill registry (load_skills()). Do not edit by hand.