Skip to main content

Workflow: EmailTemplate Type

Introduction

An EmailTemplate workflow is a specialized workflow type that generates fully composed email content from business data.
Instead of sending the email directly, it returns the subject, body, and attachments so that other workflows or applications can send the email using standard email tasks or external systems.

EmailTemplate workflows are ideal when you need to:

  • Standardize outbound communication (e.g., order confirmations, shipment status updates, invoices ready, POD notifications).
  • Separate template logic from sending logic, so different channels (TMS UI, integrations, background workflows) can reuse the same email content.
  • Build dynamic, data-driven emails using order, customer, shipment, and document data.
  • Reuse existing document workflows as attachments (e.g., commercial invoice PDF, labels, packing lists).

EmailTemplate workflows use the standard workflow manifest structure, but with:

  • workflow.workflowType: "EmailTemplate" to mark the workflow as an EmailTemplate workflow.
  • A fixed output contract that returns:
    • subject: Email subject line.
    • body: Email body as HTML/text.
    • attachments: Array of attachment definitions compatible with the Email/Send@1 task.

YAML Structure

An EmailTemplate workflow is defined using the standard workflow manifest with a specialized workflowType and required outputs.

High-level structure:

workflow:
workflowId: "00000000-0000-0000-0000-000000000000"
name: "Emails / Order Confirmation"
isActive: true
workflowType: "EmailTemplate"
executionMode: "Sync" # EmailTemplate workflows should execute synchronously
version: "1.0"
tags:
- "email"
- "template"
- "order"

inputs:
- name: "orderId"
type: "number"
props:
required: true
visible: false

outputs:
- name: "subject"
mapping: "subject"
- name: "body"
mapping: "body"
- name: "attachments"
mapping: "attachments"

activities:
- name: "data"
steps: []
- name: "composeEmail"
steps: []

Key structural notes:

  • workflow.workflowType must be set to "EmailTemplate".
  • executionMode should be "Sync", because email content is usually needed immediately by the caller.
  • Inputs typically include identifiers such as orderId, customerId, or other domain keys.
  • Outputs must include subject, body, and attachments.
  • Activities usually follow this pattern:
    1. Load domain data (e.g., Order, Customer).
    2. Build reusable metadata (optional).
    3. Compose email subject and body.
    4. Build attachment definitions (referencing documents or workflows).

Attribute Description

Workflow-Level Attributes

AttributeTypeRequiredDescriptionExample
workflow.workflowIdstringYesUnique identifier of the workflow definition."2e28201d-704e-40b1-8568-7a87d198e255"
workflow.namestringYesDisplay name of the workflow."Emails / Order Confirmation"
workflow.workflowTypestringYesMust be set to "Email Template" for this workflow type."Email Template"
workflow.executionModestringYesExecution mode. Email Template workflows should use "Sync"."Sync"
workflow.versionstringYesVersion of the workflow definition file."1.0"
workflow.tags[]arrayRecommendedTags for categorization and discovery (e.g., email, order, template).["email","order","template"]
workflow.descriptionstringNoHuman-readable description of what the template does."Order confirmation email template"

For all other workflow-level fields (e.g., logLevel, concurrency, enableAudit), see Workflow Manifest YAML.

Inputs

EmailTemplate workflows are typically driven by an order-centric input model.

AttributeTypeRequiredDescriptionExample
inputs[].namestringYesName of the input parameter."orderId"
inputs[].typestringYesData type of the input (e.g., number, text, domain-specific types)."number"
inputs[].props.*objectNoStandard input UI and validation properties.See manifest

Typical input:

NameTypeRequiredDescription
orderIdnumberYesUnique identifier of the order.

Outputs (Email Contract)

EmailTemplate workflows must return the following outputs:

AttributeTypeRequiredDescriptionExample
outputs.subjectstringYesEmail subject line after all templating and data mapping."Order #12345 confirmed"
outputs.bodyobjectYesEmail body object, compatible with Email/Send@1 (html and/or text fields).{ html: "<h1>...</h1>", text: "..." }
outputs.attachmentsarrayYesArray of attachment definitions compatible with Email/Send@1. May be empty.[{ name: "Invoice.pdf", documentWorkflowId: "..." }]

subject

  • Type: string
  • Required: Yes
  • Description: The final subject line for the email.
  • Example: "Order #12345 confirmation – ACME Logistics"

body

Email body should follow the structure used by the Email task:

FieldTypeRequiredDescriptionExample
body.htmlstringRecommendedRich HTML content of the email body."<h1>Order...</h1>"
body.textstringOptionalPlain-text version of the email body (fallback)."Order 12345 confirmed..."
  • html: Preferred for rich formatting; rendered in most clients.
  • text: Provides a simple fallback for plain-text clients or logging.

attachments[]

Attachment objects must be compatible with Email Task attachments:

FieldTypeRequiredDescriptionExample
attachments[].namestringNoDisplay name of the attachment file."CommercialInvoice.pdf"
attachments[].attachmentIdnumberNoReference to an existing stored attachment by ID.101
attachments[].orderDocumentIdnumberNoReference to an order document record.102
attachments[].documentWorkflowIdstringNoDocument workflow ID used to generate an attachment on demand."4afb7c5f-9cf9-46a2-973f-2df763e935d1"
attachments[].documentWorkflowVariablesobjectNoVariables passed to the document workflow when generating the attachment.{ orderId: 12345 }
attachments[].contentstringNoBase64-encoded file content (used when attaching ad-hoc content)."VGhpcyBpcyBhIHRlc3QgYXR0YWNobWVudA=="

