Get the FREE Ultimate OpenClaw Setup Guide →

orchardcore-email

Scanned
npx machina-cli add skill CrestApps/CrestApps.AgentSkills/orchardcore-email --openclaw
Files (1)
SKILL.md
12.3 KB

OrchardCore.Email Module

The OrchardCore.Email module provides email functionality for Orchard Core applications. It supports multiple email providers, Liquid-based templates for dynamic content, workflow integration, and both admin UI and recipe-based configuration.

Email Providers

Orchard Core ships with built-in support for the following email providers:

  • SMTP (MailKit) — Uses MailKitSmtpService to deliver messages through any standard SMTP server.
  • Azure Communication Services — Sends email through the Azure Communication Services Email API using the OrchardCore.Email.Azure module.

Enable the relevant feature depending on your provider:

  • OrchardCore.Email — Core email abstractions and admin settings.
  • OrchardCore.Email.Smtp — SMTP delivery via MailKit.
  • OrchardCore.Email.Azure — Azure Communication Services delivery.

Configuring SMTP Settings

Via Admin UI

Navigate to Configuration → Settings → Email in the admin dashboard. The SMTP settings section allows you to specify:

SettingDescription
Default SenderThe default "From" address for outgoing messages.
HostThe SMTP server hostname (e.g., smtp.example.com).
PortThe SMTP port (typically 25, 465, or 587).
Encryption MethodNone, SSLTLS, or STARTTLS.
UsernameCredentials for SMTP authentication.
PasswordPassword for SMTP authentication.
Proxy Host / PortOptional SOCKS proxy settings for environments that route through a proxy.

Via Recipe

Configure SMTP settings declaratively using a Settings recipe step targeting SmtpSettings:

{
  "steps": [
    {
      "name": "Settings",
      "SmtpSettings": {
        "DefaultSender": "noreply@example.com",
        "Host": "smtp.example.com",
        "Port": 587,
        "EncryptionMethod": "STARTTLS",
        "AutoSelectEncryption": false,
        "RequireCredentials": true,
        "UserName": "smtp-user",
        "Password": "smtp-password",
        "ProxyHost": null,
        "ProxyPort": 0
      }
    }
  ]
}

Via Configuration Provider

SMTP settings can also be supplied through appsettings.json or environment variables using the OrchardCore_Email_Smtp configuration section:

{
  "OrchardCore_Email_Smtp": {
    "DefaultSender": "noreply@example.com",
    "Host": "smtp.example.com",
    "Port": 587,
    "EncryptionMethod": "STARTTLS",
    "RequireCredentials": true,
    "UserName": "smtp-user",
    "Password": "smtp-password"
  }
}

Configuring Azure Communication Services Email

Enable the OrchardCore.Email.Azure feature, then configure settings in the admin under Configuration → Settings → Email → Azure Communication Services, or via configuration:

{
  "OrchardCore_Email_Azure": {
    "DefaultSender": "DoNotReply@your-azure-domain.azurecomm.net",
    "ConnectionString": "endpoint=https://your-resource.communication.azure.com/;accesskey=YOUR_ACCESS_KEY"
  }
}

Or supply the connection string as a recipe step:

{
  "steps": [
    {
      "name": "Settings",
      "AzureEmailSettings": {
        "DefaultSender": "DoNotReply@your-azure-domain.azurecomm.net",
        "ConnectionString": "endpoint=https://your-resource.communication.azure.com/;accesskey=YOUR_ACCESS_KEY"
      }
    }
  ]
}

Sending Emails Programmatically

Using ISmtpService

Inject ISmtpService to send emails from custom code. Build a MailMessage and call SendAsync:

using Microsoft.Extensions.Localization;
using OrchardCore.Email;

public sealed class OrderConfirmationService
{
    private readonly ISmtpService _smtpService;
    private readonly IStringLocalizer S;

    public OrderConfirmationService(
        ISmtpService smtpService,
        IStringLocalizer<OrderConfirmationService> stringLocalizer)
    {
        _smtpService = smtpService;
        S = stringLocalizer;
    }

    public async Task<SmtpResult> SendOrderConfirmationAsync(
        string recipientEmail,
        string orderId)
    {
        var message = new MailMessage
        {
            To = recipientEmail,
            Subject = S["Order Confirmation - {0}", orderId].Value,
            Body = $"<p>Your order <strong>{orderId}</strong> has been confirmed.</p>",
            IsHtmlBody = true
        };

        return await _smtpService.SendAsync(message);
    }
}

