📑 Daftar Isi
- Why Default Exim Logging Falls Short
- Enabling Verbose Logging in WHM
- Essential Exim CLI Commands Every NOC Engineer Must Know
- Understanding Exim Log Notation Symbols
- Decoding Exim SMTP Error Codes
- Code 421 — Service Temporarily Unavailable
- Code 450 — Access Denied (Temporary)
- Code 451 — Local Processing Error (Temporary)
- Code 452 — Insufficient Storage (Temporary)
- Code 550 — Mailbox Not Found / Relay Denied (Permanent)
- Code 553 — Mailbox Name Not Allowed
- Code 554 — Transaction Failed
- SpamAssassin and SpamBox Integration
- Common Problem Patterns in Exim Logs
- Pro Tips and Warnings
- Quick Troubleshooting Decision Tree
- Conclusion
I remember the first time a client called me panicking because their business emails were bouncing back with no clear explanation. I pulled up the Exim mainlog on their cPanel server and stared at lines that told me almost nothing useful. The default logging was so sparse that I spent over two hours just trying to figure out where in the delivery chain things were falling apart. That was the day I learned that Exim’s default logging is built for performance, not for troubleshooting.
Think of Exim logs like the black box recorder on an airplane. When everything goes smoothly, you never think about it. But when something goes wrong — a plane crashes, or in our case, emails bounce or disappear — you need every bit of data that recorder captured. Default Exim logging gives you the flight number and destination, but not the engine readings, weather conditions, or pilot inputs. Verbose logging changes that equation entirely.
In this guide, we are going to walk through everything a NOC engineer needs to know about Exim logs in cPanel. From enabling verbose logging to reading log notation, mastering CLI commands, decoding SMTP error codes like 421, 450, 550, and 554, and understanding how SpamAssassin and SpamBox integrate with the mail flow. Everything here comes from real production experience handling hundreds of servers daily.
Why Default Exim Logging Falls Short
Before we dive into commands and configs, you need to understand why default Exim logging is insufficient for serious troubleshooting. By default, Exim only records minimal information — enough to see that an email arrived and was delivered, but not enough to understand why a specific message failed, why routing went wrong, or why SMTP authentication suddenly stopped working.
The real-world impact is significant. When a client reports a bounced email, you end up guessing instead of reading what actually happened in the log. A troubleshooting session that should take ten minutes stretches into an hour or more. In business contexts, a failed email delivery can mean a lost deal, an unpaid invoice, or critical communication that never reaches its destination.
The good news is that Exim gives you full control over what gets logged. You just need to know where to configure it and what parameters to use. The bad news is that most cPanel server administrators never touch the logging configuration, which means they are working with a significant blind spot every time they try to diagnose email issues.
Enabling Verbose Logging in WHM
There are two primary ways to enable verbose logging in Exim on cPanel: through the WHM interface and by directly editing the configuration file.
Method 1: WHM Advanced Editor
Login to WHM, navigate to Service Configuration, then Exim Configuration Manager, and click the Advanced Editor tab. Look for the log_selector section where you can add the parameters you need. Here are the most useful ones:
| Parameter | Function | When to Use |
|---|---|---|
+all |
Enable all verbose logging | Intensive debugging (not for long-term production) |
+address_rewrite |
Log every address rewrite process | Forwarding and filtering issues |
+dns_lookup |
Log every DNS lookup | DNS and MX record problems |
+host_lookup_failed |
Log failed DNS lookups | DNS timeouts and resolution failures |
+reject |
Log all email rejections | Spam filtering and blocked senders |
+smtp_confirmation |
Show SMTP confirmation from remote server | Debugging bounces and remote rejections |
+smtp_protocol_error |
Log SMTP protocol errors | Failed SMTP communication |
+tls_cipher |
Show TLS cipher information | Encryption and TLS handshake debugging |
My recommendation for production servers: do not use +all because the logs will become enormous and consume significant disk I/O. Instead, use a targeted combination of parameters. Here is a solid configuration for debugging email delivery issues:
log_selector = +address_rewrite +dns_lookup +host_lookup_failed +reject +smtp_confirmation +smtp_protocol_error
If you genuinely need full debugging (like during a critical incident investigation), use +all but remember to revert to a lighter configuration once you are done. Leaving +all active on a busy server for days will generate gigabytes of log data.
Method 2: Direct Configuration File Edit
Open /etc/exim.conf and find the log_selector line. If it does not exist, add it in the Main configuration section:
log_selector = +address_rewrite +dns_lookup +host_lookup_failed +reject +smtp_confirmation
After editing, restart Exim:
systemctl restart exim
Or through WHM: Home, Restart Services, Exim Mail Server.