At least one of attachmentId, orderDocumentId, documentWorkflowId, or content should be provided for each attachment entry.

Triggers

EmailTemplate workflows are usually triggered manually or from other workflows:

AttributeTypeRequiredDescriptionExample
triggers[].typestringYesTrigger type (Manual, Entity, Schedule)."Manual"
triggers[].entityNamestringRecommended for Manual/EntityEntity where the action is exposed."Order"
triggers[].displayNamestringRecommendedLabel shown in the UI."Send Email"

Examples

Example: Order Confirmation Email Template

This example workflow:

  1. Loads order and customer data.
  2. Builds a metadata object.
  3. Composes the subject and body using metadata.
  4. Builds attachments using document workflows and order documents.
workflow:
name: "Emails / Order Confirmation"
workflowId: "2e28201d-704e-40b1-8568-7a87d198e255"
isActive: true
workflowType: "EmailTemplate"
executionMode: "Sync" # EmailTemplate workflows should execute synchronously
version: "1.0"
tags:
- "email"
- "order"
- "template"

variables:
- name: "organizationId"
value: 123

inputs:
- name: "orderId"
type: "number"
props:
required: true
visible: false

outputs:
- name: "subject"
mapping: "subject"
- name: "body"
mapping: "body"
- name: "attachments"
mapping: "attachments"

triggers:
- type: "Manual"
displayName: "Generate Order Confirmation Email"
entityName: "Order"

activities:
- name: data
steps:
- task: "Query/GraphQL"
name: "getOrder"
inputs:
query: |
query($orderId: Int!, $organizationId: Int!) {
order(orderId: $orderId, organizationId: $organizationId) {
orderId
orderNumber
orderDate
totalAmount
customer {
customerId
name
email
}
}
}
variables:
orderId: "{{ orderId }}"
organizationId: "{{ organizationId }}"
outputs:
- name: "order"
mapping: "order"

- name: metadata
steps:
- task: "Utilities/SetVariable@1"
name: "buildMetadata"
inputs:
name: "meta"
value:
orderId: "{{ data.getOrder.order.orderId }}"
orderNumber: "{{ data.getOrder.order.orderNumber }}"
orderDate: "{{ data.getOrder.order.orderDate }}"
totalAmount: "{{ data.getOrder.order.totalAmount }}"
customerId: "{{ data.getOrder.order.customer.customerId }}"
customerName: "{{ data.getOrder.order.customer.name }}"
customerEmail: "{{ data.getOrder.order.customer.email }}"

- name: composeEmail
steps:
# Subject
- task: "Utilities/SetVariable@1"
name: "buildSubject"
inputs:
name: "subject"
value: "Order {{ meta.orderNumber }} confirmation – Thank you for your business"

# Body (HTML + Text)
- task: "Utilities/SetVariable@1"
name: "buildBody"
inputs:
name: "body"
value:
html: |
<h1>Order Confirmation</h1>
<p>Dear {{ meta.customerName }},</p>
<p>Thank you for your order <strong>#{{ meta.orderNumber }}</strong> placed on {{ meta.orderDate }}.</p>
<p>Total Amount: <strong>{{ meta.totalAmount }}</strong></p>
<p>You can find your documents attached to this email.</p>
<p>Best regards,<br/>CargoXplorer TMS</p>
text: |
Dear {{ meta.customerName }},

Thank you for your order #{{ meta.orderNumber }} placed on {{ meta.orderDate }}.
Total Amount: {{ meta.totalAmount }}

Your documents are attached to this email.

Best regards,
CargoXplorer TMS

# Attachments compatible with Email/Send@1
- task: "Utilities/SetVariable@1"
name: "buildAttachments"
inputs:
name: "attachments"
value:
- name: "CommercialInvoice_{{ meta.orderNumber }}.pdf"
documentWorkflowId: "4afb7c5f-9cf9-46a2-973f-2df763e935d1"
documentWorkflowVariables:
orderId: "{{ meta.orderId }}"
organizationId: "{{ organizationId }}"
- name: "Label_{{ meta.orderNumber }}.pdf"
orderDocumentId: 102

The caller (another workflow or an external system) can then:

  1. Execute this Email Template workflow with orderId.
  2. Use the returned subject, body, and attachments as inputs to Email/Send@1 (or equivalent email sending mechanism).

Best Practices

  • Keep logic pure and idempotent:
    • EmailTemplate workflows should not send emails themselves.
    • They should only compute and return subject, body, and attachments.
  • Align outputs with Email/Send@1:
    • Ensure body matches the expected { html, text } structure.
    • Ensure attachments entries use the same fields as the Email task.
  • Use metadata for reuse:
    • Build a meta object containing all derived values (names, totals, formatted dates).
    • Reuse meta across subject, body, and attachments to avoid duplication.
  • Prefer Sync execution:
    • Use executionMode: "Sync" so callers can immediately receive the email content.
    • Avoid long-running operations inside Email Template workflows.
  • Reuse Document workflows for attachments:
    • Use documentWorkflowId and documentWorkflowVariables to attach generated documents.
    • Keep document generation logic in Document workflows, not in the EmailTemplate workflow.
  • Minimize PII exposure:
    • Include only the personal data required to render the email.
    • Avoid persisting sensitive metadata unless necessary.
  • Localization and branding:
    • Use metadata to inject localized labels, currency formats, and branding.
    • Consider separate templates or conditionals for different divisions or languages.