Troubleshooting intermittent Exim AUTH negotiation errors#
Managing mail servers with Exim in cPanel/WHM environments often involves dealing with intermittent connection issues. Recently, I analyzed a case where a remote WordPress application (using the Post SMTP plugin) failed randomly to send emails via authenticated SMTP, returning the following protocol error:
AUTH command used when not advertised
Interestingly, sending mail via Webmail (Roundcube) and local clients (such as Thunderbird) worked normally. The problem only occurred during connections from the remote application to the server under my administration.
Below, I detail the step-by-step diagnostics, security audits, and the definitive fix using Exim's ACL configurations.
1. Preparation: security backup#
Before altering any parameters on a production mail server, it is mandatory to backup the active configurations:
# Backup the individual Exim configuration file
cp /etc/exim.conf /etc/exim.conf.bak.$(date +%Y%m%d)
# Create a full compressed backup of the Exim configuration directory
tar czf /root/exim-backup-$(date +%Y%m%d).tar.gz /etc/exim.conf /etc/exim/
Note: In cPanel, you can also export the Exim configuration by going to: WHM » Exim Configuration Manager » Backup.
2. Validating the ssl/tls security layer#
The error AUTH command used when not advertised occurs because Exim stops advertising the authentication method (AUTH) when it detects that the connection is insecure or failed to establish a stable TLS session.
Below, the logical sequence diagram demonstrates Exim's decision-making process for advertising or suppressing the AUTH capability depending on the TLS negotiation status:
Step a: verify certificates and TLS version#
Use openssl to validate certificate expiration, active protocols, and accepted network ciphers:
# Verify validity dates for the mail certificate
openssl s_client -connect mail.meudominio.com.br:465 </dev/null 2>/dev/null | openssl x509 -noout -dates
# Check negotiated protocols and ciphers
openssl s_client -connect mail.meudominio.com.br:465 </dev/null 2>/dev/null | grep -E "Protocol|Cipher"
# Test if STARTTLS works on port 587
openssl s_client -connect mail.meudominio.com.br:587 -starttls smtp
Step b: query Exim's EHLO responses#
Initiate a raw SMTP connection and send the EHLO command to see which capabilities Exim advertises:
# SMTP connection via openssl
openssl s_client -connect mail.meudominio.com.br:465
# Once TLS is established, send:
EHLO app.cliente.com.br
If the output omits the 250-AUTH LOGIN PLAIN line, Exim chose to suppress the authentication methods for that specific connection:
220-server.meuhost.com.br ESMTP Exim 4.99.1
250-server.meuhost.com.br Hello app.cliente.com.br [203.0.113.50]
250-SIZE 52428800
250-LIMITS MAILMAX=1000 RCPTMAX=50000
250-8BITMIME
250-PIPELINING
250-PIPECONNECT
250 HELP
3. Diagnostics and triage via Exim logs#
To understand why the authentication advertisement was suppressed, it is necessary to inspect the Exim logs and the connection behavior.
Step a: identify the client's correct IP#
If the remote SMTP application is hosted on another platform, discover its real public IP before analyzing the logs:
# Run from the client machine to check its outbound IP
curl -s ifconfig.me
# Or query the mail server logs for the client domain
grep "app.cliente.com.br" /var/log/exim_mainlog | tail -n 5
# Confirm the reverse DNS of the identified IP
dig -x 203.0.113.50 +short
Step b: investigate Exim error logs#
Monitor /var/log/exim_mainlog filtering for rejections, TLS errors, or authentication failures associated with the IP:
# Real-time general Exim logs
tail -f /var/log/exim_mainlog | grep "203.0.113.50"
# Filter specifically for authentication errors or rejected connections
grep -E "auth|rejected|denied" /var/log/exim_mainlog | tail -n 20
# Check TLS-related logs
grep "TLS" /var/log/exim_mainlog | tail -n 20
If you find errors like this in the logs: TLS error on connection from app.cliente.com.br [203.0.113.50]: SSL_accept: TCP connection closed by peer
It means the remote application abruptly closed the TCP socket at the beginning of the TLS negotiation. Because the handshake failed intermittently, Exim disabled authentication to protect the credentials.
Step c: simulate connections using exim -bh#
It is possible to test how Exim reacts to connections from a specific IP in a simulated session:
exim -bh 203.0.113.50
Type EHLO app.cliente.com.br in the interactive session and check for ACL rules that block or suppress specific capabilities.
4. The solution: allow unadvertised AUTH for trusted IPs#
To resolve the instability without weakening the security of the entire server, I created a rule in Exim that allows only the specific IP of the remote application (203.0.113.50) to perform authentication even if the AUTH advertisement was suppressed due to negotiation failures.
Step a: configuration via WHM (recommended)#
Do not edit /etc/exim.conf directly, as cPanel will overwrite your changes. Use the administration panel:
- Navigate to: WHM » Exim Configuration Manager » Advanced Editor.
- Locate the section:
custom_begin_smtp_helo. - Insert the following code block:
# 1. Default Security Block (Keep if there are pre-existing rules)
# Note: Guard against missing /etc/heloblocks to prevent lookup warnings or errors
drop
condition = ${if exists{/etc/heloblocks}{${lookup{$sender_helo_name}lsearch{/etc/heloblocks}{yes}{no}}}{no}}
log_message = HELO/EHLO - HELO on heloblocks Blocklist
message = HELO on heloblocks Blocklist
# 2. Solution: Allow unadvertised AUTH for the trusted application IP
warn
hosts = 203.0.113.50
control = allow_auth_unadvertised
# 3. Default Accept
accept
Step b: apply configuration and restart service#
After saving changes in the WHM interface, the rules will be saved and Exim will restart automatically. If you prefer to validate and restart manually via CLI:
# Validate Exim configuration syntax and build info
exim -bV
# Validate if the allow_auth_unadvertised rules were saved
grep -r "allow_auth_unadvertised" /etc/exim.conf
# Verify the configuration loads successfully
exim -C /etc/exim.conf -bP | head -n 5
# Safely restart the Exim service
/scripts/restartsrv exim
5. Post-configuration verification#
After applying the fix, validate that the bypass works as expected:
1. Test via Exim simulation#
Run the simulation again (remember: exim -bh requires root privileges) and check if the control allows using AUTH even if it's not advertised:
exim -bh 203.0.113.50
# Send these commands in order:
EHLO app.cliente.com.br
AUTH PLAIN dGVzdG9wZXJhdGlvbmFs
2. Confirm active variables#
Verify that the Exim variable is configured as planned:
exim -bP auth_advertise_hosts
3. Complete manual SMTP test#
You can test email delivery using different tools from external networks.
# Test TLS handshake on port 465 (implicit TLS)
echo "" | openssl s_client -connect mail.meudominio.com.br:465 -quiet 2>/dev/null
# Secure curl test using a credentials file
# 1. Create a temporary credentials file with restricted permissions
cat > ~/.smtptestrc << 'EOF'
machine mail.meudominio.com.br
login [email protected]
password your_password_here
EOF
chmod 600 ~/.smtptestrc
# 2. Run curl consuming credentials from the file
curl --ssl-reqd --url "smtps://mail.meudominio.com.br:465" \
--netrc-file ~/.smtptestrc \
--mail-from "[email protected]" \
--mail-rcpt "[email protected]" \
-v
# 3. Remove the credentials file from the environment
rm -f ~/.smtptestrc
6. Rollback plan#
If the changes cause any unforeseen issues in the email flow, follow this immediate rollback procedure:
Rollback via CLI#
# Restore the original configuration file from the most recent backup
cp "$(ls -t /etc/exim.conf.bak.* 2>/dev/null | head -1)" /etc/exim.conf
# Restart the Exim service
/scripts/restartsrv exim
Rollback via WHM#
- Navigate to: WHM » Exim Configuration Manager.
- Click the Reset tab and select Reset to Default to revert the custom ACLs.
7. Firewall and compatibility audits#
Step a: verify SMTP ports are open and active#
# Verify listening SMTP ports (25, 465, 587)
ss -lntp | grep -E "25|465|587"
# Audit iptables rules for SMTP ports
iptables -L -n | grep -E "465|587"
Step b: check IP blocks in configserver security & firewall (CSF)#
If the external client completely loses connection to the server, verify if the IP was temporarily blocked by LFD/CSF:
# Search for the IP in CSF
csf -g 203.0.113.50
# Remove the IP from blocklist if listed
csf -dr 203.0.113.50
csf -r
Step c: get Exim version and package updates#
# Verify installed version
exim -V
# Check if there are pending package updates
# On RHEL 8/9, Rocky, and AlmaLinux, yum is an alias for dnf
yum check-update exim
# Explicit modern alternative:
dnf check-update exim 2>/dev/null || true
Automated SMTP and AUTH diagnostics script#
For a quick triage of Exim status and environment validations, use the diagnose-exim-auth.sh script:
#!/bin/bash
# diagnose-exim-auth.sh - Exim SMTP AUTH Diagnostics
# Usage: ./diagnose-exim-auth.sh <CLIENT_IP>
set -euo pipefail
CLIENT_IP="${1:-}"
echo "=========================================================="
echo " RUNNING EXIM AND SMTP AUTH DIAGNOSTICS"
echo "=========================================================="
# 1. Exim Version
echo -e "\n[1] Exim Version:"
exim -V | head -3
# 2. Service Status
echo -e "\n[2] Service Status (systemctl):"
if systemctl is-active --quiet exim; then
echo " ✅ Exim is active and running"
else
echo " ❌ Exim is inactive or has errors"
systemctl status exim --no-pager | head -n 10
fi
# 3. Listening SMTP Ports
echo -e "\n[3] Active SMTP Ports:"
ss -lntp | grep -E ":25|:465|:587" || echo " ⚠️ No SMTP ports (25, 465, 587) are listening!"
# 4. Global AUTH Configuration
echo -e "\n[4] Exim AUTH Advertise Configuration:"
exim -bP auth_advertise_hosts || echo " (not configured)"
# 5. Client IP Analysis (optional)
if [ -n "$CLIENT_IP" ]; then
echo -e "\n[5] Client IP Analysis ($CLIENT_IP):"
echo -e " - Reverse DNS (PTR):"
dig -x "$CLIENT_IP" +short || echo " No PTR record found"
echo -e " - Recent entries in exim_mainlog:"
grep "$CLIENT_IP" /var/log/exim_mainlog | tail -n 5 || echo " No recent records found"
fi
# 6. Custom ACLs in exim.conf
echo -e "\n[6] Custom ACLs (allow_auth_unadvertised):"
grep -n "allow_auth_unadvertised" /etc/exim.conf || echo " No bypass rules configured."
# 7. TLS host advertisement configuration (another common cause of AUTH suppression)
echo -e "\n[7] Exim tls_advertise_hosts Configuration:"
exim -bP tls_advertise_hosts 2>/dev/null || echo " tls_advertise_hosts not set (AUTH may be suppressed on all non-TLS connections)."
echo -e "\n=========================================================="
echo " DIAGNOSTICS COMPLETED"
echo "=========================================================="
Production takeaways#
The AUTH command used when not advertised error is a defensive mechanism deployed by Exim to prevent transmitting credentials under degraded SSL/TLS handshakes. By identifying the trusted source IP and configuring the allow_auth_unadvertised parameter in the HELO ACLs, transaction delivery is restored for the partner application while maintaining server integrity.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments