EST. 2026 — Notes from real server work SYSADMIN · SECURITY · AI · DIRECTADMIN Issue 01
THE SYSADMIN ALMANAC
Home / Security / Tracing Dovecot IMAP/POP Failures on DirectAdmin and Keeping 90-Day Logs
Security — Mail Forensics [2]

Tracing Dovecot IMAP/POP Failures on DirectAdmin and Keeping 90-Day Logs

by Ton-Or ·23 May 2026·11 min read
Tracing Dovecot IMAP/POP Failures on DirectAdmin and Keeping 90-Day Logs

In Part 1, I traced exim mainlog to find devices with incorrect passwords on the LAN. After publishing it, more questions came in — where to check IMAP/POP failures, why DirectAdmin logs disappear within days, and how to keep a full 90 days. I wrote this follow-up to cover the whole process.

In Part 1, I described tracing exim mainlog to find a machine on the LAN that kept using an incorrect password, causing LFD to ban the entire subnet. After the article went up, several questions followed, mostly around three things — which log to check for IMAP/POP when "fetching mail," why DirectAdmin logs disappear before there is time to investigate, and where to make changes to keep them for 90 days.

I am covering the rest in this installment, focusing on the stack DirectAdmin actually uses: exim for SMTP, dovecot for IMAP/POP, and LFD/CSF for intrusion protection. If your machine uses postfix instead of DA's stack, the path differs (it is /var/log/maillog instead), but the overall patterns are similar and easy enough to adapt. I have included the adjustments at the end.

Placeholders used in this article

I am using the same placeholders as in Part 1 to avoid exposing real data. Replace them with your own machine's values when using the commands.

  • example.com is the example customer domain
  • 203.0.113.x and <server-ip> are public IPs (remote and server sides)
  • 192.168.1.x is an internal LAN IP (RFC1918)
  • [email protected] is the example mail account

Mail log paths on DirectAdmin

The most common mistake is looking for logs in the wrong place. General tutorials usually point to /var/log/exim4/mainlog or /var/log/maillog, but DirectAdmin uses a different layout (I checked this on an actual DA-Debian machine). Here is the actual layout.

exim/var/log/exim/mainlog
reject/var/log/exim/rejectlog
dovecot/var/log/mail.log
LMTP/var/log/dovecot-lmtp.log
LFD/var/log/lfd.log

More detail on each file

  • /var/log/exim/mainlog — exim SMTP logs (the ones I covered in Part 1)
  • /var/log/exim/rejectlog — connections rejected before the data phase
  • /var/log/mail.log — dovecot IMAP/POP logs written through rsyslog; this is the main focus of this installment
  • /var/log/dovecot-lmtp.log — LMTP delivery when exim delivers mail to dovecot mailboxes
  • /var/log/lfd.log — CSF/LFD events

These files normally have root:root or root:adm permissions, meaning only root can read them.

Root required

Every command in this article must run as root or with sudo. Running as a regular user will give you Permission denied as soon as you try to grep the log files.

Start by checking that all the logs I will use are present.

ls -la /var/log/exim/mainlog \
       /var/log/mail.log \
       /var/log/dovecot-lmtp.log \
       /var/log/lfd.log

Dovecot IMAP / POP failure patterns

An office machine that keeps using an incorrect password normally fails on both sides — SMTP when sending mail (covered in Part 1) and IMAP/POP when fetching mail (covered here) — because the mail client uses the same password to send and receive. Checking both sides together makes the picture much clearer.

What many people do not realize is that POP3 failures often outnumber SMTP failures several times over. The reason is simple — mail clients already poll the inbox every 1 to 5 minutes, and each poll with an incorrect password counts as one failure. SMTP failures happen only when the user clicks Send, so their frequency is very different. This becomes an important clue in the next section.

mail clientSame passwordsend and receiveOn clicking SendPoll every 1-5 mineximSMTP fail on senddovecotIMAP/POP fail each poll/var/log/exim/mainlogauthenticator failed/var/log/mail.logauth failedPOP3/IMAP failures often far exceed SMTP failures — a clue to a stuck client
One client with an incorrect saved password causes failures on both sides: SMTP counts only sends, while IMAP/POP counts every poll.