Register the service in your module's Startup:

using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Modules;

public sealed class Startup : StartupBase
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<OrderConfirmationService>();
    }
}

Checking the Result

SmtpResult indicates whether the send operation succeeded:

var result = await _smtpService.SendAsync(message);

if (!result.Succeeded)
{
    foreach (var error in result.Errors)
    {
        logger.LogError("Email send failed: {Error}", error.Value);
    }
}

MailMessage Properties

The MailMessage class exposes these key properties:

PropertyTypeDescription
FromstringSender address. Falls back to DefaultSender if empty.
TostringComma-separated list of recipient addresses.
CcstringComma-separated list of CC addresses.
BccstringComma-separated list of BCC addresses.
ReplyTostringReply-to address.
SubjectstringMessage subject line.
BodystringMessage body (plain text or HTML).
IsHtmlBodyboolWhen true, the body is treated as HTML.
AttachmentsList<MailMessageAttachment>File attachments.

Sending with Attachments

public sealed class ReportEmailService
{
    private readonly ISmtpService _smtpService;

    public ReportEmailService(ISmtpService smtpService)
    {
        _smtpService = smtpService;
    }

    public async Task<SmtpResult> SendReportAsync(
        string recipientEmail,
        string reportName,
        Stream reportStream)
    {
        var message = new MailMessage
        {
            To = recipientEmail,
            Subject = $"Report: {reportName}",
            Body = "<p>Please find the attached report.</p>",
            IsHtmlBody = true
        };

        message.Attachments.Add(new MailMessageAttachment
        {
            Filename = $"{reportName}.pdf",
            Stream = reportStream
        });

        return await _smtpService.SendAsync(message);
    }
}

Liquid Email Templates

Orchard Core's Liquid integration allows you to build dynamic email bodies. Use ILiquidTemplateManager to render templates before sending:

using OrchardCore.Liquid;
using OrchardCore.Email;

public sealed class TemplatedEmailService
{
    private readonly ISmtpService _smtpService;
    private readonly ILiquidTemplateManager _liquidTemplateManager;

    public TemplatedEmailService(
        ISmtpService smtpService,
        ILiquidTemplateManager liquidTemplateManager)
    {
        _smtpService = smtpService;
        _liquidTemplateManager = liquidTemplateManager;
    }

    public async Task<SmtpResult> SendWelcomeEmailAsync(
        string recipientEmail,
        string userName)
    {
        var template = @"
<h1>Welcome, {{ UserName }}!</h1>
<p>Thank you for registering on our site.</p>
<p>Your account is now active and ready to use.</p>
";

        var model = new { UserName = userName };
        var body = await _liquidTemplateManager.RenderStringAsync(
            template,
            System.Text.Encodings.Web.HtmlEncoder.Default,
            model);

        var message = new MailMessage
        {
            To = recipientEmail,
            Subject = $"Welcome, {userName}!",
            Body = body,
            IsHtmlBody = true
        };

        return await _smtpService.SendAsync(message);
    }
}

Liquid Syntax in Email Templates

Common Liquid constructs for email templates:

  • Variable output: {{ Model.PropertyName }}
  • Conditionals: {% if Model.IsVip %} ... {% endif %}
  • Loops: {% for item in Model.Items %} ... {% endfor %}
  • Filters: {{ Model.Date | date: "%B %d, %Y" }}
  • Content items: {% contentitem id: Model.ContentItemId, assign_model: "item" %}

Email Workflow Activities

When the OrchardCore.Email feature is enabled alongside OrchardCore.Workflows, a Send Email activity becomes available in the workflow editor.

Send Email Activity Properties

PropertyDescription
SenderThe "From" address. Defaults to the configured default sender.
RecipientsComma-separated recipient addresses. Supports Liquid expressions.
CCComma-separated CC addresses. Supports Liquid expressions.
BCCComma-separated BCC addresses. Supports Liquid expressions.
Reply-ToReply-to address. Supports Liquid expressions.
SubjectEmail subject. Supports Liquid expressions.
BodyEmail body. Supports full Liquid template syntax with HTML.
Is HTML BodyWhether the body should be treated as HTML.

In workflow Liquid expressions, access the current workflow context with {{ Workflow }} and the triggering content item with {{ ContentItem }}.

Example Workflow: Notify Admin on Content Publication

