Skip to Content
Evaluate Get Started Plugins Glossary

Sending Emails

Send email notifications at specific workflow stages using the SendEmail action in BasicPlugin. This pattern notifies users about process events - order confirmations, approval requests, completion notifications - via SMTP.

Real-world scenario

A customer support workflow sends an email notification when a ticket is resolved. A manager triggers the SendEmail command from the workflow UI. The workflow sends an HTML-formatted email to the customer with the resolution details and a satisfaction survey link.

Workflow scheme

Email notification workflow scheme

The scheme starts in the Start activity, which initializes process parameters (customer email, name, ticket details) via SetParameter actions. A SendEmail command triggers the transition to the SendNotification activity, which sends the email with parameter-substituted content via the SendEmail action.

Related capabilities: SendEmail action, Setting_Mailserver* configuration properties.

email-notification.xml
<Process Name="EmailNotification" CanBeInlined="false">  <Designer />  <Commands>    <Command Name="SendEmail" />  </Commands>  <Activities>    <Activity Name="Start" State="Start" IsInitial="True"              IsFinal="False" IsForSetState="True"              IsAutoSchemeUpdate="True">      <Implementation>        <ActionRef Order="1" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "CustomerEmail",              "Value": "\"alice@example.com\""            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="2" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "CustomerName",              "Value": "\"Alice Johnson\""            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="3" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "TicketId",              "Value": "\"TKT-2026-0842\""            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="4" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "AgentName",              "Value": "\"Bob Smith\""            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="5" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "Resolution",              "Value": "\"The issue was resolved by restarting the server\""            }          ]]></ActionParameter>        </ActionRef>        <ActionRef Order="6" NameRef="SetParameter">          <ActionParameter><![CDATA[            {              "ParameterName": "SurveyLink",              "Value": "\"https://survey.example.com/ticket-0842\""            }          ]]></ActionParameter>        </ActionRef>      </Implementation>      <Designer X="100" Y="200" />    </Activity>    <Activity Name="SendNotification" State="NotificationSent" IsInitial="False"              IsFinal="True" IsForSetState="True"              IsAutoSchemeUpdate="True">      <Implementation>        <ActionRef Order="1" NameRef="SendEmail">          <ActionParameter><![CDATA[            {              "To": "@CustomerEmail",              "Subject": "Your support ticket #@TicketId has been resolved",              "Body": "<h2>Your ticket has been resolved</h2><p>Dear @CustomerName,</p><p>Your support ticket <strong>#@TicketId</strong> has been resolved by @AgentName.</p><p><strong>Resolution:</strong> @Resolution</p><p>Please take a moment to fill out our <a href='@SurveyLink'>satisfaction survey</a>.</p><p>Thank you,<br/>Support Team</p>",              "IsHTML": true            }          ]]></ActionParameter>        </ActionRef>      </Implementation>      <Designer X="400" Y="200" />    </Activity>  </Activities>  <Transitions>    <Transition Name="Start_SendNotification" To="SendNotification"                From="Start" Classifier="Direct" IsFork="false"                AllowConcatenationType="And" RestrictConcatenationType="And"                ConditionsConcatenationType="And"                MergeViaSetState="false" DisableParentStateControl="false">      <Triggers>        <Trigger Type="Command" NameRef="SendEmail" />      </Triggers>      <Conditions>        <Condition Type="Always" />      </Conditions>      <Designer />    </Transition>  </Transitions></Process>

Configuration

Configure SMTP settings on the BasicPlugin instance before registration:

WorkflowInit.cs
basicPlugin.Setting_Mailserver = "smtp.gmail.com";basicPlugin.Setting_MailserverPort = 587;basicPlugin.Setting_MailserverFrom = "workflow@company.com";basicPlugin.Setting_MailserverLogin = "workflow@company.com";basicPlugin.Setting_MailserverPassword = "app-password";basicPlugin.Setting_MailserverSsl = true;

Register the plugin with WorkflowRuntime:

runtime.WithPlugin(basicPlugin);

In your scheme, assign SendEmail to an activity Implementation. The action parameters override the global SMTP settings per-action if specified.

SendEmail parameters

The SendEmail action accepts these parameters in JSON format:

