IT

Guides / windows-server

550 5.7.54 on the right connector: it arrived over IPv6

The receive connector was configured correctly and the relay right was granted. Exchange refused anyway, because the connection never reached that connector.

An application needed to send mail to the outside world through Exchange. The dedicated receive connector had been created, the address ranges were right, the relay right had been granted. The message was refused.

550 5.7.54 Unable to relay recipient in non-accepted domain

Re-reading the connector configuration achieved nothing, because the connector configuration was correct. The problem was that the connection was not arriving on that connector.

The protocol log tells you where it came from

SMTP protocol logs are not on by default, but they are the only place where Exchange states which connector accepted a connection and which address it saw it arrive from. Turning them on and reading again closed the question in one line.

LAB-MBX01\Default Frontend LAB-MBX01,...,[fe80::51f1:d32e:f1c2:2fab%4]:25,...

Two pieces of information, both unexpected.

The connector that accepted the connection was Default Frontend, not the one dedicated to the application. And the source address was fe80::IPv6 link-local, the address every network interface gives itself without anyone configuring it.

Why the right connector was never chosen

The dedicated connector was listening on 0.0.0.0:25, with remote ranges expressed in IPv4. 0.0.0.0 means “every IPv4 address on this machine” — it does not mean “every address”. An IPv6 connection cannot match it, under any circumstances.

Default Frontend, on the other hand, also listens on [::]:25. When an IPv6 connection arrives, it is the only remaining candidate, and Exchange assigns it. At that point the refusal is correct: Default Frontend does not grant relay to unauthenticated senders, and rightly so. If it did, the server would be an open relay.

The system was not getting it wrong. It was applying, to the letter, a rule written for a different connector.

The two fixes, and which to choose

Connect by IPv4 address. The application targets the numeric address instead of the name. It removes the problem at the root and touches nothing in Exchange, but it gives up name resolution: if the server changes address, the application has to be edited by hand.

Add fe80::/64 to the connector’s remote ranges.

Set-ReceiveConnector "smtp-app-lab" -RemoteIPRanges @{add="fe80::/64"}

This keeps the name and makes IPv6 connections match too. It is the cleaner choice, on one condition: that the connector really is listening on [::]:25 as well — otherwise you have added a range to a connector that will still never be selected.

Verify, do not assume:

Get-ReceiveConnector "smtp-app-lab" | Select-Object Bindings, RemoteIPRanges

The incidental discovery

In the same log, a few lines further on, there was a second refusal nobody was looking for.

Inbound authentication failed as we reject well-known account
authentication for CONTOSO\Administrator
535 5.7.3 Authentication unsuccessful

Exchange refuses on principle to accept SMTP authentication from well-known accounts — Administrator first among them — regardless of the password. This is not a configured policy: it is product behaviour.

It is the same 535 5.7.3 you meet in production when someone tries to make an application send using the administrator’s credentials “just to test”. It will never work, and the reason is not the password. It is also the structural reason applications need dedicated service accounts: it is not merely hygiene, it is the only thing Exchange will accept.

The three lessons

Before re-reading the configuration, confirm it is the one in use. Hours spent checking a correct connector are hours in which the right question — which connector answered? — had not yet been asked.

0.0.0.0 does not mean “everything”. It means “all of IPv4”. Every rule written in IPv4 has a hole exactly the shape of IPv6, and that hole opens by itself the day a client decides to prefer it.

A refusal can be the system working. Default Frontend did its job. The fault was upstream, in how the connection was routed, and looking for it inside the component that complained meant looking in the wrong place.

Lab built with the support of Ilie.