Alerts
dotMARC raises an alert when something about a monitored domain needs attention, delivers it through Teams, Slack and/or a generic webhook, and shows the same event in the Alerts feed. An alert resolves itself automatically once the underlying condition clears, no manual dismissal needed.
Alert types
| Type | Raised when | Resolves when |
|---|---|---|
MissedReport | A monitored domain hasn't received a DMARC report within the configured threshold. | A DMARC report is received for that domain. |
TlsrptFailure | A TLSRPT report for the domain contains one or more failed TLS delivery sessions. See MTA-STS: TLS reporting. | A later TLSRPT report for the same domain has zero failed sessions. |
PsaConnectionLost | dotMARC can no longer sign in to a PSA, such as when NinjaOne's sign-in lapses. It doesn't raise tickets by default. See NinjaOne. | Someone reconnects the PSA, or turns it off. |
These alert types are raised at Warning severity. The DNS health alerts below have their own severities.
Cooldown and re-firing
Alerts don't re-fire on every check. If an alert of the same type is already open (unresolved) for a domain, a new occurrence of the same condition is suppressed until the configured cooldown elapses since the open alert was created, so a genuinely down domain doesn't page you every cycle.
The Alerts page
Alerts (/alerts) is the event feed, every alert ever raised, most recent first, with its
domain, type, severity, created/resolved timestamps, and message. It requires the AlertsView
permission, which is part of the built-in Viewer role by default.
Open DMARC policy weakened and nameservers changed alerts have an Acknowledge button for anyone with the
AlertsManage permission. See Closing policy and nameserver alerts.
Alert settings
Alert settings (/alerts/settings) configures delivery. It requires the AlertsManage
permission, granted separately from AlertsView.
| Setting | Description |
|---|---|
| Enable notifications | Master on/off switch. Disabled means no alerts are raised or delivered at all, not just silenced delivery. |
| Teams, Slack, Generic | A switch and webhook URL for each channel. Alerts go to every channel that's switched on and has a URL. Send test posts a marked test alert to the URL as typed, before you save. |
| Missing report threshold (days) | How many days without a report before MissedReport fires. Default 2. |
| Cooldown (minutes) | Minimum time between repeat firings of the same open alert. Default 180. |
| Monitor interval (seconds) | How often the background check for missed reports runs. Default 300. |
| DNS health alerts | For each of the seven checks: When it breaks (default), Whenever it fails or Off. See DNS health alerts. |
| Alert when a DMARC policy weakens | On by default. |
| Alert when nameservers change | On by default. |
| Close policy and nameserver alerts after (days) | 0 (default) keeps them open until acknowledged or their ticket is closed. |
Webhook URLs must be absolute HTTPS URLs with no embedded credentials (no
https://user:pass@host/...); anything else is rejected on save, and Send test won't post to it.
DNS health alerts
dotMARC checks each domain's DMARC, DMARC authorization, TLS-RPT, SPF, MX, DKIM and MTA-STS records about once a day. It raises an alert when one of those checks fails, when a domain's DMARC policy gets weaker, or when its nameservers change.
| Type | Raised when | Resolves when | Severity |
|---|---|---|---|
DmarcRecordBroken | The DMARC record is missing or broken. | The check passes again. | Warning |
DmarcAuthorizationBroken | The record that lets reports go to dotMARC's mailbox is missing. | The check passes again. | Warning |
TlsrptRecordBroken | The TLS-RPT record is missing or broken. | The check passes again. | Warning |
SpfRecordBroken | The SPF record is missing, duplicated or broken. A -all-only record counts as passing. | The check passes again. | Warning |
MxRecordBroken | There's no MX record, or the mail server's name doesn't resolve. A null MX counts as passing. | The check passes again. | Warning |
DkimRecordBroken | A DKIM selector set for the domain is missing or broken. | The check passes again, or the selectors are removed. | Warning |
MtaStsFailing | dotMARC stopped being able to serve the domain's MTA-STS policy. | MTA-STS is active again, or turned off. | Warning |
DmarcPolicyWeakened | p, sp or pct went down, for example from p=reject to p=quarantine. | The policy goes back up, or the alert is closed (see below). | Warning |
NameserversChanged | The domain's nameservers changed, often the start of a DNS migration. | They change back, or the alert is closed (see below). | Info |
A check that hasn't run yet, or doesn't apply (no DKIM selectors, MTA-STS turned off or still being set up), never alerts.
When a check alerts
Each check has a setting:
- When it breaks (the default): alerts only once the check has passed at least once. A domain that was never set up, for example one with no TLS-RPT record, stays quiet.
- Whenever it fails: alerts whenever the check fails.
- Off: never alerts, and closes any open alert.
When a check first fails, nothing is sent. dotMARC checks it again about 15 minutes later and only alerts if it's still failing, so a brief DNS hiccup doesn't page anyone. The same applies to policy and nameserver changes.
Upgrading to a version with DNS health alerts doesn't raise a flood of alerts: on its first run dotMARC notes which checks pass and the current policy and nameservers, and only alerts on changes from there.
Nameservers changed alerts don't open a PSA ticket by default. Change that with the ticket rules, like any other alert type.
Closing policy and nameserver alerts
A weaker DMARC policy or new nameservers may be deliberate, so these alerts compare against an accepted value. Any of these closes the alert and accepts the current policy or nameservers as the new normal:
- Acknowledge on the Alerts page (needs
AlertsManage). It's recorded in the audit log. - Closing its PSA ticket in HaloPSA, NinjaOne, ConnectWise or Autotask.
- Closing automatically after the number of days in Close policy and nameserver alerts after (days), if set.
Delivery channels
Delivery is best-effort: a failed webhook call is logged as a warning and does not stop the alert from being recorded or shown in the Alerts feed, and does not affect the rest of that check cycle. Each channel is sent separately, so one that's down doesn't stop the others.
For syncing alerts to a PSA instead of (or alongside) Teams, Slack or webhook delivery, see PSA integration.
Teams
Sent as an Adaptive Card (application/vnd.microsoft.card.adaptive, schema version 1.5) via
POST to the Teams webhook URL, with the domain, alert type, and message as a fact set under the
alert title.
Slack
Sent as a POST to a Slack incoming webhook, using Slack's Block Kit layout: a "dotMARC alert" header, the alert
title, the domain and alert type side by side, then the message. To get a webhook URL:
- At api.slack.com/apps, create an app (from scratch) in your workspace.
- Under Incoming Webhooks, turn them on, then Add New Webhook to Workspace and pick the channel.
- Copy the URL (it starts
https://hooks.slack.com/services/) into Slack webhook URL, switch Slack on, and use Send test to check it.
Generic webhook
Sent as a POST with a JSON body to the generic webhook URL:
{
"domainName": "contoso.io",
"alertType": "MissedReport",
"title": "Missing expected DMARC report",
"message": "The monitored domain 'contoso.io' has not received a DMARC report since 2026-08-30T00:00:00+00:00.",
"severity": "Warning",
"createdUtc": "2026-09-02T14:32:10.1234567+00:00"
}
| Field | Type | Description |
|---|---|---|
domainName | string | The domain the alert is about. |
alertType | string | MissedReport or TlsrptFailure (see Alert types above). |
title | string | Short summary, e.g. "Missing expected DMARC report". |
message | string | Full human-readable detail, including the domain name and, where relevant, counts or timestamps. |
severity | string | Currently always Warning. |
createdUtc | string | ISO 8601 timestamp (UTC) of when the alert was raised. |
There's no signature or shared secret on these requests, treat the webhook URL itself as the credential and keep it private. Your endpoint should return a 2xx status; a non-2xx or unreachable endpoint is logged and otherwise ignored.