550 5.7.23
Returned by Microsoft (Exchange Online) and other receivers. The wording varies between operators and versions; the code is what identifies it.
The message was rejected because of Sender Policy Framework violation.
What the receiving server did
The receiver took the domain from the SMTP envelope sender — not the From header a human reads — looked up its SPF record, and asked whether the connecting IP address is permitted to send for it. The record said no.
An SPF record ends in a qualifier that decides what "no" means. -all is a hard fail and licenses the receiver to reject outright, which is what produced this code. ~all is a soft fail and normally results in delivery with a mark rather than a rejection.
Because the check uses the envelope sender, this code can appear even when the visible From address looks perfectly correct — the two are different fields and frequently hold different domains.
Why yours failed — in the order it is usually true
- 1
A legitimate sender was never added to the record
Find the sending IP in the bounce or in the Received chain and compare it against the record. Invoicing software, an ERP, a ticket system and a website contact form are the four that get forgotten most reliably.
No SPF record found — what it means and how to fix it - 2
Two SPF records are published, which invalidates both
RFC 7208 permits exactly one. A second record — usually added when a new service was set up rather than merged into the existing one — makes the result PermError, and a receiver may treat that as a failure.
Multiple SPF records on one domain (PermError) — how to merge them - 3
The record exceeds the ten-lookup limit
Each include:, a, mx, ptr and exists: mechanism costs a DNS lookup, and includes nest. Past ten the record is invalid regardless of how correct it looks.
SPF PermError: too many DNS lookups (the 10-lookup limit) — how to fix it - 4
Mail is being forwarded
Forwarding replaces the connecting server without changing the envelope sender, so SPF fails through no fault of the record. This is a known limitation of SPF and the reason DKIM exists.
The record
Illustrative only — publish the includes your own providers document, and exactly one record. While you are still finding missing senders, ~all avoids rejecting your own mail; tighten to -all once the aggregate reports are quiet.
Check what your domain publishes right now
Free, no signup. It counts your SPF lookups, tries 24 DKIM selectors and reads your DMARC policy, then tells you which of the causes above applies to you.