Checklist
Anonymous relay (550 5.7.54) checklist
Based on the article: 550 5.7.54 Unable to relay: configuring anonymous relay on Exchange Server safely · 4 min read
Your scanner, ERP system or monitoring tool can email internal users, but every message to an outside address fails with 550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain. That is Exchange correctly refusing to act as an open relay. In this post I'll show how to allow relay for exactly those hosts with a dedicated receive connector, test it, and make sure you haven't opened the server to the internet. The steps apply to Exchange Server SE, 2019 and 2016.
Symptoms to confirm
The application's SMTP log, or a manual Telnet test, shows the rejection at the RCPT TO stage:
MAIL FROM:<scanner@contoso.com>
250 2.1.0 Sender OK
RCPT TO:<supplier@fabrikam.com>
550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain- Recipients in your own accepted domains work; only external addresses fail.
- Older Exchange versions, and Microsoft's own Telnet test steps, use the wording
550 5.7.1 Unable to relayfor the same condition. - It typically starts after applications move to a new Exchange server, after an application server's IP address changes, or when a load balancer or NAT device is placed in front of Exchange.
Likely causes
- An unauthenticated connection to port 25 on a Mailbox server lands on the
Default Frontend <ServerName>receive connector in the Front End Transport service. That connector has to accept anonymous mail, because that's how internet mail reaches you, but only for recipients in your accepted domains. - When several connectors listen on the same address and port, Exchange uses the one whose remote IP ranges match the connecting IP most specifically. So the fix is a dedicated connector that lists only your application servers.
Checklist
- 1
Find out which IP Exchange sees and which connector answered
powershellGet-ReceiveConnector -Server EX01 | Format-Table Name, TransportRole, Bindings, RemoteIPRanges -AutoSize $log = Join-Path $env:ExchangeInstallPath "TransportRoles\Logs\FrontEnd\ProtocolLog\SmtpReceive" Select-String -Path "$log\*.LOG" -Pattern "5.7.54" | Select-Object -Last 5Each protocol log line includes the connector name and the remote endpoint (IP address and port). If the remote IP is a load balancer, NAT or gateway address rather than the application server, that's the address Exchange matches on.
- 2
Create a dedicated Frontend connector
powershellNew-ReceiveConnector -Name "Anonymous Relay" -Server EX01 -TransportRole FrontendTransport -Custom ` -Bindings 0.0.0.0:25 -RemoteIPRanges 10.10.20.15,10.10.20.16Create it in the Front End Transport service, not the Transport service, whose default connector listens on port 2525 for other Exchange servers.
RemoteIPRangesaccepts single addresses, ranges and CIDR notation; be as specific as you can. - 3
Grant relay with one method, not both
Method A, anonymous relay (least privilege, and the one I'd default to):
powershellSet-ReceiveConnector "EX01\Anonymous Relay" -PermissionGroups AnonymousUsers Get-ReceiveConnector "EX01\Anonymous Relay" | Add-ADPermission -User "NT AUTHORITY\ANONYMOUS LOGON" -ExtendedRights "Ms-Exch-SMTP-Accept-Any-Recipient"Method B, externally secured:
powershellSet-ReceiveConnector "EX01\Anonymous Relay" -AuthMechanism ExternalAuthoritative -PermissionGroups ExchangeServersMethod Hosts are treated as Antispam and size limits Use it when A: AnonymousUsers + Accept-Any-Recipient Anonymous senders Still applied Most applications and devices B: ExternalAuthoritative + ExchangeServers Authenticated internal senders Bypassed Hosts you trust completely - 4
Point the application at the server
Configure the application to use the Exchange server's FQDN or IP address on port 25 without authentication. If the application can sign in with a mailbox, authenticated submission on port 587 (the Client Frontend connector) is the better design and needs no relay connector at all.
Watch out: If a load balancer or firewall source-NATs connections, Exchange sees its address, not the application's. Never add that address to the relay connector if internet traffic can also arrive from it, because you'd have built an open relay. Preserve the client IP on the load balancer, or point applications at the servers directly.
Verify
Get-ReceiveConnector "EX01\Anonymous Relay" | Format-List Enabled, TransportRole, Bindings, RemoteIPRanges, PermissionGroups
Get-ReceiveConnector "EX01\Anonymous Relay" | Get-ADPermission -User "NT AUTHORITY\ANONYMOUS LOGON" |
Where-Object { -not $_.Deny -and -not $_.IsInherited } | Format-Table User, ExtendedRights- Then test from an allowed host with the Telnet Client or any SMTP test tool. After
RCPT TOwith an external address you should get250 2.1.5 Recipient OK, and after the message body250 2.6.0 ... Queued mail for delivery.
Get-TransportService | Get-MessageTrackingLog -Sender scanner@contoso.com -Start (Get-Date).AddMinutes(-30) |
Format-Table Timestamp, EventId, Source, Recipients -AutoSize- Good looks like a
RECEIVEevent followed by aSENDthrough your internet send connector or smart host.
Prevent it next time
- Never add relay rights to the default receive connectors, and never use
0.0.0.0-255.255.255.255on a relay connector. Microsoft explicitly advises against adding anonymous relay to the default connectors. - Audit who can relay. Only your dedicated relay connectors should appear in this output:
- Keep a record of each allowed IP address and its owner, and remove decommissioned hosts.
- When you build new servers, for example moving to Exchange Server SE on new hardware, recreate the relay connector on them before you repoint the applications.
- If relay works only intermittently, review the message rate and throttling settings on the connector.
+1 more tips in the full article.