550 5.7.23 The message was rejected because of Sender Policy Framework violation
Last updated 2026-08-14
Exchange Online checked your SPF record, the connecting IP was not authorised, and your
record ends in -all. That is the whole story in the simple case. The
interesting cases are forwarding and permerror.
What it means. The recipient's Microsoft 365 tenant rejected the message because SPF evaluation for the envelope sender domain did not authorise the IP that connected.
What to change. Add the sending system to your SPF record, or give it a return-path on a domain whose SPF does authorise it. Then make sure DKIM signs too, so forwarded copies survive.
When it clears. As soon as the updated SPF record is out of cache at the receiving end, which is your TTL plus a few minutes.
The exact bounce
Microsoft sometimes appends the sending IP or a
SPFRecord diagnostic. Keep that IP: it is the fastest route to the cause.
Causes
- A new sending system nobody added. New CRM, new ticketing tool, a script on a VM. Check the IP from the bounce against the SPF checker output.
- Forwarding. The recipient forwards to a Microsoft 365 mailbox. SPF is evaluated against the forwarder's IP, which your record has never heard of, so it fails. Nothing you publish will make plain forwarding pass SPF. DKIM is the fix, and it is why alignment on DKIM matters more than SPF perfection.
-
SPF permerror treated as a violation. Over ten lookups, or a record
with two
v=spf1strings, and evaluation stops with an error that many receivers handle as a failure. Fix that first. -
An envelope sender you did not expect. Bounce handling at a bulk
platform often uses
bounces.vendor.net. If it does, your SPF record is not even consulted, and a 5.7.23 means the vendor's own record has a problem. Tell the vendor.
Diagnose
Exactly one v=spf1 string, please. Two SPF records is a permerror and it is
more common than it should be, because DNS panels make it easy to add rather than edit.
Then run the SPF checker and look at the lookup counter and the resolution chain. The chain view is where you see that one include pulls in four more, which is how a record that reads as five lookups turns out to be eleven.
Fix
Add the system properly. For a server you own, an ip4: literal costs zero
lookups and never breaks:
For a platform, use its documented include and check the counter afterwards. Keep
-all. A record that ends in ~all to paper over a missing sender
is a record that will not protect you the day it matters, and receivers increasingly
treat softfail as fail anyway.
For forwarding, get DKIM working and stop trying to solve it with SPF. Signed mail passes DMARC through as many forwarding hops as you like, as long as nothing rewrites the body.
You fixed this sender. Tomorrow the reports name the other hosts still sending as you, and we turn a day of XML into one email with a verdict per sender. On the paid plans, the day a report first names a new sender failing, you hear about it. Get the weekly digest. The first domain is free.
Hear about the next failing sender first
This rejection named one sender, and the next to break sends no warning ahead of it. On a paid plan, the first failing report from a new source reaches you as an email that day, not in Monday's digest. Pro watches 5 domains for $19 a month.
Get the alerts and the digestNo card · 12+ months of history · The free plan does not expire
Questions
Is 550 5.7.23 my problem or the recipient's?
Usually yours: the recipient's Exchange Online checked your SPF record and the connecting IP was not in it. The exception is forwarded mail, where the last hop is a server neither of you controls and only DKIM can save it.
Should I change -all to ~all to stop it?
No. Softfail hides the problem and weakens the record for everyone, and Microsoft can still reject on the composite verdict. Add the missing sender or fix the return-path.
Keep reading
Checking as you fix? Our DMARC checker, SPF checker and DKIM checker read the records live, no signup.