SMTP EHLO sends [127.0.0.1] instead of server hostname (Symfony Mailer migration)

XFConvert

Member
Licensed customer
Affected version
2.3.9
Description:

After upgrading from XenForo 2.0.6 to 2.3.9, outgoing SMTP emails intermittently fail with 421 rejections from Google's SMTP relay (smtp-relay.gmail.com). The error message:

Expected response code "250" but got code "421", with message "421-4.7.0 Try again later, closing connection. (EHLO)"

The root cause is that Symfony Mailer's EsmtpTransport defaults to EHLO [127.0.0.1] when no local_domain is specified. The previous SwiftMailer implementation automatically used the server's hostname for the EHLO greeting, but the migration to Symfony Mailer in XenForo 2.3 does not set the local_domain option.

In src/XF/Mail/Mailer.php, the getTransportFromOption() method creates the SMTP transport via EsmtpTransportFactory::create() with a Dsn object, but does not pass a local_domain option. The Dsn constructor accepts options as its 6th parameter, but it is not used.

Google (and potentially other strict mail servers) reject EHLO [127.0.0.1] as it appears to come from a misconfigured server.

Workaround:

Adding the following line immediately after the transport is created (after line 553 of src/XF/Mail/Mailer.php in XF 2.3.9):

$transport->setLocalDomain('yourserver.yourdomain.com');

This resolves the issue, but the fix is overwritten on upgrade.

Suggested fix:

Either:
(a) Automatically set the local_domain from PHP's gethostname() when constructing the SMTP transport, similar to how SwiftMailer behaved, or
(b) Expose a local_domain / EHLO hostname field in Admin CP > Email Options, or
(c) Support a config.php option (e.g. $config['emailTransport']['localDomain']) that gets passed through to the Dsn options.

Option (a) would be the most seamless and backward-compatible, requiring no action from administrators.
 
Interims workaround without patching

config.php
PHP:
$c->extend('mailer.transport', function (\Symfony\Component\Mailer\Transport\TransportInterface $transport) {
    $transport->setLocalDomain('yourserver.yourdomain.com');

    return $transport;
});
 
Back
Top Bottom