Essential Exim CLI Commands Every NOC Engineer Must Know
Once verbose logging is active, you need to master the Exim CLI commands that let you read and analyze logs. These are the commands I use almost every single day:
Basic Monitoring Commands
| Command | Function | Use Case |
|---|---|---|
exiwhat |
Show what Exim is currently doing | Check for stuck processes |
exim -bpc |
Count emails in queue | Check for queue overflow |
exim -bp |
List emails in queue | See which emails are pending |
exim -bp | head -30 |
Show top 30 queued emails | Quick queue check |
exigrep <pattern> /var/log/exim/mainlog |
Search for specific pattern in log | Trace a specific email |
exim -Mvh <message-id> |
Show email headers | Inspect a specific email |
exim -Mvb <message-id> |
Show email body | Check email content |
exim -Mra <message-id> |
Resend email from queue | Retry delivery |
exim -Mrm <message-id> |
Remove email from queue | Delete spam/stuck mail (CAUTION!) |
Before running exim -Mrm, make sure you have:
- Backed up the queue list:
exim -bp > /tmp/mailqueue-backup-$(date +%Y%m%d-%H%M).txt - Verified the target with
exim -Mvh <message-id> - Confirmed the email is genuinely spam or stuck, not a valid client message
Running deletion without verification can cause permanent data loss — important client emails may disappear forever.
Log Search and Analysis Commands
# Find all emails from a specific IP
exigrep "192.0.2.10" /var/log/exim/mainlog
# Find all emails to a specific address
exigrep "user@client-a.com" /var/log/exim/mainlog
# Find all errors from the last 24 hours
exigrep "== " /var/log/exim/mainlog | grep "$(date +%Y-%m-%d)"
# Find all bounces
exigrep "** " /var/log/exim/mainlog | tail -20
# Find all rejected emails
exigrep "rejected" /var/log/exim/mainlog | tail -20
# Find all successfully delivered emails
exigrep "=> " /var/log/exim/mainlog | tail -30
Understanding Exim Log Notation Symbols
This is the most critical part to understand. Exim uses symbolic notation to mark activity types in its logs. If you do not understand these symbols, reading Exim logs will be like trying to navigate a foreign city without a map.
| Symbol | Meaning |
|---|---|
<= |
Email received (arrived at server) |
=> |
Email delivered successfully |
-> |
Email forwarded or copied |
** |
Email bounced (failed, returned to sender) |
== |
Email deferred (delivery temporarily delayed) |
The reading pattern is left-to-right. <= means the email arrived, then => means it was delivered, ** means it bounced, and == means it was deferred. From these symbol combinations, you can map the entire journey of an email from arrival to completion.
Complete Log Example and Analysis
Let us look at a real log example and learn to read it step by step:
2026-07-20 09:15:33 [45231] <= orders@shop-client.com H=mail.shop-client.com [203.0.113.25] P=ESMTPS X=TLSv1.3 TLS_AES_256_GCM_SHA384 CV=no C="250 OK id=1mN8k2-0003ABC-123" S=4521 I=5 E=none N=8 QT=0.002 DT=0.001
2026-07-20 09:15:34 [45231] => admin@mydomain.com R=virtual_user T=virtual_delivery H=local [127.0.0.1] C="250 OK" QT=0.8 DT=0.799
2026-07-20 09:15:34 [45231] => sales@mydomain.com R=virtual_user T=virtual_delivery H=local [127.0.0.1] C="250 OK" QT=0.8 DT=0.799
2026-07-20 09:16:45 [45232] <= newsletter@marketing-tool.com H=relay.marketing-tool.com [198.51.100.50] P=ESMTPS X=TLSv1.2 TLS_AES_128_GCM_SHA256 CV=no C="250 OK id=2kL9m3-0004DEF-567" S=15234 I=8 E=none N=12 QT=0.003 DT=0.002
2026-07-20 09:16:46 [45232] == user@mydomain.com R=lookuphost T=remote_smtp H=mx1.mydomain.com [203.0.113.10] C="421 4.7.1 Try again later" QT=1.2 DT=1.198
2026-07-20 09:16:46 [45232] == user@mydomain.com R=lookuphost T=remote_smtp H=mx2.mydomain.com [203.0.113.11] C="421 4.7.1 Try again later" QT=1.2 DT=1.198
2026-07-20 09:21:46 [45232] == user@mydomain.com R=lookuphost T=remote_smtp H=mx1.mydomain.com [203.0.113.10] C="421 4.7.1 Try again later" QT=5.0 DT=4.999
2026-07-20 09:31:47 [45232] == user@mydomain.com R=lookuphost T=remote_smtp H=mx1.mydomain.com [203.0.113.10] C="450 4.7.25 IP not in whitelist" QT=10.0 DT=9.998
2026-07-20 09:31:47 [45232] ** user@mydomain.com: H=mx1.mydomain.com [203.0.113.10] C="450 4.7.25 IP not in whitelist — too many connections" QT=10.0 DT=9.998
2026-07-20 09:31:47 [45232] Frozen (delivery error message)
2026-07-20 09:31:47 [45232] <= <> R=double-bounce T=double_bounce S=0 QT=0.001 DT=0.001
Here is the trace from start to finish:
- Line 1 (
<=): Email arrives fromorders@shop-client.comvia TLS. Message ID is45231. Everything normal here. - Lines 2-3 (
=>): Email successfully delivered toadmin@mydomain.comandsales@mydomain.comlocally. Two recipients handled. - Line 4 (
<=): New email arrives fromnewsletter@marketing-tool.com. Message ID45232. - Lines 5-6 (
==): Delivery touser@mydomain.comfails on both MX1 and MX2 — remote server responds421 4.7.1 Try again later. The remote server is busy or rate limiting. - Line 7 (
==): First retry after 5 minutes — still fails with same code. - Line 8 (
==): Second retry — error changes to450 4.7.25 IP not in whitelist. Our server IP hit a rate limit or temporary block. - Line 9 (
**): BOUNCE — email fails permanently after retries exhausted. Full error message displayed. - Line 10 (
Frozen): Email frozen in queue due to delivery error. - Line 11 (
<=): Double bounce recorded — the bounce message itself also failed to deliver.
From this trace, we can conclude: the problem is not on our local server but on the remote MX server rejecting connections because our IP hit rate limiting. Solution: check whether our IP is listed in any RBLs and consider adjusting retry configuration.
Decoding Exim SMTP Error Codes
Now we get to the section you have been waiting for — understanding Exim error codes. Exim follows standard SMTP reply codes but adds internal details that are extremely helpful for troubleshooting.
Code 421 — Service Temporarily Unavailable
Error 421 means the destination server is not ready to receive email. This is temporary — Exim will automatically retry. But if it keeps appearing, there is a problem that needs attention.
2026-07-20 10:05:12 [67890] == recipient@external.com R=lookuphost T=remote_smtp H=mx.external.com [203.0.113.50] C="421 4.7.1 Service temporarily overloaded" QT=0.5 DT=0.499
2026-07-20 10:10:13 [67890] == recipient@external.com R=lookuphost T=remote_smtp H=mx.external.com [203.0.113.50] C="421 4.3.2 Not currently accepting mail" QT=5.0 DT=4.998
2026-07-20 10:25:15 [67890] == recipient@external.com R=lookuphost T=remote_smtp H=mx.external.com [203.0.113.50] C="421 4.7.1 Service temporarily overloaded" QT=15.0 DT=14.997
2026-07-20 11:05:16 [67890] => recipient@external.com R=lookuphost T=remote_smtp H=mx.external.com [203.0.113.50] C="250 OK id=3mP7q1-0008GHI-901" QT=40.0 DT=39.995
In this example, the email is initially rejected due to server overload. Exim retries several times and finally succeeds on the fourth attempt after 40 minutes. If you see this pattern, do not panic — Exim is working as designed.
Code 450 — Access Denied (Temporary)
450 means there is a temporary access issue. The most common causes: rate limiting, IP temporarily blacklisted, or authentication not yet completed.
2026-07-20 14:22:10 [11223] == client@partner.com R=lookuphost T=remote_smtp H=mx.partner.com [198.51.100.15] C="450 4.7.1 IP not in whitelist" QT=0.3 DT=0.298
From this log, our server IP is likely on a temporary whitelist at the partner server. Check our IP against common RBLs:
# Check server IP against various RBLs
dig +short 10.0.0.1.zen.spamhaus.org
dig +short 10.0.0.1.b.barracudacentral.org
dig +short 10.0.0.1.bl.spamcop.net
Code 451 — Local Processing Error (Temporary)
451 indicates a local error at the destination server. Also temporary with automatic retry. Usually related to DNS issues or server restarts in progress.
Code 452 — Insufficient Storage (Temporary)
452 means the mailbox is full or the server ran out of storage. Frequently appears for shared hosting mailboxes that have exceeded their quota.
2026-07-20 16:44:55 [33445] ** user@hosting-client.com: Remote host said: 452 4.2.2 Mailbox quota exceeded QT=0.001 DT=0.001
Solution: login to the client cPanel, check disk usage under Email Accounts, and ask the client to clean up their mailbox or upgrade their quota.
Code 550 — Mailbox Not Found / Relay Denied (Permanent)
This is a permanent error — Exim will not retry because the destination server rejected definitively. 550 has several important sub-variants:
# 550 User not found
2026-07-20 17:05:12 [55667] ** nonexistent@client-a.com R=lookuphost T=remote_smtp H=mx.client-a.com [203.0.113.20] C="550 5.1.1 The email account that you tried to reach does not exist" S=189 QT=0.5 DT=0.499
# 550 Relay denied
2026-07-20 17:10:33 [66778] ** spammer@random-domain.com R=lookuphost T=remote_smtp H=mx.random-domain.com [198.51.100.30] C="550 5.7.1 Relaying denied" S=201 QT=0.3 DT=0.298
# 550 Blocked — sender blacklisted
2026-07-20 17:15:44 [77889] ** sender@blacklisted-domain.com R=lookuphost T=remote_smtp H=mx.external.com [203.0.113.40] C="550 5.7.1 Message rejected — see https://www.spamhaus.org/query/bl/" S=312 QT=0.4 DT=0.398
Code 553 — Mailbox Name Not Allowed
553 usually appears when the email address is syntactically invalid or the destination server does not recognize the domain.
Code 554 — Transaction Failed
554 is the catch-all for permanent errors that do not fit other categories. Frequently appears when the destination server rejects email due to poor IP reputation or content filtering rules.
| Code | Type | Exim Action | Common Cause | Solution |
|---|---|---|---|---|
| 421 | Temporary | Auto-retry | Server overload, maintenance | Wait, check remote server status |
| 450 | Temporary | Auto-retry | Rate limit, temporary IP block | Check RBLs, wait for cooldown |
| 451 | Temporary | Auto-retry | DNS error, server restart | Verify DNS MX records |
| 452 | Temporary | Auto-retry | Mailbox full, quota exceeded | Clean mailbox or upgrade quota |
| 550 | Permanent | Bounce | User, relay denied, blacklisted | Verify address, check IP reputation |
| 553 | Permanent | Bounce | Invalid email syntax, wrong domain | Check recipient email address |
| 554 | Permanent | Bounce | Transaction failed, content filter | Check email content, IP reputation |
SpamAssassin and SpamBox Integration
SpamAssassin and SpamBox are two components that significantly impact email behavior on cPanel servers. If you do not understand how both integrate with Exim, you will struggle when client emails end up in spam folders unexpectedly.
SpamAssassin
SpamAssassin works by adding an X-Spam-Score header to every incoming email. On cPanel, the default threshold for marking email as spam is typically 5.0. You can check the spam score in Exim logs:
# Find all emails marked as spam
exigrep "X-Spam-Score" /var/log/exim/mainlog | tail -20
# Find emails with a specific spam score
exigrep "X-Spam-Score: [89]" /var/log/exim/mainlog
For detailed SpamAssassin scoring, look at the X-Spam-Status header:
X-Spam-Status: No, score=8.2 required=5.0 tests=RCVD_IN_BL_SPAMHAUS,HTML_IMAGE_RATIO_02,MISSING_HTML_TAG,URIBL_BLACK autolearn=unavailable version=3.4.6
From this log, you can see the email scored 8.2 (above the 5.0 threshold), so it was marked as spam. The primary cause is the Spamhaus blacklist test (RCVD_IN_BL_SPAMHAUS) along with several other tests.
SpamBox
SpamBox stores flagged spam in a .Spam folder in the user mailbox instead of blocking it outright. This is good because users can still check their spam folder. But sometimes legitimate emails end up there too, and users do not realize it.
The SpamBox path in cPanel:
/home/username/mail/domain.com/user/.Spam/
Make sure the permissions on this directory are correct. I once handled a case where the .Spam folder had wrong permissions (644 instead of 711), causing SpamBox to fail writing emails to the folder. The result: all spam emails bounced back to senders instead of being filed.
# Check mailbox directory permissions
ls -la /home/username/mail/domain.com/user/
# Correct permissions for mailbox directories
drwx--x--- 3 username username 4096 Jul 20 09:00 .
drwx--x--- 5 username username 4096 Jul 20 09:00 ..
drwx------ 2 username username 4096 Jul 20 09:00 cur
drwx------ 2 username username 4096 Jul 20 09:00 new
drwx------ 2 username username 4096 Jul 20 09:00 tmp
drwx------ 2 username username 4096 Jul 20 09:00 .Spam
Note that mailbox directories use drwx--x--- (711 for directories, 700 for subfolders). This is a critical security setting that prevents other users on the same server from reading mailbox contents.
| Problem | Log Symptom | Root Cause | Solution |
|---|---|---|---|
| Legitimate email marked as spam | X-Spam-Score above threshold | SpamAssassin false positive | Add whitelist in SpamAssassin config |
| SpamBox folder not writable | Delivery failed to local | Wrong folder permissions (not 711) | Fix: chmod 711 .Spam |
| Email bounced without clear reason | ** in log without details | Missing or wrong DNS PTR record | Setup PTR record for server IP |
| SMTP authentication failing | 535 authentication failed | Plain text auth disabled / wrong password | Check “Require SSL” in email client |
Common Problem Patterns in Exim Logs
Based on experience handling hundreds of servers, here are the most frequent problem patterns:
1. Incorrect DNS Configuration (MX/PTR)
One of the most common reasons for email bounces. If MX records are wrong or the PTR record for your server IP is not configured, emails from your server will be rejected by almost all major mail servers.
# Check your domain MX record
dig +short MX yourdomain.com
# Check PTR record for your server IP
dig +short -x 203.0.113.10
# Verify forward-confirmed reverse DNS
hostname -f
The PTR record must resolve to your server hostname, and your hostname must resolve back to the same IP (forward-confirmed reverse DNS). If they do not match, many mail servers will reject emails from your IP.
2. SMTP Authentication Failure
Sometimes clients complain they cannot send email from their email client (Outlook, Thunderbird). In the Exim log you will see:
2026-07-20 20:15:33 [88990] authenticator failed for (client-pc-123): 535 Incorrect authentication data
Causes vary: wrong password, plain text authentication disabled in WHM while the client is not using SSL, or issues with the cPanel dovecotauth driver. Check in WHM under Exim Configuration Manager, Security tab, and ensure SMTP Authentication is properly enabled.
3. Queue Overflow
When thousands of emails get stuck in queue, server performance drops dramatically. Check queue count:
exim -bpc
If the number is in the hundreds or thousands, there is a serious problem. See what is stuck:
exim -bp | head -50
For more details on queue management, read our guide on Exim Mail Queue Management.
Pro Tips and Warnings
- Never leave
+allenabled on production for extended periods. Logs can reach gigabytes per day and burden disk I/O. Enable only during troubleshooting, then revert. - Always check DNS first before concluding there is a problem with the local system. 60% of email issues actually originate from DNS misconfiguration.
- Use
exigrepwisely. Overly generic patterns will return thousands of irrelevant results. Always include a specific message ID or IP address. - Backups are mandatory before destructive operations. This is not optional — it is required. One mistake can mean a client’s important email is lost forever.
- Pay attention to timestamps. When investigating an email bounce, start from the time of the incident and trace forward. Do not start from the last lines of the log.
- Check RBLs regularly. Your server IP can end up on a blacklist at any time. Set up monitoring for hourly auto-checks. Our guide on Checking IP Blacklist RBL covers this in detail.
- Mailbox directory structure must be correct. The folder
/home/username/mail/domain/user/must have proper structure with 711 permissions for directories and 700 for subfolders. See also our Email Troubleshooting cPanel guide for more details. - Understand Exim retry rules. Exim does not immediately remove failed emails. There is a retry mechanism that determines when an email will be attempted again. Check retry configuration in Exim Retry Configuration Guide.
Quick Troubleshooting Decision Tree
When you receive an email issue report, follow this flow:
- Check queue first:
exim -bpc— if high, there is a delivery problem - Check log for specific message ID:
exigrep "<message-id>" /var/log/exim/mainlog - Read the symbols:
<=arrived,=>delivered,==deferred,**bounced - Check error code: 4xx is temporary (retry), 5xx is permanent (bounce)
- Trace from start to finish: Begin at the first line, follow the flow
Conclusion
Reading Exim logs demands attention to detail — you need to understand every symbol, every error code, and be able to trace an email journey from start to finish. But once you master the patterns, troubleshooting email becomes significantly faster and more accurate. Remember: always verify DNS records and server RBL status before concluding the problem is with your local system. And most importantly — backup first, then execute.
Have questions about Exim logs? Our NOC team handles this daily — reach out to us if you need direct assistance with email issues on your server.
Q: Why can I not see verbose logs in Exim even after changing log_selector in WHM?
There are several possible causes. First, make sure you restarted Exim after changing the configuration — editing the config file alone is not enough, Exim must be reloaded to apply changes. Second, verify your syntax is correct — a single typo in the log_selector parameter can prevent the entire configuration from taking effect. Third, check if there is an override file at /etc/exim.conf that might be overriding your WHM settings. You can verify by running exim -bV to see the actually active configuration.
Q: My email is stuck in queue with status “Frozen” — what does that mean and how do I fix it?
Frozen means Exim has stopped attempting to deliver that email because it exceeded the retry limit or encountered a permanent delivery error. To address this, first check why it is frozen with exim -Mvh <message-id> to view the header, then exim -Mvb <message-id> for the body. If you believe the email is valid, try resending with exim -Mra <message-id>. If the email is spam or invalid, remove it with exim -Mrm <message-id> after backing up the queue list.
Q: How long does Exim keep emails in queue before removing them?
By default, Exim retains emails in queue for several days depending on the retry configuration set in WHM. Default retry rules typically attempt resending several times within a specific timeframe before giving up. Emails that exceed the retry limit remain in queue until manually flushed or until the retention period expires. You can check retry configuration in WHM under Exim Configuration Manager, Advanced Editor, in the retry rules section. For more detailed settings, read our Exim Retry Configuration Guide.