Skip to main content

Email Notification Service

tip

The Email Notification Service was added to the platform in v5.20.

The Email Notification Service sends automated email alerts when Cinchy data syncs, event listeners, or automations fail, succeed, or run longer than expected. When any of these artifacts hit a notable state, the affected team receives a branded email with the artifact name, execution details, and error summary so they can investigate immediately instead of discovering the failure hours later.

The service covers three artifact types:

  • Batch syncs — scheduled data imports/exports.
  • Event listeners — real-time listener-triggered syncs.
  • Automations — multi-step Cinchy automation runs.

How it works

Batch Syncs and Event Syncs notify the service by webhook; automations are detected by background monitors. Every notification is persisted to a durable outbox before sending, so no email is lost even if the service restarts mid-send.

Access and permissions

By default, the Email Notification Service tables and the global kill switch are managed by the Cinchy Administrators User Group. The service itself runs as a dedicated notification@cinchy.com user with its own integrated client, so end users do not need direct access to send emails — they only need entitlements to manage which notifications are configured.

Administrators can delegate management of notification rules and branding to non-admin users or groups by granting per-table entitlements. For example, the data engineering team can own Notification Config rows for their syncs without needing platform admin rights.

Table / ObjectAccess required forRecommended entitlement
[Cinchy].[Notification Config]Creating per-artifact notification rules (recipients, trigger types, cooldowns, priority)View + Edit
[Cinchy].[Notification Branding]Customizing logo, color, and company name on outgoing emailsView + Edit
[Cinchy].[Notification Outbox]Auditing sent/failed emails and troubleshooting deliveryView
[Cinchy].[System Properties] row Notifications EnabledToggling the global kill switchEdit (Administrators only)

To grant access, open the table's Design Controls > Entitlements view in Cinchy and add the user or group with the appropriate permission level. The global kill switch should remain under Administrators only — per-row Send Email on the Notification Config table is the right place to delegate per-artifact control.

Prerequisites

  • Cinchy v5.20+ is required.
  • Kubernetes deployment is recommended. The service runs as a standalone container alongside the rest of the Cinchy platform.
  • A reachable email provider (SMTP server, AWS SES, Azure Communication Services, or a Microsoft 365 tenant for Microsoft Graph).

Enabling the service

The service is disabled by default. How you enable it depends on your deployment platform:

  • Kubernetes: Set "notification_enabled": "true" in terraform_config.notification of your deployment.json.
  • IIS: Deploy the Notification service as an IIS sub-application under your Cinchy site. The service is opt-in by deployment — no additional flag is required in appsettings.json.

In addition to the deployment flag, a System Property acts as the platform-level kill switch. In [Cinchy].[System Properties]:

System PropertyPurpose
Notifications EnabledGlobal kill switch. Set to true to enable. When false (or not set), the service sends nothing regardless of per-artifact configuration.
Two levels of enablement

There are two separate switches:

  • Notifications Enabled (System Property) — the global kill switch. When false (or not set), the service sends nothing, regardless of any per-artifact configuration. Set to true to allow emails to send.
  • Send Email (column on each [Cinchy].[Notification Config] row) — the per-artifact toggle, default false. A config row only generates emails when its Send Email is on and the global switch is true.

Trigger types

Each row in the [Cinchy].[Notification Config] table gates which event types generate emails. There are three primary trigger types:

Trigger TypeDefaultDescriptionWired for
FailureEnabledSync, listener, or automation ended in a failure statebatch syncs, listeners, automations
SuccessDisabledSync or automation completed successfullybatch syncs, automations
LongRunningDisabledSync or automation has been in Running state longer than the configured thresholdbatch syncs, automations

The trigger types that apply to each artifact type are summarized below.

Config row typeNotify On FailureNotify On SuccessNotify On Long Running
Data Sync ConfigYesYesYes
Listener ConfigYesNoNo
AutomationYesYesYes
note

For listener config rows, only Notify On Failure is wired end-to-end. Notify On Success has no upstream emitter today, and Notify On Long Running is intentionally out of scope (event-driven listeners are not batch).

A [Cinchy].[Notification Config] row (with recipients and Send Email = true) is required for an artifact to generate any email — there is no global default recipient list. On a row, Notify On Failure defaults to on, while Notify On Success and Notify On Long Running are off, so customers do not receive success or long-running noise without opting in.

