/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.
What decides the outgoing IP
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.
Take inventory before changing anything
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.confsrc 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.
Read what Exim logged
/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=>), 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.
Confirm from the receiving side
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.
Map domains to IPs and HELO names
* 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- Every IP in
/etc/mailipsmust 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. - 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.comanddig -x 192.0.2.10 +shortcheck both directions. - The domain's SPF record must authorize the IP you mapped it to.
dig TXT example.com +shortshows what receivers will see. - 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.
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.