What a successful login looks like in the log (IMAP)

May 25 10:05:38 mail dovecot: imap-login: Login: user=<[email protected]>, method=PLAIN, rip=203.0.113.x, lip=<server-ip>, mpid=12345, TLS, session=<aBcDefGhIj>

What a failed login looks like in the log (IMAP)

May 25 08:07:19 mail dovecot: imap-login: Disconnected (auth failed, 1 attempts in 5 secs): user=<[email protected]>, method=PLAIN, rip=203.0.113.x, lip=<server-ip>, TLS, session=<aBcDefGhIj>

POP3 uses exactly the same pattern; only imap-login changes to pop3-login.

Find the accounts with the most IMAP failures today.

TODAY=$(date "+%b %e" | sed 's/  / /')          # syslog format "May 25" (ระวัง double-space ถ้าวันที่ < 10)
LOG=/var/log/mail.log

grep "^$TODAY " $LOG \
  | grep 'imap-login: Disconnected (auth failed' \
  | grep -oE 'user=<[^>]+>' | sort | uniq -c | sort -rn | head
The double-space trap

syslog writes the date as "May 5" (with two spaces) when the day is a single digit. The sed command above therefore needs to collapse double spaces into a single space. Skip this step and grep will find no matches on days 1 to 9 of the month.

Find the IPs with the most IMAP failures today.

grep "^$TODAY " $LOG \
  | grep 'imap-login: Disconnected (auth failed' \
  | grep -oE 'rip=[0-9.]+' | sed 's/rip=//' | sort | uniq -c | sort -rn | head

Count today's combined IMAP and POP3 failures for one account.

[email protected]
grep "^$TODAY " /var/log/mail.log \
  | grep -E '(imap-login|pop3-login): Disconnected \(auth failed' \
  | grep -c "user=<$ACCT>"

Cross-protocol check — distinguish a stuck client from an attacker

This is the check I use most often in practice, because it determines whether a case involves "an office machine with an incorrect saved password" or "an external bot trying to guess passwords." These require completely different responses.

The principle is to compare failure counts across protocols for the same account.

[email protected]

echo "-- SMTP (exim) fail --"
grep "set_id=$ACCT" /var/log/exim/mainlog | grep -c 'authenticator failed'

echo "-- IMAP fail --"
grep "user=<$ACCT>" /var/log/mail.log | grep -c 'imap-login: Disconnected (auth failed'

echo "-- POP3 fail --"
grep "user=<$ACCT>" /var/log/mail.log | grep -c 'pop3-login: Disconnected (auth failed'

Here is how I have always interpreted the results.

stuck client

High POP3 : SMTP ratio (10x or more)

  • POP3/IMAP failures outnumber SMTP failures several times over
  • Repeated attempts from the same IP, on the LAN or from the office
  • A desktop client with an incorrect saved password (Outlook / Thunderbird) polling the inbox frequently
  • Fix it at the source — update the password in the application
attacker

Ratio close to 1:1

  • Similar numbers of SMTP and IMAP/POP failures
  • Attempts from multiple scattered IPs or foreign IPs
  • A password-guessing bot, or someone entering an incorrect password in webmail
  • Address it at the perimeter — block IPs, enable brute-force protection, change the password

The key observation is that a stuck client automatically polls the inbox every few minutes, so POP3/IMAP failures climb rapidly while SMTP failures barely move because the user does not send mail very often. An attacker guessing passwords tries each protocol at roughly the same rate, so the counts are similar.

Keep logs for 90 days — adjust DirectAdmin logrotate

This is why so many people find that "I need to look back, but the logs are already gone" — DirectAdmin's default retention is very short. I opened every config and checked: exim and dovecot use weekly + rotate 4, which keeps roughly 28 days, while LFD is worse at rotate 1, keeping only 7 days.

