The email check looks at a domain's mail records as public resolvers see them right now and reports what is wrong: missing or duplicated SPF, too many SPF lookups, weak DKIM keys, no DMARC, proxied mail names and more. It works for delegated and external zones and changes nothing. Reading it needs the readonly role; forcing a fresh check needs tech.
Run the check
Open the domain's DNS › Email. Public check shows the result; Check again runs it now. The domain's Overview has an Email card with the worst status.
curl "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/email/check?refresh=1" \
-H "Authorization: Bearer $OPENWAF_TOKEN"selectors=s1,s2 adds DKIM selectors to look for (up to 10). Without refresh=1, a result from the last minute is reused.
Ask your assistant to check the email of example.com. It calls email_check (zone, optional selectors and refresh) and summarises what is not ok.
The report has a summary.status (the worst of all checks) and one entry per check, each with a status (ok, warn, fail or info), a stable code and its params. It also lists the providers detected from the MX records, the SPF includes and the DKIM selectors.
What is checked
| Check | Codes |
|---|---|
mx | mx_ok, mx_missing (fail), mx_null (info: the domain declares it receives no mail), mx_mixed (warn: MX of several providers), mx_no_address (fail), mx_cname (warn) |
spf_record | spf_ok, spf_missing (fail), spf_multiple (fail: more than one SPF record), spf_syntax (fail) |
spf_lookups | spf_lookups_ok, spf_lookups_exceeded (more than 10 DNS lookups, nested includes counted), spf_void_exceeded (more than 2 lookups with no answer), spf_loop, spf_include_missing, spf_include_invalid |
spf_policy | spf_all_strict (-all), spf_all_soft (~all), spf_all_pass (fail: +all), spf_all_neutral (warn: ?all), spf_ptr (warn) |
dkim | dkim_ok, dkim_weak, dkim_invalid, dkim_revoked, dkim_missing |
dmarc | dmarc_enforced, dmarc_monitoring (info: p=none), dmarc_missing (fail), dmarc_multiple, dmarc_invalid, dmarc_rua_unauthorized (warn) |
proxied | proxied_ok, proxied_mail_name (fail: mail, smtp, imap, pop, mx, autodiscover, autoconfig or an MX target of the zone is proxied), mx_target_proxied (fail: an MX resolves to the OpenWAF edge) |
conflicts | conflicts_ok, conflict_cname (fail: a CNAME next to other records, or the domain itself is a CNAME in public DNS) |
world | world_ok, world_mismatch (warn: the zone's MX, SPF, DMARC or DKIM differ from what the world sees), world_external (info) |
Any check can also carry lookup_error (warn) when a resolver did not answer.
SPF lookups
SPF allows at most 10 DNS lookups when a receiver evaluates the record (RFC 7208). include, a, mx, ptr, exists and redirect cost one lookup each, wherever they appear in the include tree; ip4, ip6 and all cost none. The dashboard shows the include tree with the lookups of each branch.
DKIM selectors
OpenWAF looks for DKIM keys at the selectors you pass, the *._domainkey names of the zone, the selectors of known providers and common ones (default, selector1, k1, s1, dkim, mail…). RSA keys under 1024 bits are invalid; under 2048 bits they are reported as weak.
Set up a mail provider
DNS › Email › Set up email generates the records of a mailbox provider (Google Workspace, Microsoft 365, Zoho Mail, Proton Mail, Fastmail, iCloud+ or another) and of sending services (Amazon SES, Resend, Mailgun, SendGrid, Brevo, MailerLite):
- Providers. Choose one mailbox (where mail is received) and any number of sending services.
- Details. Paste the values each provider shows: DKIM key, verification code, region…
- Records. Review the exact records to create, update, keep or delete, and the DMARC policy. OpenWAF keeps a single SPF record that merges your providers, counts its lookups and never tightens an existing
~allwithout asking. - Apply. In a delegated zone, the records are applied as one version, which you can revert from the history. In an external zone, create them at your DNS provider by hand.
Start DMARC with p=none and a reporting address: after 2–4 weeks, when the reports show only your own services, move to p=quarantine and then p=reject. The check reminds you while the policy is still none.