Bounce and error codes

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

550 5.7.23 The message was rejected because of Sender Policy Framework violation

Microsoft sometimes appends the sending IP or a SPFRecord diagnostic. Keep that IP: it is the fastest route to the cause.

Causes

  1. 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.
  2. 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.
  3. SPF permerror treated as a violation. Over ten lookups, or a record with two v=spf1 strings, and evaluation stops with an error that many receivers handle as a failure. Fix that first.
  4. 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

dig +short TXT example.com dig +short TXT _dmarc.example.com

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:

v=spf1 ip4:203.0.113.24 include:_spf.google.com -all

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 digest

No 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.