The problem is that in actual investigations, I have had to look back 60 to 80 days to find when the password first became incorrect, because some customers take a month to notice that something is not working. In practice, I therefore aim for at least 90 days to make the logs useful.

Why 90 dayspasswordFirst incorrect on day X->Intermittent accessFor several weeks->Finally reported60-80 days later->Logs already goneWith only 28 days kept

Check the current configuration first.

cat /etc/logrotate.d/exim
cat /etc/logrotate.d/dovecot
cat /etc/logrotate.d/lfd
cat /etc/logrotate.d/rsyslog               # มี /var/log/mail.log อยู่ในนี้
cat /etc/logrotate.conf | grep -E 'rotate|weekly|daily|compress'

The default exim configuration I found on DA-Debian looks roughly like this.

/var/log/exim/mainlog /var/log/exim/processlog /var/log/exim/rejectlog /var/log/exim/paniclog {
    missingok
    sharedscripts
}

There is no rotate N, no compress, and no daily, meaning it uses the defaults from /etc/logrotate.conf: weekly + rotate 4, or 28 days, without compression.

Override exim to 90 days + compress

Edit /etc/logrotate.d/exim.

/var/log/exim/mainlog /var/log/exim/processlog /var/log/exim/rejectlog /var/log/exim/paniclog {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
    sharedscripts
}

Override dovecot

Edit /etc/logrotate.d/dovecot.

/var/log/dovecot*.log {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
    sharedscripts
    postrotate
        kill -s 0 `cat /var/run/dovecot/master.pid` || kill -s USR1 `cat /var/run/dovecot/master.pid`
    endscript
}

Override mail.log (managed by rsyslog)

The /var/log/mail.log file containing dovecot IMAP/POP logs is normally managed in /etc/logrotate.d/rsyslog.

