exim -bpc returns a five-figure number, mail is crawling, and the load average is climbing. The
queue is backed up — but before you run the "delete everything" one-liner you found on a forum,
work out why. A queue full of frozen bounces is a different problem from a queue full of
deferred outbound spam, and clearing the wrong one either loses legitimate mail or papers over a
compromised account that refills the queue in minutes.
This is the triage order for a cPanel box where Exim won't drain. For stopping the outbreak in the first place, see Exim outbound throttling; this article assumes the queue is already on fire.
Step 1: size the queue and split it by state
exim -bpc # total messages
exiqgrep -c -z # frozen only
exiqgrep -c -r '.' # count by recipient regex (sanity check)
A message is frozen when Exim has given up retrying — almost always a bounce with no valid return
path (<> sender). It is deferred when delivery failed but Exim will retry on schedule. The split
tells you which branch to follow:
- Mostly frozen, sender
<>→ bounce backscatter. Usually safe to purge (Step 3). - Mostly deferred to remote domains, one local sender → outbound spam from a compromised account (Step 2). Do not purge first.
- Deferred to your domains → a real delivery problem (full disk, broken
/etc/localdomains, MySQL down). Fix the cause; don't delete mail.
Step 2: find the account flooding the queue
Before clearing anything, identify the top senders. If one account owns most of the queue, you have a compromise, not a backlog.
# Top authenticated senders / auth IDs in the queue
exim -bpr | grep -oP '(?<=<)[^>]+(?=>)' | sort | uniq -c | sort -rn | head
# Who is sending right now, by directory / script
grep cwd /var/log/exim_mainlog | grep -v /var/spool | awk '{for(i=1;i<=NF;i++) if($i ~ /cwd=/) print $i}' | sort | uniq -c | sort -rn | head
The cwd= line points straight at the offending site's document root — that is the WordPress install or
PHP script doing the sending.
Step 3: clear the queue selectively
Match the command to what you found. Always prefer the narrowest filter that solves the problem.
# Remove only frozen messages (safe for backscatter bounces)
exiqgrep -z -i | xargs -r exim -Mrm
# Remove messages from one sender
exiqgrep -f '^baduser@example\.com$' -i | xargs -r exim -Mrm
# Remove messages older than 3 days (259200 seconds)
exiqgrep -o 259200 -i | xargs -r exim -Mrm
Only when you've confirmed the queue is entirely junk should you reach for the nuclear option:
# Delete EVERY message in the queue — irreversible
exim -bp | awk '/<[^@]+@/{print $3}' | xargs -r exim -Mrm
Step 4: verify the queue actually drains
After clearing, watch the count fall and confirm it stays down:
watch -n5 'exim -bpc'
If the count climbs again, Step 2 missed the source — recheck cwd= in the live log. A queue that
refills after a clean purge is a compromise, full stop. Run a malware scan
(Imunify360 Proactive Defense catches most PHP mailers)
and rotate the account's passwords.
Step 5: clean up the queue database
A queue that hit six figures leaves a bloated retry/wait hints database that slows every delivery.
Compact it during a quiet window:
exim_tidydb -t 7d /var/spool/exim retry
exim_tidydb -t 7d /var/spool/exim wait-remote_smtp
If Exim itself is wedged and ignoring signals, /scripts/restartsrv_exim restarts the daemon cleanly on
cPanel without touching your config.
What is the difference between a frozen and a deferred Exim message?+
How do I delete all frozen messages in cPanel Exim?+
Why does my Exim queue fill up again right after I clear it?+
Is it safe to delete the whole Exim mail queue?+
How do I count how many messages are in the cPanel mail queue?+
Next steps
- Exim outbound throttling on cPanel — per-account caps and ACLs so the queue never floods again.
- Route outbound mail through a smart host — keep sending if your server IP gets blacklisted during cleanup.
- Email deliverability: SPF, DKIM, and DMARC on cPanel — the inbound-reputation side of the same problem.