Key capabilities

Flexible recipient routing

  • Per-artifact overrides — route specific notifications to specific teams via the [Cinchy].[Notification Config] table.
  • Group-based recipients — link Cinchy Groups as To, CC, or BCC recipients; member emails are resolved at send time, so changes to group membership take effect automatically.
  • BCC Recipient Groups — a dedicated BCC group column for compliance and audit trails.
  • CC and BCC support — add managers, on-call groups, or compliance mailboxes.
  • Reply-To per artifact — route replies to the right team (for example, support@ for one sync, finance@ for another).
  • From address override — use a different sender identity per config row.
  • Priority levels — High, Medium, or Low per config row, mapped to email importance headers.
  • Kill switch — disable all notifications globally via System Properties without redeploying.
  • Deduplication across To/CC/BCC — recipients appearing in To are removed from CC; recipients in To or CC are removed from BCC.
  • Resolved recipients are written back — after resolution, the final To/CC/BCC lists are saved to the Outbox row for audit.

Server-side cooldown and deduplication

  • A configurable Cooldown Minutes value per (artifact, trigger type) combination prevents notification storms.
  • The default cooldown is 5 minutes, configurable via DefaultCooldownMinutes in appsettings.json.
  • Each config row can override the default via the Cooldown Minutes column.
  • Cooldown state is server-side (persisted in the Outbox), so it survives pod restarts.
  • The cooldown key includes the trigger type, so a LongRunning notification does not suppress a subsequent Success notification for the same artifact. Both emails fire if both checkboxes are checked.

Long-running monitors

Two parallel background services detect artifacts stuck in the Running state:

  • Batch sync monitor — polls [Execution Log] for batch syncs with State = Running beyond their configured threshold. Scoped to Notification Config rows where Data Sync Config is filled.
  • Automation monitor — polls [Automation Execution History] for automations with Status = Running past threshold. Scoped to Notification Config rows where Automation is filled.

Both share the same template and respect the same per-(artifact, trigger-type) cooldown. Neither applies to listener config rows — long-running is a batch concept, listeners are event-driven.

Automation monitor (Failure + Success)

A background service polls [Cinchy].[Automation Execution History] and enqueues notifications for terminal-state transitions:

  • Rows transitioning to Status = 'Failed' enqueue a Failure notification.
  • Rows transitioning to Status = 'Succeeded' enqueue a Success notification.

Both queries filter by [Modified] rather than [Created], so long-running automations that transition to terminal state long after the row was inserted are still caught. Step-level execution history from [Automation Steps Execution History] is included in the email template.