/var/log/mail.log
{
    daily
    rotate 90
    missingok
    notifempty
    compress
    delaycompress
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

Override LFD — the one with a default of just 7 days

This one matters a lot, because DA's default keeps only 7 days, which is too short to investigate any case in time. Edit /etc/logrotate.d/lfd.

/var/log/lfd.log {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
}
/var/log/lfd_messenger.log {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
}

Dry-run before applying

Do not force a rotation yet; always test with a dry-run first.

logrotate -d /etc/logrotate.d/exim           # dry-run ดู debug output ว่าจะทำอะไรบ้าง
logrotate -d /etc/logrotate.d/dovecot
logrotate -d /etc/logrotate.d/lfd
logrotate -d /etc/logrotate.d/rsyslog

If the dry-run reports no errors, the configuration will apply automatically tonight when the daily cron job runs (/etc/cron.daily/logrotate).

Do not force a rotation now

There is no need to run logrotate with force immediately, because it will simply rotate over today's cycle. Let the daily cron job handle it tonight. The new configuration will take effect from the next cycle.

Check disk impact before increasing retention

Increasing retention to 90 days means using more disk space, so check that there is enough first.

ls -lh /var/log/exim/mainlog* /var/log/mail.log* /var/log/dovecot* /var/log/lfd* 2>/dev/null
du -sh /var/log
df -h /var

My medium-sized mail server (around 50 domains and 200 mailboxes) uses roughly 3 to 5 GB for 90 days of logs after gzip compression. If your machine has a separate /var partition, check it carefully, because logs filling the partition and causing rsyslog to crash are difficult to recover from.

If /var has too little space

Set up a postrotate script to copy rotated logs to another disk, such as /backup/maillogs/, and keep only 30 days in /var. This splits retention across disks without losing history.

Query historical rotated logs compressed with gzip

After enabling compress in the previous section, all older files will become .gz files. You can use zgrep directly in place of grep here; it reads both regular and gzip files in a single command.

View an account's IMAP failures across 90 days.

[email protected]
zgrep -h "user=<$ACCT>" /var/log/mail.log* \
  | grep -c 'imap-login: Disconnected (auth failed'

View the IPs from which that account successfully logged in over the past 90 days.

zgrep -h "user=<$ACCT>" /var/log/mail.log* \
  | grep 'imap-login: Login' \
  | grep -oE 'rip=[0-9.]+' | sed 's/rip=//' \
  | sort | uniq -c | sort -rn | head -20

A case I encounter very often is a customer insisting, "My device used to work." Looking back through 60 days of logs shows that it really did log in successfully all along, then suddenly started failing on day X. This confirms that the password was changed (often by someone in the office logging into webmail and changing it themselves), rather than the device breaking.

For SMTP (exim), use zgrep in the same way.

zgrep -h "set_id=$ACCT" /var/log/exim/mainlog* | grep -c 'authenticator failed'

More one-liners

This set builds on the commands in Part 1. Keep them handy to paste in when you need to investigate an urgent case.

Top 10 accounts with IMAP failures today

TODAY=$(date "+%b %e" | sed 's/  / /')
grep "^$TODAY " /var/log/mail.log \
  | grep 'imap-login: Disconnected (auth failed' \
  | grep -oE 'user=<[^>]+>' | sort | uniq -c | sort -rn | head

Top 10 IPs with IMAP failures today

grep "^$TODAY " /var/log/mail.log \
  | grep 'imap-login: Disconnected (auth failed' \
  | grep -oE 'rip=[0-9.]+' | sed 's/rip=//' | sort | uniq -c | sort -rn | head

Find accounts that logged in successfully within 60 days but have been silent for the last 7 days (possibly no longer in use, or the device is missing).

# success ใน 60 วัน (mainlog + rotated)
zgrep -h 'A=[a-z_]*:' /var/log/exim/mainlog* \
  | grep -oE 'A=[a-z_]*:[^ ]+' | sort -u > /home/<user>/all60

# success ใน 7 วันล่าสุด
zgrep -h 'A=[a-z_]*:' /var/log/exim/mainlog{,.[1-7]}* 2>/dev/null \
  | grep -oE 'A=[a-z_]*:[^ ]+' | sort -u > /home/<user>/last7

comm -23 /home/<user>/all60 /home/<user>/last7

Count failures across all protocols for 1 account over 90 days.

[email protected]
echo "-- SMTP (exim) --"
zgrep -h "set_id=$ACCT" /var/log/exim/mainlog* | grep -c 'authenticator failed'
echo "-- IMAP+POP (dovecot) --"
zgrep -h "user=<$ACCT>" /var/log/mail.log* | grep -c 'Disconnected (auth failed'

Extended workflow summary

Everything fits together into one sequence as follows.

workflowMany IMAP/POP failures§2 dovecot pattern->Really a stuck client?§3 cross-protocol ratio->Need to go back 60+ days§4 logrotate 90 + §5 zgrep->Find silent accounts§6 last one-liner
  • Many IMAP/POP failures: check the dovecot pattern in §2
  • Unsure whether it is really a stuck client: compare cross-protocol ratios in §3
  • Need to look back more than 60 days: configure logrotate for 90 in §4, then use zgrep in §5
  • Find inactive or silent accounts: use the last one-liner in §6

For those using postfix instead of exim

If your machine uses postfix instead of DA's exim, the path differs. On CentOS it is /var/log/maillog, while on some Debian setups the entries are mixed into /var/log/mail.log. The format is still syslog, but the messages differ; for example, an authentication failure appears as SASL PLAIN authentication failed. A small regex adjustment to the commands above is enough to use them.

I have been running this setup for almost a year, and it has helped me investigate cases faster, so I wrote this follow-up. If you have better tricks, whether a shorter regex, a script that automatically correlates exim and dovecot, or a dashboard summarizing the results, feel free to share them.

Use whatever suits you — exim or postfix, 30 days or 90 days of retention. The principle is the same: check both sides and keep logs long enough to trace the problem back to where it started.

Want us to set this up?

Get help with server setup, configuration, migration, or troubleshooting. Save time for the work that matters.

Get a quote

Hit something like this? Stuck somewhere?

Come trade notes on the LinuxThai board

→ Continue on the board

Comments 0

No comments yet — be the first