Recently, I had to deal with a serious problem: backscatter.
One of our mail gateways ended up listed on the backscatter.org blacklist for sending bounce messages to forged senders.

After checking the logs, I quickly realized that our system wasn’t actually protected against backscatter attacks, so I had to do something about it.

What Even Is Backscatter?

Backscatter is unwanted email that your mail server sends after receiving a message, usually in the form of a non-delivery report (NDR) or bounce to a forged sender address.

It happens when:

  • A spammer sends email with a fake “From” address (often an innocent third party).
  • Your mail server accepts the message first, but later discovers it’s undeliverable.
  • Your server sends a bounce to the forged address, hitting an innocent person instead of the spammer.

This makes your server appear to be sending spam, even though you’re just bouncing bad mail.

The Problem in Our Setup

Our mail gateway mostly relays mail to multiple internal Exchange Server clusters.
We have a list of valid domains configured, so Postfix will only accept mail for those domains.

The problem?
Postfix didn’t know which individual recipients were valid on the downstream Exchange servers.
That meant it would happily accept messages for nonexistent users, only to later bounce them, classic backscatter behavior.

The Goal

We needed to reject mail during the SMTP session, ideally right after the RCPT TO command, if the recipient didn’t exist on the Exchange servers.

That way, the sending server would get the rejection immediately, and we would never have to generate a bounce message.

Possible Solutions I Considered

1. relay_recipient_maps

This would require maintaining a full list of valid recipients in a Postfix lookup table.
It works well, but means writing and maintaining a script to sync the list from Active Directory on a regular basis.

For us, this was too much custom scripting, too fragile, and too messy to maintain.

2. virtual_mailbox_maps with LDAP

Another approach would be using LDAP lookups directly against Active Directory to verify recipients in real-time.

This can work in some setups, but:

  • It adds complexity and dependencies.
  • It can introduce security concerns.
  • It didn’t fit well with our environment.

So I ruled it out.

The Solution: reject_unverified_recipient

While reading through the Postfix Address Verification Howto, I came across the reject_unverified_recipient option - bling! - exactly what I needed.

How It Works

When an incoming SMTP session reaches the RCPT TO stage:

  1. Postfix checks if reject_unverified_recipient is enabled for the recipient domain.
  2. If yes, it temporarily probes the downstream mail system to see if the recipient address exists.
  3. If the downstream system says:
    • User exists → Postfix continues processing.
    • User does not exist → Postfix rejects immediately with:
      550 5.1.1 <user@example.de>: Recipient address rejected: User unknown
      

Because the rejection happens during SMTP, no bounce is generated, and backscatter is avoided entirely.

Implementation in ISPConfig

In our case, the mail gateways run Postfix with ISPConfig as the management interface.
I implemented a new configuration option in ISPConfig for per-domain control of reject_unverified_recipient, along with a validation server to specify for the downstream validation server.

Specifying a Validation Server for Recipient Verification

One important detail is that Exchange servers cannot validate recipients over the default SMTP transport on port 25. To enable recipient validation, you need to activate it on the Exchange server and use the Hub Transport service, which by default runs on port 2525.

Make sure to restrict access to this port, as it requires anonymous login specifically for recipient validation, you don’t want that exposed broadly.

Note: This setup does not affect your regular mail flow. Only the SMTP probes used for verifying recipients are sent to this validation server.
Postfix enables this behavior with the address_verify_transport_maps option.

To optimize performance and reduce unnecessary verification probes for addresses that have already been checked, I configured a local cache on the mail gateway using the address_verify_map option. This way, repeated probes for the same recipient are avoided.

Now, for domains that need recipient verification, we can enable it in the panel and point Postfix to the appropriate validation transport.

The Result

After enabling reject_unverified_recipient and pointing it at the Exchange clusters, the backscatter stopped completely.
We were no longer accepting messages for invalid recipients.

Conclusion

If your Postfix server is acting as a relay for Exchange (or any downstream mail system) and you’re struggling with backscatter spam, enabling reject_unverified_recipient can be a clean and effective fix.

It avoids maintaining large static recipient maps, works dynamically, and ensures that invalid mail is rejected before it ever gets into your system.