ParameterTypeRequiredDescription
TostringyesRecipient email address. Supports comma-separated addresses for multiple recipients.
SubjectstringnoEmail subject line.
BodystringnoEmail body content.
IsHTMLboolnoSet to true to render body as HTML. Default: false.
CcListJSON arraynoList of CC recipients. Example: ["manager@company.com", "hr@company.com"].
BccListJSON arraynoList of BCC recipients.
ReplyToListJSON arraynoList of Reply-To addresses.
MailServerstringnoSMTP server (overrides global setting).
MailServerPortintnoSMTP port (overrides global setting).
MailServerFromstringnoFrom address (overrides global setting).
MailServerLoginstringnoSMTP login (overrides global setting).
MailServerPassstringnoSMTP password (overrides global setting).
MailServerSslboolnoEnable SSL (overrides global setting).

Using process parameters in email content

You can inject workflow parameter values into email content using the @ParameterName syntax. The WorkflowRuntime substitutes these references before sending the email.

Example with parameter substitution:

{  "To": "@CustomerEmail",  "Subject": "Ticket #@TicketId resolved",  "Body": "<p>Dear @CustomerName,</p><p>Your ticket has been resolved.</p>",  "IsHTML": true}

The workflow engine replaces @CustomerEmail, @TicketId, and @CustomerName with actual process parameter values at runtime. To reference nested parameters use @(Parameter.SubName) syntax. For formatted values use @(Parameter:format) (for example, @(StartDate:yyyy-MM-dd)). For JSON serialization use @(Parameter:json).

Error handling

The SendEmail action throws an exception if the email fails (SMTP error, network issue, authentication failure). Unlike HTTPRequest, SendEmail does not return a failure status it either succeeds or throws.

Activities support built-in exception handlers that catch action exceptions and determine the next step. Add an ExceptionsHandlers block to the activity. For a SetState handler, NameForSet is a state name, not an activity name. First, add a fallback activity to the Activities block of the page's scheme:

email-notification.xml
<Activity Name="EmailError" State="Error" IsInitial="False"          IsFinal="True" IsForSetState="True"          IsAutoSchemeUpdate="True">  <Designer X="400" Y="400" /></Activity>

The SetState handler can select EmailError because its non-empty State equals NameForSet="Error" and IsForSetState is True. Without a matching activity, the handler throws ActivityNotFoundException while handling the original email error. Then add the handler to SendNotification:

email-notification.xml
<Activity Name="SendNotification" State="NotificationSent" IsInitial="False"          IsFinal="True" IsForSetState="True" IsAutoSchemeUpdate="True">  <ExceptionsHandlers>    <ExceptionsHandler Exceptions="*" Type="SetState"                       NameForSet="Error" Order="1" />  </ExceptionsHandlers>  <Implementation>    <ActionRef Order="1" NameRef="SendEmail">      ...    </ActionRef>  </Implementation>  <Designer X="400" Y="200" /></Activity>

Available handler types:

TypeBehavior
SetActivityMove to a specified activity
SetStateMove to a specified state
RetryRetry the action (set RetryCount)
IgnoreSuppress the exception and continue

Use Exceptions="*" to catch all exceptions, or specify a full exception type name (for example, System.Net.Mail.SmtpException). Handlers are evaluated in Order sequence.

See also

Frequently asked questions

Can I send HTML emails?

Yes. Set IsHTML to true in the SendEmail action parameters. The email body renders as HTML, supporting tags like <h2>, <p>, <table>, and <a>.

How do I send to multiple recipients?

Use comma-separated email addresses in the To parameter. For CC and BCC recipients, use the CcList and BccList parameters as JSON arrays: ["user1@company.com", "user2@company.com"].

Can I override SMTP settings per email?

Yes. The SendEmail action parameters override the global SMTP configuration. Specify MailServer, MailServerPort, MailServerFrom, MailServerLogin, MailServerPass, and MailServerSsl in the action parameters to use different SMTP servers for different emails.

How do I use workflow parameters in email content?

Use the @ParameterName syntax in the Subject and Body fields. The WorkflowRuntime substitutes these references with actual parameter values before sending the email. Use @(Parameter:format) for formatted values (for example, @(StartDate:yyyy-MM-dd)) and @(Parameter:json) for JSON serialization.

What happens if the email fails to send?

The SendEmail action throws an exception (SMTP error, network issue, etc.). Add an exception handler to the activity to catch the error and move to a fallback activity or retry.