What the standard actually says
The Cyber Security Agency of Singapore (CSA) certifies organisations with two marks: Cyber Essentials for basic cyber hygiene and the risk-based Cyber Trust mark. The 2025 edition of Cyber Essentials covers classical cyber security, cloud security, OT security and AI security.
Email authentication sits in section A.4, "Virus and malware protection". Clause A.4.4 (d) applies when the scope of certification includes web browser or email use, and lists measures such as anti-phishing and spam filtering, fully supported email clients, and this one: email authentication protocols such as SPF, DKIM and DMARC should be implemented to provide email security.
The wording matters. In the document's own definitions, "shall" is a requirement and "should" is a recommendation. So DMARC is a recommendation in Cyber Essentials, not a hard requirement. In the same section, A.4.4 (j) says the organisation shall make sure employees immediately report suspicious emails or attachments.
Why do it anyway? In May 2026 the Singapore Police Force reported at least 66 business email compromise cases since the start of the year, with losses of at least $19 million, and advised organisations to implement DMARC on their email domains. CSA's Internet Hygiene Portal also checks DMARC. A recommendation that auditors, the police and customers all look at is worth treating as a requirement.
SPF, DKIM and DMARC in two minutes
- SPF lists the servers that may send for a domain. It checks the envelope sender (Return-Path), not the From address people see.
- DKIM signs every message. The receiver checks the signature with a public key in the DNS of the signing domain (the
d=value). DKIM survives forwarding, SPF does not. - DMARC ties both to the visible From domain. A message passes when SPF or DKIM passes and its domain matches the From domain. That match is called alignment, and it is where most third-party senders fail.
The policy decides what happens to messages that fail: p=none only reports, p=quarantine sends them to junk, p=reject refuses them at the door.
Step 1: start with reporting
Publish a record with p=none and an address for aggregate reports:
_dmarc.example.com.sg TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com.sg"
Check what is published today, for every domain you own, including the ones that never send mail:
"example.com.sg","example.sg" | ForEach-Object {
[pscustomobject]@{
Domain = $_
SPF = (Resolve-DnsName $_ -Type TXT -ErrorAction SilentlyContinue | Where-Object { $_.Strings -like "v=spf1*" }).Strings -join ""
DMARC = (Resolve-DnsName "_dmarc.$_" -Type TXT -ErrorAction SilentlyContinue).Strings -join ""
}
}
Or type the domain into the domain check of DMARC Geeks, the tool I built for this work. It reads MX, SPF, DKIM, DMARC, MTA-STS, TLS-RPT and BIMI in one go.
Step 2: find every sender
After a day or two, the large mailbox providers send XML reports. Each row says: this many messages with your From domain came from this IP, and this is how SPF and DKIM evaluated. Group the rows by source and map each source to a system and an owner. In a typical company that means Exchange Online, a newsletter tool, a CRM, a ticketing system, the accounting software, a multifunction printer and one forgotten script.
Keep the result as a simple table. It becomes the list you check every new service against later.
| System | From address | Path | SPF aligned | DKIM aligned | Owner |
|---|---|---|---|---|---|
| Exchange Online | staff@ | Microsoft 365 | yes | yes | IT |
| Newsletter tool | news@ | vendor platform | no | no, signs as vendor | Marketing |
| Scanner | scan@ | SMTP from office IP | no | no | Facilities |
Reading the XML by hand gets tedious quickly. A DMARC analysis service, or a small script, groups the reports by source. The tool matters less than someone looking at the results every week.
Step 3: fix each sender
The usual failures
- Foreign Return-Path: the newsletter tool sends
From: news@example.com.sgbut bounces to its own domain. SPF passes for the vendor's domain, which does not count for DMARC. Adding the vendor'sinclude:to your SPF record does not help here. - Foreign DKIM signature: the service signs with its own domain. Valid, but not aligned. Set up your own sending domain in the service and publish the DKIM records it gives you.
- Devices and scripts: they send from an IP that is not in SPF and do not sign. Route them through Exchange Online, which signs with your domain's key.
- Gateways that change messages: a disclaimer or link rewriting after signing breaks DKIM. The system that changes the message last has to sign it.
Stay under ten SPF lookups
Every include:, a and mx costs DNS lookups, nested includes included. More than ten is a permanent error and SPF fails. Remove services you no longer use, leave out services that use their own Return-Path anyway, and move bulk senders to a subdomain such as news.example.com.sg with its own SPF record.
DKIM in Exchange Online
Connect-ExchangeOnline
# Create the configuration if the domain has none yet
New-DkimSigningConfig -DomainName "example.com.sg" -Enabled $false
# Read the two CNAME targets for DNS
Get-DkimSigningConfig -Identity "example.com.sg" | Format-List Domain, Enabled, Selector1CNAME, Selector2CNAME
# After publishing selector1._domainkey and selector2._domainkey as CNAMEs
Set-DkimSigningConfig -Identity "example.com.sg" -Enabled $true
Always take the CNAME targets from Get-DkimSigningConfig. Microsoft has changed the format of the targets, and examples copied from old blog posts often no longer match.
Step 4: tighten in stages
| Phase | Policy | Typical duration | Goal |
|---|---|---|---|
| Inventory | none | 2–4 weeks | Every sender found and assigned |
| Repair | none | per sender | SPF or DKIM aligned for every legitimate sender |
| Quarantine | quarantine | 2–4 weeks | No legitimate failures in the reports |
| Enforce | reject | permanent | Spoofed mail is refused |
Move to the next phase when the reports show no failing legitimate source, not when the calendar says so. Two more tags are worth knowing: sp= sets a policy for subdomains, and pct= applies the policy to a share of messages, which receivers honour inconsistently. Do not rely on it as a safety net. Domains that never send mail get v=spf1 -all and p=reject straight away.
Before each step, send a test message from every path to an external mailbox and read the header: dmarc=pass, plus spf=pass with your domain or dkim=pass header.d=example.com.sg.
Checklist
- DMARC record with
p=noneandruapublished, reports arriving - Every sending system identified, with an owner
- Unused SPF includes removed, under ten lookups
- DKIM enabled in Exchange Online and at every third-party sender, with your domain
- Every sending path tested with a real message and a header check
- At least two weeks on
p=quarantinewithout legitimate failures - Move to
p=rejectannounced internally - Parked domains on
v=spf1 -allandp=reject - Reports still reviewed after enforcement
This is engineering guidance, not legal or certification advice. Your certification body decides how it assesses the clause.