Branded email templates

  • Professional HTML emails rendered through Liquid (Fluid) templates.
  • Cinchy brand colors built into the default template (Jetsam #00B1FF header, Raspberry #E7015B failure badges, Sunset #FFAB02 warning badges, Ink #1C1A1D body and footer).
  • Default embedded Cinchy white logo in the header, overridable via the Branding table.
  • Customizable company name, logo, and background color via the [Cinchy].[Notification Branding] table.
  • Plain-text fallback included with all emails.
  • Built-in templates include sync-failure, sync-success, sync-partial-failure, long-running-warning, listener-down, service-down, automation-failure, automation-success, and digest.
  • Subject prefix: [Cinchy Email Notification Service].

Multiple email providers

ProviderProvider.TypeUse case
SMTPSmtpOn-prem deployments, Office 365, or any SMTP server
AWS SESAwsSesCloud deployments on AWS (uses IAM roles, no static credentials needed)
Azure Communication ServicesAzureCommunicationCloud deployments on Azure (supports managed identity)
Microsoft GraphMicrosoftGraphMicrosoft 365 environments where SMTP is disabled. Sends via the Graph API using a Microsoft Entra (Azure AD) app registration.

Only one provider is active per deployment, configured via appsettings.json. Set Provider.Type to one of "Smtp", "AwsSes", "AzureCommunication", or "MicrosoftGraph" — the service fails fast at startup if Type is missing.

Reliable delivery (outbox pattern)

  • Emails are persisted to a database outbox before sending.
  • A background processor picks up pending emails in batches.
  • Automatic retries with configurable exponential backoff (up to 5 retries by default).
  • Stale claim recovery — if a pod crashes mid-send, another cycle reclaims the email.
  • No email is lost once it reaches the outbox.

Safety features

  • Allowed recipient domains — restrict who can receive emails in non-production environments to prevent test leaks to real customers.
  • Rate limiting — client-side rate limit to stay within provider quotas (for example, AWS SES sending limits).
  • Startup validation — SMTP settings are validated at startup; the service fails fast if misconfigured.

Invalid config detection

If a Notification Config row has more than one of Data Sync Config, Listener Config, or Automation filled, the service treats it as invalid and suppresses notifications with a descriptive error written to the Outbox Last Error column. Unique constraints on the table enforce one row per sync, listener, or automation.

Database tables

TablePurpose
[Cinchy].[Notification Outbox]Pending, sent, and failed email queue.
[Cinchy].[Notification Config]Per-artifact recipient routing, trigger filtering, and overrides.
[Cinchy].[Notification Branding]Logo (via Files table or Logo URL), background color (via System Colours), and company name.

All tables are provisioned by the v5.20 model upgrade. New columns are auto-added on upgrade.

Notification Config columns

Show all Notification Config columns
ColumnTypeDescription
Data Sync ConfigLink → Data Sync ConfigurationsBatch sync to monitor.
Listener ConfigLink → Listener ConfigEvent listener to monitor.
AutomationLink → AutomationsAutomation to monitor.
Send EmailYes/No (default: false)Master toggle for this config row. Must be on (and the global Notifications Enabled switch true) for the row to send.
Notify On FailureYes/No (default: true)Send on artifact failure.
Notify On SuccessYes/No (default: false)Send on artifact success.
Notify On Long RunningYes/No (default: false)Send warning if sync or automation exceeds threshold.
Long Running Threshold MinutesNumberMinutes before a long-running alert triggers.
RecipientsTextSemicolon-delimited email addresses.
CC RecipientsTextSemicolon-delimited CC addresses.
BCC RecipientsTextSemicolon-delimited BCC addresses.
Recipient GroupsLink → Groups (multi)Cinchy groups resolved to member emails.
CC Recipient GroupsLink → Groups (multi)Cinchy groups for CC.
BCC Recipient GroupsLink → Groups (multi)Cinchy groups for BCC (compliance/audit).
Reply ToTextReply-to address override.
From Address OverrideTextSender address override.
From Display Name OverrideTextSender display name override.
PriorityChoiceHigh / Medium / Low.
Max Retries OverrideNumberOverride default retry count.
Cooldown MinutesNumberMinimum minutes between notifications per (artifact, trigger type).
Max Emails Per DayNumberOptional daily cap per artifact.
Subject TemplateTextPer-row subject override (Liquid). Available variables include {{sync_config_name}}, {{listener_config_name}}, {{automation_name}}, {{trigger_type}}, {{execution_id}}, {{timestamp}}, {{environment}}; LongRunning also exposes {{duration}} and {{threshold_minutes}}. Leave empty for the default subject.
Client BrandingLink → Notification BrandingCustom email styling.
caution

Exactly one of Data Sync Config, Listener Config, or Automation must be filled per row. Unique constraints on the table enforce one row per artifact.

Quick start

The simplest setup sends an email to your team whenever a specific sync fails.

Step 1. In [Cinchy].[System Properties], set the global kill switch:

NameValue
Notifications Enabledtrue

Step 2. In appsettings.json, configure your email provider (see Provider setup below).

Step 3. In [Cinchy].[Notification Config], add a row for the sync you want to monitor:

Data Sync ConfigRecipientsSend Email
Daily Importyour-team@company.comtrue

That is it. A Daily Import failure now sends an email to your-team@company.com using the default template. Add a row per artifact you want to monitor. Success and long-running notifications are suppressed by default unless you enable them on the row.

Use cases

Route different syncs to different teams

Scenario: Finance sync failures should go to the finance team, and HR sync failures should go to the HR team.

Add one [Cinchy].[Notification Config] row per sync, each with its own recipients:

Data Sync ConfigListener ConfigRecipientsSend Email
Finance Daily Importfinance-ops@company.comtrue
HR Payroll Synchr-team@company.com;hr-manager@company.comtrue

Finance Daily Import failures go to finance-ops, and HR Payroll Sync failures go to the HR team and HR manager. A sync with no Config row produces no email — add a row for each artifact you want to monitor.

Monitor event listeners

Scenario: You want to know when your real-time event listeners fail.

Data Sync ConfigListener ConfigAutomationRecipientsSend Email
Customer Orders Listenerintegration-team@company.comtrue
Inventory Updates Listenerwarehouse-ops@company.comtrue
note

Only Notify On Failure is wired end-to-end for listener rows today. Notify On Success and Notify On Long Running may appear in the UI but will not produce emails for listener rows.

Monitor automations

Scenario: You want emails when a Cinchy automation fails, succeeds, or runs longer than expected.

AutomationNotify On FailureNotify On SuccessNotify On Long RunningLong Running Threshold MinutesRecipientsSend Email
Daily ETLtruefalsetrue30ops-team@company.comtrue
Monthly Reconciliationtruetruetrue60finance@company.comtrue

All three checkboxes are independent. A LongRunning notification followed by a Success notification for the same automation execution will both fire because they are separate trigger types with independent cooldowns.

Use Cinchy Groups instead of email addresses

Scenario: You do not want to maintain email addresses in the Config table; you already have Cinchy Groups with the right members.

Data Sync ConfigRecipient GroupsCC Recipient GroupsBCC Recipient GroupsSend Email
Finance Daily ImportFinance OpsFinance ManagersCompliance Auditorstrue
HR Payroll SyncHR Teamtrue

The service resolves group membership at send time via CQL link traversal (Config → Group → Users → Email Address). When someone joins or leaves the group, notifications automatically update — no Config changes needed.

note

You can combine Recipients (raw emails) and Recipient Groups (Cinchy groups) on the same row. Both lists are merged and deduplicated. The same applies for CC and BCC columns.

Suppress a noisy sync

Scenario: A sync is known to fail intermittently and you do not want notifications while the team investigates.

Data Sync ConfigRecipientsSend Email
Legacy Data Migrationfalse

Failures from Legacy Data Migration are suppressed. All other syncs continue to notify normally. When the issue is resolved, flip Send Email back to true.

Trigger type filtering

Scenario: You want failure notifications for several syncs, plus success confirmations for your critical payment sync and long-running warnings for your large nightly batch. On each row, Notify On Failure defaults to on, while Notify On Success and Notify On Long Running are off until you enable them.

Data Sync ConfigNotify On FailureNotify On SuccessNotify On Long RunningLong Running Threshold MinutesSend Email
Payment Processing Synctruetruefalsetrue
Nightly Warehouse Loadtruefalsetrue60true
Daily Report Synctruefalsefalsetrue
  • A sync with no Config row → no email; a Config row with recipients and Send Email = true is required to send anything.
  • On a row where only Notify On Failure is on, a success or long-running event produces no email.
note

Trigger types are independent. A LongRunning notification does not suppress a subsequent Success notification for the same artifact. The cooldown gate is keyed by (artifact, trigger type), so both emails fire if both checkboxes are checked.

Control notification frequency with cooldown

Scenario: A sync fails in a tight retry loop and you do not want 50 emails in 10 minutes.

Option A — Global default (appsettings.json):

{
"EmailNotification": {
"DefaultCooldownMinutes": 5
}
}

A five-minute cooldown applies between duplicate notifications (same artifact, same trigger type). The cooldown is server-side and persisted in the Outbox, so it survives pod restarts.

Option B — Per-sync override (Config table):

Data Sync ConfigCooldown MinutesSend Email
Flaky External API Sync15true
Critical Payment Sync1true

Compliance BCC on all emails

Scenario: Your compliance team requires a copy of every notification email.

Option A — Global BCC (appsettings.json):

{
"EmailNotification": {
"DefaultBccAddress": "compliance-audit@company.com"
}
}

Every email sent by the service will BCC this address regardless of which artifact triggered it.

Option B — BCC on specific syncs (Config table):

Data Sync ConfigBCC RecipientsBCC Recipient GroupsSend Email
Financial Reporting Synccompliance-audit@company.comCompliance Auditorstrue
note

The per-row BCC and the global DefaultBccAddress are merged, not overridden. Recipients are deduplicated across To, CC, and BCC.

Different reply-to per team

Scenario: Recipients should reply to the right support inbox, not the no-reply sender.

appsettings.json:

{
"EmailNotification": {
"DefaultFromAddress": "noreply@company.com",
"DefaultReplyToAddress": "platform-support@company.com"
}
}

Per-sync override:

Data Sync ConfigReply ToSend Email
Finance Daily Importfinance-support@company.comtrue
HR Payroll Synchr-helpdesk@company.comtrue

Different sender identity per artifact

Scenario: Finance emails should come from finance-alerts@company.com and HR emails from hr-alerts@company.com.

Data Sync ConfigFrom Address OverrideFrom Display Name OverrideSend Email
Finance Daily Importfinance-alerts@company.comFinance Platformtrue
HR Payroll Synchr-alerts@company.comHR Platformtrue
caution

The override address must be authorized by your email provider (verified in SES, permitted by your SMTP server, and so on).

Mark critical syncs as high priority

Scenario: Some failures are urgent and should stand out in recipients' inboxes.

Data Sync ConfigPrioritySend Email
Payment Processing SyncHightrue
Daily Report SyncLowtrue

High-priority emails carry the Importance: High header; most email clients show them with a flag or exclamation mark.

Non-production safety

Scenario: You are testing in staging and want to make sure test emails never reach real customers.

{
"EmailNotification": {
"Safety": {
"AllowedRecipientDomains": ["company.com", "testing.internal"],
"RateLimitPerMinute": 30
}
}
}

Recipients outside the allow-list are filtered out. If all recipients are filtered out, the email is marked as failed with No recipients resolved. Remove the restriction (or set the list to []) for production.

Custom email branding

Scenario: You host Cinchy for multiple clients and want their notification emails branded differently.

  1. Upload logo images to the [Cinchy].[Files] table.

  2. Add color entries to [Cinchy].[System Colours] (if custom colors are needed):

    NameHex Value
    Acme Orange#FF6600
    BigBank Navy#003366
  3. Add rows to [Cinchy].[Notification Branding]:

    Branding NameCompany NameBackground ColorLogoLogo URL
    Acme CorpAcme CorporationAcme Orangeacme-logo.png
    BigBankBigBank FinancialBigBank Navyhttps://cdn.bigbank.example.com/logo.png

    Background Color is a link to System Colours (not a plain hex value); Logo is a link to the Files table (not a URL or binary upload). Logo URL is an optional public URL — when set, it takes precedence over the Logo file link.

  4. Link branding in [Cinchy].[Notification Config]:

    Data Sync ConfigClient BrandingSend Email
    Acme Daily SyncAcme Corptrue
    BigBank Nightly ImportBigBanktrue

To apply a global default branding, set DefaultBrandingName in appsettings.json. If left empty, the default Cinchy branding is used.

Provider setup

Only one provider is active per deployment. Pick the scenario that matches your environment below, configure only that provider's block in appsettings.json, and delete the other blocks (or leave them entirely absent). Mixing fields from multiple providers in one config file is a common source of confusion — only the active provider's block is read.

How the provider is selected

Provider.Type is required. Set it to exactly one of "Smtp", "AwsSes", "AzureCommunication", or "MicrosoftGraph". The service fails fast at startup with a clear error if it is missing or empty.

Customer deployments configure Provider.Type directly: in appsettings.json for IIS, or via the notification_provider_type field of your deployment.json (see the v5.20 Kubernetes upgrade guide) for Kubernetes.

Common configuration gotchas
  • Do not blank out int fields like Port with "". The .NET configuration binder cannot convert an empty string to an integer, and the service will fail to start before logging initializes. Either delete the key entirely or set a valid number.
  • Leftover blocks for other providers are ignored. Only the block matching Provider.Type is bound and validated; others can stay in the file or be deleted — your choice.
  • AWS SES API vs. AWS SES SMTP relay are different code paths. Pick "AwsSes" for the API path (uses the AWS SDK with an IAM role or access keys). Pick "Smtp" and point Smtp.Host at email-smtp.<region>.amazonaws.com for the SMTP relay — SES SMTP credentials are generated separately in the SES console and are different from IAM keys.
Per-provider sender overrides

Each provider block also accepts its own FromAddress and FromDisplayName. When set, those values override the top-level DefaultFromAddress / DefaultFromDisplayName for that provider only — useful when, for example, AWS SES requires a verified identity that differs from the global default sender.

Use for on-prem SMTP relays, Office 365 SMTP, internal mail gateways, or the AWS SES SMTP relay endpoint.

Required fields

FieldNotes
Provider.TypeSet to "Smtp"
Smtp.HostSMTP server hostname
Smtp.PortInteger (1–65535). Common: 25, 465, 587, 2525
Smtp.UsernameRequired if RequireAuth = true
Smtp.PasswordRequired if RequireAuth = true
DefaultFromAddress or Smtp.FromAddressOne must be set; the From address is required at send time

Optional fields

FieldDefaultNotes
Smtp.SecurityStartTlsNone | Auto | SslOnConnect | StartTls | StartTlsWhenAvailable
Smtp.RequireAuthtrueIf false, Username/Password are not sent
Smtp.EhloDomainmachine hostnameOverride the EHLO/HELO domain
Smtp.ConnectionTimeoutMs30000
Smtp.SendTimeoutMs30000
Smtp.ValidateCertificatestrueSet false only for self-signed certs on internal relays
Smtp.FromAddress / FromDisplayNameemptyPer-provider sender override

Example — Office 365 SMTP

{
"EmailNotification": {
"DefaultFromAddress": "cinchy-alerts@company.com",
"DefaultFromDisplayName": "Cinchy Notifications",

"Provider": {
"Type": "Smtp",
"Smtp": {
"Host": "smtp.office365.com",
"Port": 587,
"Security": "StartTls",
"RequireAuth": true,
"Username": "cinchy-alerts@company.com",
"Password": "your-app-password"
}
}
}
}

Example — internal relay, no auth, no TLS

{
"EmailNotification": {
"DefaultFromAddress": "cinchy-alerts@company.com",

"Provider": {
"Type": "Smtp",
"Smtp": {
"Host": "mail-relay.internal",
"Port": 25,
"Security": "None",
"RequireAuth": false
}
}
}
}

Security modes (MailKit SecureSocketOptions):

ValueTypical portBehavior
None25No encryption (internal relay only)
AutoanyMailKit auto-detects
SslOnConnect465Implicit TLS from first byte
StartTls587Mandatory STARTTLS upgrade
StartTlsWhenAvailable587Opportunistic STARTTLS

Resilience configuration

Per-send resilience

{
"EmailNotification": {
"Resilience": {
"MaxRetryAttempts": 3,
"TimeoutSeconds": 30,
"RetryBaseDelaySeconds": 2,
"UseJitter": true
}
}
}

This controls retries within a single send attempt (for example, transient SMTP connection failures). These are separate from the outbox-level retries below.

Outbox-level retries

{
"EmailNotification": {
"Outbox": {
"PollingIntervalSeconds": 10,
"BatchSize": 10,
"MaxRetries": 5,
"RetryBaseDelaySeconds": 30,
"RetryBackoffMultiplier": 4.0,
"ClaimTimeoutMinutes": 5,
"StartupDelaySeconds": 5,
"QueryTimeoutSeconds": 30
}
}
}
SettingDefaultDescription
PollingIntervalSeconds10How often the processor and monitors check for pending work.
BatchSize10Max emails claimed per polling cycle.
MaxRetries5Total send attempts before permanent failure.
RetryBaseDelaySeconds30Base delay for exponential backoff.
RetryBackoffMultiplier4.0Multiplier for exponential backoff.
ClaimTimeoutMinutes5Reclaim entries stuck in Sending state.
StartupDelaySeconds5Delay before the processor starts after service boot.
QueryTimeoutSeconds30Per-query timeout for outbox reads/writes and cooldown checks, so a slow or locked database cannot stall the polling loop.

Configuration hierarchy

Settings are resolved in this order — the first non-empty value wins:

SettingFirst (highest priority)SecondThird (fallback)
RecipientsConfig table row (text + groups merged)(none — must be set on the Config row)
CCConfig table row (text + groups merged)(none)
BCCConfig table row (text + groups merged)merged withappsettings.DefaultBccAddress
Reply-ToConfig table rowappsettings.DefaultReplyToAddress
From AddressConfig table rowappsettings.DefaultFromAddress
From Display NameConfig table rowappsettings.DefaultFromDisplayName
PriorityConfig table row(none — normal)
Max RetriesConfig table rowappsettings.Outbox.MaxRetries
Cooldown MinutesConfig table rowappsettings.DefaultCooldownMinutes (default: 5)
BrandingConfig table Client Branding linkappsettings.DefaultBrandingName → hardcoded defaults
Send EmailConfig table rowBlocked when global Notifications Enabled = 0 (additional gate, not a fallback source)
Trigger filteringConfig table row (if exists)Default: Failure-only
note

BCC is special: the per-row BCC and the global DefaultBccAddress are merged, not overridden. This ensures compliance BCC is always applied even when an artifact has its own BCC.

note

There is no "catch-all" row and no global default recipient list. Recipients must be set per artifact on the Config row (via Recipients text or Recipient Groups). Global defaults for cooldown and branding are handled through appsettings.json.

Infrastructure settings reference

Show all infrastructure (appsettings.json) settings
SettingPurpose
DefaultFromAddressDefault sender email for all emails.
DefaultFromDisplayNameDefault sender display name.
DefaultReplyToAddressDefault reply-to address.
DefaultBccAddressDefault BCC for compliance/audit.
DefaultBrandingNameDefault branding config name (from Branding table).
DefaultCooldownMinutesDefault cooldown between duplicate notifications (default: 5).
Provider.TypeSmtp, AwsSes, AzureCommunication, or MicrosoftGraph.
Provider.Smtp.SecurityTLS mode (see Provider setup).
Provider.Smtp.ConnectionTimeoutMsSMTP connection timeout (default: 30000).
Provider.Smtp.SendTimeoutMsSMTP send timeout (default: 30000).
Provider.Smtp.EhloDomainCustom EHLO domain for SMTP.
Provider.Smtp.ValidateCertificatesTLS certificate validation (default: true).
Provider.Smtp.RequireAuthRequire SMTP authentication (default: true).
Provider.AwsSes.ConfigurationSetNameSES configuration set for delivery tracking.
Provider.AwsSes.FeedbackForwardingAddressSES bounce/complaint address.
Provider.AzureCommunication.UseManagedIdentityUse managed identity auth.
Provider.AzureCommunication.EndpointACS endpoint for managed identity.
Resilience.MaxRetryAttemptsPer-send retry attempts (default: 3).
Resilience.TimeoutSecondsPer-send timeout (default: 30).
Resilience.RetryBaseDelaySecondsPer-send retry base delay (default: 2).
Resilience.UseJitterAdd jitter to retry delays (default: true).
Outbox.RetryBaseDelaySecondsOutbox retry base delay (default: 30).
Outbox.RetryBackoffMultiplierOutbox retry backoff multiplier (default: 4.0).
Safety.AllowedRecipientDomainsDomain allow-list for non-production.
Safety.RateLimitPerMinuteClient-side rate limit.

Health endpoints

The service exposes three HTTP endpoints for monitoring and verification. On Kubernetes they back the liveness and readiness probes; on IIS they are reachable under the /notification sub-application path.

EndpointPurpose
GET /healthcheckDetailed status — returns the component name, build identifier, and individual checks for Cinchy connectivity, outbox table access, and the email provider.
GET /healthLiveness — returns { "status": "Green" } when the service is running.
GET /health/readyReadiness — confirms the service can read the outbox table.

Known limitations

  • Crash before enqueue. If a sync pod is OOM-killed mid-execution, the webhook code never runs. The heartbeat monitor partially mitigates this by detecting stale services. Automation Failure, Success, and LongRunning notifications are monitor-driven and unaffected.
  • Single notification service pod. The service runs as one replica. If it is down, outbox entries queue up and are processed when it recovers.
  • Listener Success and Listener LongRunning are not wired. The Notification Config UI exposes both checkboxes for listener rows, but Notify On Success for a listener has no upstream emitter today, and Notify On Long Running is intentionally out of scope for listeners.
  • No step-level automation notifications. Only automation-level rollups are produced. Step status is included inside the automation emails as a step breakdown table; no separate per-step email is produced.
  • Cooldown is window-based, not per-execution. A second failure of the same automation within the cooldown window collapses to one email. This is usually desirable for anti-spam.