Google Workspace SMTP Relay 550 5.7.1 Invalid Credentials on a Dual-Stack Server
Fix Google SMTP relay 550 5.7.1 errors when only IPv4 is allowlisted by preferring IPv4 in gai.conf and restarting PHP-FPM.
Mail sent through smtp-relay.gmail.com is rejected at MAIL FROM even though the serverโs IPv4 address is allowlisted in the Google Workspace SMTP relay settings.
550-5.7.1 Invalid credentials for relay [<server-ipv6>]. The IP
550-5.7.1 address you've registered in your Workspace SMTP Relay service
550-5.7.1 doesn't match the domain of the account this email is being sent
550 5.7.1 from.
The address in square brackets is the giveaway: it is the serverโs IPv6 address, not the IPv4 address that was allowlisted.
Cause
smtp-relay.gmail.com has both A and AAAA records. On a dual-stack server the default address selection prefers IPv6, so the connection arrives from an address the relay does not recognise. The relay accepts the TCP connection, EHLO and STARTTLS, then refuses the message at MAIL FROM, which makes it look like a credentials or domain problem.
Fix
These steps make the server prefer IPv4 for outbound connections. Inbound traffic is unaffected, and IPv6 stays enabled.
Confirm which address is rejected
Test each address family without sending a message. The script stops after RCPT TO. Save it as relay-test.py, replacing the placeholders:
import smtplib, socket
for family, name in ((socket.AF_INET, 'ipv4'), (socket.AF_INET6, 'ipv6')):
try:
addr = socket.getaddrinfo('smtp-relay.gmail.com', 587, family)[0][4][0]
s = smtplib.SMTP(timeout=15)
s._host = 'smtp-relay.gmail.com'
s.connect(addr, 587)
s.ehlo('<your-domain>')
s.starttls()
s.ehlo('<your-domain>')
print(name, 'MAIL', s.mail('no-reply@<your-domain>'))
print(name, 'RCPT', s.rcpt('postmaster@<your-domain>'))
s.rset()
s.quit()
except Exception as e:
print(name, 'FAIL', repr(e))
Then run it on the server:
python3 relay-test.py
If IPv4 returns 250 and IPv6 returns 550 5.7.1, this article applies.
Prefer IPv4
Uncomment the existing precedence line in /etc/gai.conf, or add it if it is missing:
sudo sed -i 's|^#precedence ::ffff:0:0/96 100|precedence ::ffff:0:0/96 100|' /etc/gai.conf
grep '^precedence' /etc/gai.conf
Restart PHP-FPM
Running PHP-FPM workers can keep using IPv6 after this change, so restart the service. Adjust the version to match the server:
sudo systemctl restart php8.5-fpm
Verify
Check the connection from inside PHP-FPM, not only from the command line. Command-line PHP picks up the change immediately, so it can pass while the website still fails.
Save this as a temporary script that is not publicly reachable, and run it through the PHP-FPM pool:
<?php
$s = stream_socket_client('tcp://smtp-relay.gmail.com:587', $errno, $error, 10);
echo 'local=', stream_socket_get_name($s, false), ' peer=', stream_socket_get_name($s, true), "\n";
The local= value should be the serverโs IPv4 address. Then send a real message from the application and delete the temporary script.
Notes
/etc/gai.confsets a preference only. If IPv4 to the relay fails, the connection can still fall back to IPv6 and be rejected again.- Fully disabling IPv6 is a much larger change. Web servers listening on
[::], firewall rules and AAAA records used by a reverse proxy may all depend on it. - Adding the IPv6 address to the relay allowlist, or using SMTP authentication, should also work, but neither was tested here.
- A PHP-FPM reload was not tested. Only a full restart was confirmed.
- Tested on Ubuntu 26.04 with PHP 8.5, WordPress and WP Mail SMTP.