Create a workflow that sends an email when a content item is published:

  1. Add a Content Published Event as the starting activity.
  2. Connect it to a Send Email activity with:
    • Recipients: admin@example.com
    • Subject: Content Published: {{ ContentItem.DisplayText }}
    • Body:
      <p>The content item <strong>{{ ContentItem.DisplayText }}</strong> of type
      <em>{{ ContentItem.ContentType }}</em> was published.</p>
      <p>Published by: {{ Workflow.Input.Owner }}</p>
      

Email Notification Events

Orchard Core raises email-related events that modules can hook into. Implement IEmailNotificationEvents or listen for specific email notification events to customize behavior before or after emails are sent.

Custom Email Event Handler

using OrchardCore.Email;
using OrchardCore.Email.Events;

public sealed class EmailAuditHandler : IEmailNotificationEvents
{
    private readonly ILogger<EmailAuditHandler> _logger;

    public EmailAuditHandler(ILogger<EmailAuditHandler> logger)
    {
        _logger = logger;
    }

    public Task SendingAsync(MailMessage message)
    {
        _logger.LogInformation(
            "Sending email to {Recipients} with subject '{Subject}'.",
            message.To,
            message.Subject);

        return Task.CompletedTask;
    }

    public Task SentAsync(MailMessage message)
    {
        _logger.LogInformation(
            "Email sent to {Recipients} successfully.",
            message.To);

        return Task.CompletedTask;
    }

    public Task FailedAsync(MailMessage message)
    {
        _logger.LogWarning(
            "Failed to send email to {Recipients}.",
            message.To);

        return Task.CompletedTask;
    }
}

Register the handler:

using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Email.Events;
using OrchardCore.Modules;

public sealed class Startup : StartupBase
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IEmailNotificationEvents, EmailAuditHandler>();
    }
}

Testing Email Configuration

Use the admin Email Test page at Configuration → Settings → Email → Test to send a test message. This validates that SMTP or Azure Communication Services settings are correctly configured.

Troubleshooting

SymptomPossible Cause
Emails not sentSMTP feature not enabled or credentials are incorrect.
Authentication failuresWrong username/password or encryption method mismatch.
Connection timeoutsFirewall blocking SMTP port, or incorrect host/port.
Azure emails rejectedSender domain not verified in Azure Communication Services.
Liquid variables emptyModel properties not passed to the template correctly.

Source

git clone https://github.com/CrestApps/CrestApps.AgentSkills/blob/main/src/CrestApps.AgentSkills/orchardcore/orchardcore-email/SKILL.mdView on GitHub

Overview

OrchardCore.Email provides email capabilities for Orchard Core apps, supporting SMTP and Azure email delivery, Liquid-based templates, and both admin UI and recipe-driven configuration. It enables programmatic sending via ISmtpService and workflow integration. This skill guides setup, template usage, and runtime sending.

How This Skill Works

The module supports multiple providers (SMTP via MailKit and Azure Communication Services) enabled by feature selection. Email content can be rendered with Liquid templates, and providers can be configured through the Admin UI, via Settings recipes, or through appsettings.json. At runtime you can send emails programmatically by injecting ISmtpService and calling SendAsync with a MailMessage.

When to Use It

  • You need transactional emails (order confirmations, password resets) from an Orchard Core site.
  • You want SMTP delivery via MailKit using your existing SMTP server.
  • You want to provision email settings automatically in deployments using a Settings recipe.
  • You plan to use Azure Communication Services for scalable email delivery.
  • You need to send emails from custom code by injecting ISmtpService.

Quick Start

  1. Step 1: Enable the relevant email feature (OrchardCore.Email) and choose the provider (SMTP or Azure) in Features.
  2. Step 2: Configure SMTP or Azure settings in Admin UI (Configuration → Settings → Email) or via a Settings recipe / appsettings.json.
  3. Step 3: Inject ISmtpService in your code and call SendAsync with a prepared MailMessage (e.g., subject, body, recipients).

Best Practices

  • Use TLS (STARTTLS/SSL) where supported to encrypt email transport.
  • Set a verified DefaultSender and validate the sender email domain.
  • Store credentials securely (secret stores or environment variables) and avoid hard-coding.
  • Test configurations with a staging SMTP server before production deployments.
  • Choose the Azure provider for cloud-scale reliability if you are already in Azure.

Example Use Cases

  • Send order confirmation emails via SMTP after a customer completes a checkout.
  • Dispatch welcome emails using a Liquid-templated template upon user registration.
  • Mail password reset links through the SMTP or Azure provider depending on your setup.
  • Use a recipe to provision SMTP settings during initial deployment of a site.
  • Trigger system alerts to admins via email when specific workflow events occur.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers