Bali, Indonesia
Insights

Which IP Does Exim Actually Send From on a Multi-IP WHM Server?

October 30, 2026
0:00
A WHM server with several IPs often produces one confusing ticket: SPF passes, reverse DNS looks right, and mail still lands in spam or gets rejected. In many of these cases the records are correct, but they describe an IP that Exim is not using. Exim does not send from the IP your website sits on. It sends from whatever source address the kernel picks, unless cPanel's /etc/mailips and /etc/mailhelo tell it otherwise. This guide is about checking, not guessing. You list what the server has, see what Exim is configured to do, confirm the IP that actually reached the recipient, then change it and check again.
When Exim opens an SMTP connection to a remote mail server, the operating system has to choose a source address for that connection. If the program does not bind to a specific local IP, the kernel uses the routing table and usually picks the server's primary address on the interface that holds the default route. On a typical multi-IP WHM box, that is the main shared IP, no matter which domain the message came from. cPanel's generated Exim config can override that. The remote SMTP transport has an interface option that can look up the sending domain in /etc/mailips and bind to the IP it finds. A helo_data option can look up the same domain in /etc/mailhelo to choose the hostname Exim announces in its HELO/EHLO greeting. Both behaviors are controlled by options in WHM's Exim Configuration Manager. The exact option names vary a bit between versions, so check your own WHM. The common misconception follows from this. An account with a dedicated IP does not send mail from that IP just because its website answers there. If the per-domain option is off, or the files are empty, mail leaves from the main IP. The dedicated IP's carefully set PTR record never gets used.
Start with read-only checks. You want to know which IPs are bound, which one the kernel prefers, and whether the live Exim config references the mapping files at all.
BASH
# IPv4 and IPv6 addresses bound to this server
ip -4 addr show
ip -6 addr show

# Source address the kernel would choose for an outside destination
ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111

# Current per-domain mapping files (they may be empty or missing)
cat /etc/mailips /etc/mailhelo

# Confirm the generated Exim config actually reads them
grep -nE 'mailips|mailhelo' /etc/exim.conf
The src field in the ip route get output is the address Exim falls back to when nothing overrides it. Write it down. If grep returns nothing for /etc/exim.conf, the files have no effect, whatever they contain. Read the interface and helo_data lines it does return. They show exactly how the lookup is keyed, so you are not relying on memory of how cPanel builds them. Do not skip the IPv6 lines. If the server has a global IPv6 address and the recipient's MX has an AAAA record, Exim may deliver over IPv6. That connection has its own source address, which needs its own PTR record and must be covered by SPF. Plenty of setups have clean IPv4 records and an IPv6 address nobody configured for mail.
Next, send a test message from a real mailbox on the affected domain, through webmail or a mail client, to an external address you control. Sending from the root shell can use a different sender domain and skew the per-domain lookup. Then follow that message through /var/log/exim_mainlog.
BASH
# Show every log line for messages to the test recipient
exigrep '[email protected]' /var/log/exim_mainlog | tail -n 20

# Check whether the outgoing_interface log selector is enabled
grep -n 'log_selector' /etc/exim.conf
In the delivery line (the one with =>), H= shows the remote host and its IP in brackets. That is the destination, not your source. A lot of people misread this field. The local IP Exim sent from appears as an I=[192.0.2.10]-style field only when the outgoing_interface log selector is enabled. If your log_selector line does not include it, the log will not tell you the source address directly, and the receiving side becomes your main evidence. Also watch for I= on the arrival line (the one with <=). There it means the local interface the message was received on, which says nothing about the outbound path.
The receiver's view is the one that counts, because it is the IP that the receiver checked SPF and reverse DNS against. Open the test message in the external mailbox and view the raw source or original message. Read the Received: headers from the top down. Find the first one added by the receiving provider, where the by part names their server and the from part names yours. It contains the HELO name your server announced, often the reverse DNS name the receiver looked up, and your connecting IP in square brackets. Many providers also add an Authentication-Results or Received-SPF header that states which client IP the SPF check was evaluated against. If you want a refresher on reading that header, the DKIM body hash article walks through it. Compare three things: the bracketed IP, the HELO name, and the reverse DNS name. On a correctly set up domain, all three point to the same identity. Another IP of yours in the brackets confirms the mismatch. Expect another wrinkle on some cloud VPS setups. The interface carries a private address and the provider maps it to a public one with NAT, so Exim's log shows the private IP while the header shows the public one. In that case the header is the truth, and the PTR has to be set on the public IP.
Once you know what is happening, the fix is a pair of simple lookup files. Each line maps a sending domain to a value, and a * line sets the default for everything else.
TEXT
# /etc/mailips  (sending domain: source IP)
example.com: 192.0.2.10
*: 192.0.2.5

# /etc/mailhelo  (sending domain: HELO hostname)
example.com: mail.example.com
*: server.example.org
A few rules keep this from making things worse:
  1. Every IP in /etc/mailips must actually be bound to the server. If it is not, Exim cannot use it as a source address and deliveries for that domain will fail rather than fall back quietly.
  2. Each HELO name should resolve forward to the IP it is paired with, and that IP's PTR should return the same name. dig +short mail.example.com and dig -x 192.0.2.10 +short check both directions.
  3. The domain's SPF record must authorize the IP you mapped it to. dig TXT example.com +short shows what receivers will see.
  4. Turn on the matching options in WHM's Exim Configuration Manager. Depending on which options are enabled, WHM may regenerate these files from account IP assignments and overwrite manual edits. Find out which mode you are in before editing by hand.
Once the change is in place, repeat the same checks. Send another test from the real mailbox, run exigrep again, and read the new Received: header. You are done when the bracketed IP, HELO name, PTR, and SPF all agree. Seeing the right line in /etc/mailips does not prove that on its own. From the support side, the usual trap is checking DNS first and stopping there because everything looks valid. Check it the other way around. Find the IP the recipient actually saw, then make the records and the Exim mapping match that IP. Keep the inventory commands and the test-message routine handy, and run them again after every IP change, migration, or new dedicated IP. Those are the moments when the outgoing address shifts without anyone noticing.