Skip to main content
AI/MLCrestApps

orchardcore-email

Guidance for configuring and sending emails in Orchard Core using the OrchardCore.Email module, including SMTP setup, programmatic sending via ISmtpService, Liquid-based email templates, recipe-driven configuration, workflow email activities, and the Azure Communication Services email provider. Use this skill when requests mention OrchardCore.Email Module, Email Providers, Configuring SMTP Settings, Via Admin UI, Via Recipe, Via Configuration Provider, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with OrchardCore.Email, OrchardCore.Email.Azure, OrchardCore.Email.Smtp, OrchardCore.Modules, OrchardCore.Liquid, OrchardCore.Workflows, OrchardCore.Email.Events, ISmtpService, MailKitSmtpService. It also helps with email examples, Via Recipe, Via Configuration Provider, Configuring Azure Communication Services Email, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.

Stars
13
Source
CrestApps/CrestApps.AgentSkills
Updated
2026-05-29
Slug
CrestApps--CrestApps.AgentSkills--orchardcore-email
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/CrestApps/CrestApps.AgentSkills/HEAD/plugins/orchardcore/skills/orchardcore-email/SKILL.md -o .claude/skills/orchardcore-email.md

Drops the SKILL.md into .claude/skills/orchardcore-email.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

OrchardCore.Email Module

OrchardCore.Email supplies the provider-neutral email API. Enable an email provider and configure one enabled provider as the default before application code sends mail.

Provider module Tenant provider technical name Configuration-backed default
OrchardCore.Email.Smtp SMTP DefaultSMTP
OrchardCore.Email.Azure Azure DefaultAzure

The email settings page is Settings → Communication → Email. It lists enabled providers and selects EmailSettings.DefaultProviderName. Enabling the last valid tenant provider selects it automatically; otherwise explicitly choose the default. The test page is Tools → Testing → Email Test and lets an administrator select an enabled provider for the test message.

Enable and Configure SMTP

{
  "steps": [
    {
      "name": "Feature",
      "enable": [
        "OrchardCore.Email",
        "OrchardCore.Email.Smtp"
      ]
    },
    {
      "name": "Settings",
      "SmtpSettings": {
        "IsEnabled": true,
        "DefaultSender": "noreply@example.com",
        "Host": "smtp.example.com",
        "Port": 587,
        "AutoSelectEncryption": false,
        "EncryptionMethod": "STARTTLS",
        "RequireCredentials": true,
        "UserName": "smtp-user",
        "Password": "use-a-secret-provider",
        "DeliveryMethod": "Network"
      },
      "EmailSettings": {
        "DefaultProviderName": "SMTP"
      }
    }
  ]
}

OrchardCore_Email_Smtp configures the DefaultSMTP provider. Use the settings UI for a tenant-specific SMTP provider. Do not commit credentials.

Enable and Configure Azure Communication Services

{
  "steps": [
    {
      "name": "Feature",
      "enable": [
        "OrchardCore.Email",
        "OrchardCore.Email.Azure"
      ]
    },
    {
      "name": "Settings",
      "AzureEmailSettings": {
        "IsEnabled": true,
        "DefaultSender": "DoNotReply@your-domain.azurecomm.net",
        "ConnectionString": "supply-from-a-secure-source"
      },
      "EmailSettings": {
        "DefaultProviderName": "Azure"
      }
    }
  ]
}

OrchardCore_Email_AzureCommunicationServices configures DefaultAzure. Use a verified ACS sender and secure configuration for connection strings.

Sending Email Programmatically

Inject IEmailService; ISmtpService, SmtpResult, and MailKitSmtpService are not the v3 API. Use HtmlBody and/or TextBody; Body and IsHtmlBody are obsolete.

using OrchardCore.Email;
using OrchardCore.Infrastructure;

namespace MyModule;

public sealed class OrderConfirmationService
{
    private readonly IEmailService _emailService;

    public OrderConfirmationService(IEmailService emailService)
    {
        _emailService = emailService;
    }

    public Task<Result> SendAsync(
        string recipientEmail,
        string orderId,
        CancellationToken cancellationToken = default)
    {
        var message = new MailMessage
        {
            To = recipientEmail,
            Subject = $"Order confirmation {orderId}",
            HtmlBody = $"<p>Your order <strong>{orderId}</strong> has been confirmed.</p>",
            TextBody = $"Your order {orderId} has been confirmed.",
        };

        return _emailService.SendAsync(message, cancellationToken: cancellationToken);
    }
}

Pass a provider technical name only when deliberately overriding the configured default:

var result = await _emailService.SendAsync(
    message,
    providerName: "SMTP",
    cancellationToken: cancellationToken);

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

MailMessage supports From, To, Cc, Bcc, ReplyTo, Sender, Subject, HtmlBody, TextBody, and Attachments.

IEmailService.SendAsync() and IEmailProvider.SendAsync() accept a CancellationToken. Pass the request token through custom providers and event handlers so shutdown and request cancellation can stop delivery.

Liquid Templates

Render a Liquid template before assigning it to HtmlBody:

var html = await _liquidTemplateManager.RenderStringAsync(
    "<p>Welcome, {{ UserName }}!</p>",
    System.Text.Encodings.Web.HtmlEncoder.Default,
    new { UserName = userName });

await _emailService.SendAsync(new MailMessage
{
    To = recipientEmail,
    Subject = "Welcome",
    HtmlBody = html,
    TextBody = $"Welcome, {userName}!",
});

Email Events

Implement IEmailServiceEvents, or derive from EmailServiceEventsBase, to observe validation and delivery. Event methods receive a cancellation token; ValidatedAsync and ValidatingAsync also receive MailMessageValidationContext.

using OrchardCore.Email;
using OrchardCore.Email.Services;

namespace MyModule;

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

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

    public override Task SendingAsync(MailMessage message, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("Sending email with subject {Subject}.", message.Subject);
        return Task.CompletedTask;
    }

    public override Task FailedAsync(MailMessage message, CancellationToken cancellationToken = default)
    {
        _logger.LogWarning("Email delivery failed for subject {Subject}.", message.Subject);
        return Task.CompletedTask;
    }
}

Register the handler as IEmailServiceEvents.

services.AddScoped<IEmailServiceEvents, EmailAuditHandler>();

Workflows

With OrchardCore.Email and OrchardCore.Workflows enabled, use the Send Email workflow activity. Its body is rendered as HTML, so provide HTML there and keep provider configuration outside the workflow definition.