cPanel Server Sending Spam? Find and Stop the Source
Outbound mail flooding out of a server nobody logged into means something else is doing the sending. Here is how to find it and shut it down.
A cPanel server sending spam without anyone touching WHM almost always means one of three things: a compromised account, a hijacked contact form or plugin, or a cron job nobody remembers writing. The queue fills, the load climbs, and if you are unlucky your IP is already on a blacklist before you notice.
Confirm it is really your server, and how bad it is
Start with a queue count. If this number is in the thousands, or climbing while you watch, you have an active sender, not a stale backlog.
exim -bpc
Prints a single number: total messages currently queued.
exiqsumm breaks the queue down by domain, which tells you fast whether this is one account hammering one target or a genuine flood.
exim -bp | exiqsumm | tail -20
If most of the destination domains look like consumer webmail providers (gmail.com, yahoo.com, outlook.com, hotmail.com) in large volume, that is a spam signature, not normal customer traffic.
Find which account or script is doing it
Every message exim accepts from a local process gets a U= field in /var/log/exim_mainlog, naming the system user that submitted it. This is the single most useful line in the whole file, because it points straight at the cPanel account, bypassing any need to guess from sender addresses that are usually spoofed anyway.
grep -oP 'U=\K[^ ]+' /var/log/exim_mainlog | sort | uniq -c | sort -rn | head -20
The user at the top with an implausibly high count is your account.
Once you have the username, check what is actually calling the mail function. Recently modified files are the fastest lead, since a compromise usually drops or edits a file within the last few days.
find /home/USERNAME/public_html -iname '*.php' -mtime -5 -type f -printf '%T@ %p\n' | sort -rn | head -30
Also check cron. A surprising number of spam incidents are a scheduled task someone set up years ago on a script that has since been exploited, not a fresh upload.
crontab -l -u USERNAME
Stop the bleeding
-
1
Suspend the account
This stops new mail from being accepted for that user immediately, in WHM under Account Functions, or
whmapi1 suspendacct user=USERNAME reason='investigating outbound spam'. It does not touch mail already queued. -
2
Clear only that sender's queued mail
Filter by the account's outgoing address pattern before removing anything.
exiqgrep -i -f 'USERNAME@' | xargs -r exim -Mrmremoves only messages sent from that address. Never pipe the whole queue intoexim -Mrmwithout a filter. -
3
Remove or quarantine the offending file
Move the malicious script or plugin out of the web root (do not delete yet, you may need it to understand how the account was compromised), then reset the account's cPanel and any application admin passwords.
-
4
Check for a backdoor before you reopen the account
A single cleaned file is rarely the whole story. Search for freshly created files with unusual permissions or names that look like base64-encoded PHP, which is the most common backdoor pattern.
grep -rl --include='*.php' -E 'eval\s*\(\s*base64_decode' /home/USERNAME/public_html
Not exhaustive, but catches the most common obfuscated backdoor shape.
Doing this once, carefully, on one server is a Saturday afternoon. Doing it every time a shared host flags an account, across a fleet of servers, is the actual job for a lot of hosting teams. BashEmail runs this same queue-and-sender triage automatically, flags the account before the IP gets blacklisted, and stops there for approval rather than suspending anything on its own.
Triaging an outbound spam spike in BashPilot
Checked exim_mainlog on web03. One local user accounts for 3,812 of the queued messages in the last hour, all to consumer webmail domains.
| User | Queued | Top destination |
|---|---|---|
| marketing_co | 3812 | gmail.com |
| billing_llc | 41 | outlook.com |
That suspends the account and removes only messages from marketing_co@ from the queue. Legitimate mail from other accounts is untouched. Confirm to proceed.
whmapi1 suspendacct user=marketing_co reason='outbound spam investigation'
exiqgrep -i -f 'marketing_co@' | xargs -r exim -Mrm
Try this on one of your own servers.
Start free trialGet off the blacklist
Clearing the queue stops the spam, it does not undo the reputation damage. Check your sending IP against the major lists before assuming you are done.
- Look the IP up on mxtoolbox.com/blacklists or a similar aggregator to see which lists actually flagged it.
- Most blacklists (Spamhaus, Barracuda, SORBS) have a self-service delisting form once the cause is fixed. Submit it, do not just wait.
- Confirm the server's PTR (reverse DNS) record resolves to the same hostname exim announces in its HELO. A mismatch here gets flagged by receiving mail servers independently of any spam history.
- Check SPF, DKIM and DMARC records under WHM's Email Authentication tool. A missing or broken DKIM signature makes every message from the domain look more suspicious, spam incident or not.
Verify it actually stopped
Do not close this out on the queue count dropping to zero once. Confirm the pattern is gone, not just the current backlog.
watch -n 30 "grep -c 'U=USERNAME' /var/log/exim_mainlog"
If that count stays flat for an hour after the account is suspended and cleaned, the source is actually gone. If it keeps climbing, the account is still compromised, most likely a backdoor you missed, or the cron job is still active under a different mechanism (a scheduled task inside the application itself, not system cron).
Prevent the repeat
- Set a per-account hourly send limit in WHM (Server Configuration > Tweak Settings > Max hourly emails per domain) so one compromised account cannot flood the whole server's reputation.
- Enable cPHulk brute force protection if it is not already on, since a lot of these incidents start with a guessed cPanel or application admin password.
- Keep CMS cores, plugins and themes patched. If you manage many accounts, a scheduled scan is worth more than reacting after the fact.
- Alert on queue size, not just on a blacklist notification. By the time a blacklist notice arrives, the reputation damage is already done.