The mail log is the first place to look when a message goes missing, a user cannot log in or someone is abusing your server. Postfix and Dovecot record every connection, delivery attempt and login, and with a few grep patterns you can answer most questions in seconds. In this tutorial you will learn where the logs live on Ubuntu 24.04, how to read a Postfix log line, how to trace a single message, how to find bounces, deferrals and authentication failures, and how to get a daily summary with pflogsumm.

Prerequisites

To follow this guide you need:

  • A mail server running Postfix and Dovecot on Ubuntu 24.04 (Debian 12 works the same), for example a CubePath VPS.
  • A non-root user with sudo privileges. The mail log is readable only by root and the adm group.
  • Some mail traffic in the logs, so the commands return results.

Step 1 - Finding the log files

On Ubuntu, Postfix and Dovecot send their messages to syslog with the mail facility, and rsyslog writes them to /var/log/mail.log. List the current and rotated files:

ls -lh /var/log/mail.log*
-rw-r----- 1 syslog adm 2.1M Sep 25 10:02 /var/log/mail.log
-rw-r----- 1 syslog adm 5.8M Sep 21 00:00 /var/log/mail.log.1
-rw-r----- 1 syslog adm 612K Sep 14 00:00 /var/log/mail.log.2.gz
-rw-r----- 1 syslog adm 598K Sep  7 00:00 /var/log/mail.log.3.gz

The most recent rotated file stays uncompressed and older ones are gzipped. To read the logs without sudo, add your user to the adm group and open a new session:

sudo usermod -aG adm $USER

The same messages are also in the systemd journal. That is useful for time ranges, because journalctl understands dates directly. Postfix processes run under the postfix@- unit on Ubuntu:

sudo journalctl -u postfix@- --since "1 hour ago"
sudo journalctl -u dovecot --since today

If /var/log/mail.log does not exist, rsyslog is not installed. Install it with sudo apt install rsyslog or work only with journalctl.

Step 2 - Understanding a Postfix log line

Every message Postfix handles receives a queue ID, and each Postfix process that touches the message logs a line with that ID. A normal outbound delivery looks like this:

2026-09-25T09:41:12.318201+00:00 mail postfix/submission/smtpd[20114]: 9A1F2B3C4D: client=unknown[198.51.100.7], sasl_method=LOGIN, [email protected]
2026-09-25T09:41:12.360044+00:00 mail postfix/cleanup[20118]: 9A1F2B3C4D: message-id=<[email protected]>
2026-09-25T09:41:12.402117+00:00 mail postfix/qmgr[1402]: 9A1F2B3C4D: from=<[email protected]>, size=1523, nrcpt=1 (queue active)
2026-09-25T09:41:13.771954+00:00 mail postfix/smtp[20120]: 9A1F2B3C4D: to=<[email protected]>, relay=gmail-smtp-in.l.google.com[142.250.27.26]:25, delay=1.5, delays=0.08/0.01/0.62/0.78, dsn=2.0.0, status=sent (250 2.0.0 OK)
2026-09-25T09:41:13.772512+00:00 mail postfix/qmgr[1402]: 9A1F2B3C4D: removed

Each line contains a timestamp, the hostname, the Postfix process with its PID, the queue ID and the details. Ubuntu 24.04 uses RFC 3339 timestamps; older releases use the Sep 25 09:41:12 format, so the commands in this guide avoid relying on field positions.

The processes tell the story of the message:

ProcessWhat it logs
smtpdIncoming SMTP connection, client IP, SASL user, rejections (NOQUEUE: reject)
cleanupMessage-ID of the accepted message
qmgrSender, size and number of recipients; removed when finished
smtpDelivery to a remote server
lmtp or local / virtualDelivery to a local mailbox

The important fields in the delivery line are:

  • status: sent (accepted by the next server), deferred (temporary failure, Postfix will retry), bounced (permanent failure, a bounce was sent to the sender).
  • dsn: the delivery status code. 2.x.x is success, 4.x.x temporary, 5.x.x permanent.
  • delays=a/b/c/d: seconds spent before the queue manager, in the queue manager, setting up the connection, and transmitting. A large third value points to DNS or network problems at the receiving side.
  • The text in parentheses at the end: the exact reply from the remote server, which usually explains a failure.

Step 3 - Tracing a single message

Users typically report "my message to X never arrived". Start by finding the queue IDs of messages to that recipient. This prints the ID of every delivery attempt to [email protected]:

sudo grep -oP '[0-9A-F]{6,}(?=: to=<alice@example\.net>)' /var/log/mail.log | sort -u
3B7C90A1E2
9A1F2B3C4D

Then print every line for one of those IDs to see the full life of the message:

sudo grep 9A1F2B3C4D /var/log/mail.log

If the message is older, search the rotated files as well. zgrep reads plain and gzipped files alike:

sudo zgrep 9A1F2B3C4D /var/log/mail.log*

When the sender gives you the Message-ID from their mail client, search for it instead. It is logged by cleanup together with the queue ID:

sudo grep 'message-id=<[email protected]>' /var/log/mail.log

Note that a message passing through a content filter (such as Amavis or rspamd in proxy mode) gets a new queue ID when it is re-injected. Follow the queued as text in the delivery line to the next ID.

Step 4 - Finding bounced and deferred mail

List permanent failures with the remote server's explanation:

sudo grep 'status=bounced' /var/log/mail.log | tail -n 20
2026-09-25T08:12:40.118822+00:00 mail postfix/smtp[18833]: 5D2E71A0C4: to=<[email protected]>, relay=mx.example.org[192.0.2.25]:25, delay=0.9, delays=0.05/0/0.4/0.45, dsn=5.1.1, status=bounced (host mx.example.org[192.0.2.25] said: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown (in reply to RCPT TO command))

Count bounces by status code to see which kind of failure dominates:

sudo grep 'status=bounced' /var/log/mail.log | grep -oP 'dsn=\K[0-9.]+' | sort | uniq -c | sort -rn
     14 5.1.1
      3 5.7.1
      1 5.4.4

5.1.1 means the mailbox does not exist, 5.7.1 is a policy rejection (often SPF, DKIM, reputation or a blocklist) and 5.4.4 means the domain has no valid MX.

Deferred messages are the ones currently stuck. Group them by recipient domain to see whether one provider is the problem:

sudo grep 'status=deferred' /var/log/mail.log | grep -oP 'to=<[^@]+@\K[^>]+' | sort | uniq -c | sort -rn | head
     42 outlook.com
      3 example.org

Then read the reason for that domain:

sudo grep 'status=deferred' /var/log/mail.log | grep 'outlook.com' | tail -n 3

A reason like Connection timed out to every domain means outbound port 25 is blocked; a reply like 451 4.7.650 ... temporarily rate limited due to IP reputation means the receiving provider is throttling your IP.

Step 5 - Finding rejected connections

When Postfix refuses a message during the SMTP conversation, it logs a NOQUEUE: reject line; no queue ID is assigned because the message was never accepted:

sudo grep 'NOQUEUE: reject' /var/log/mail.log | tail -n 5
2026-09-25T09:58:02.556180+00:00 mail postfix/smtpd[20511]: NOQUEUE: reject: RCPT from unknown[192.0.2.77]: 554 5.7.1 <[email protected]>: Relay access denied; from=<[email protected]> to=<[email protected]> proto=ESMTP helo=<example.biz>

Summarize rejections by SMTP code:

sudo grep -oP 'NOQUEUE: reject: RCPT from \S+ \K[45]\d\d [45]\.\d+\.\d+' /var/log/mail.log | sort | uniq -c | sort -rn
    118 554 5.7.1
     37 450 4.7.1
      9 550 5.1.1

Relay denials from random IPs are normal internet noise. If a legitimate sender reports being rejected, search for their IP or address to read the exact reason.

Step 6 - Finding authentication failures

Failed SMTP logins are logged by Postfix as SASL warnings:

sudo grep 'SASL .* authentication failed' /var/log/mail.log | tail -n 3
2026-09-25T10:01:44.902113+00:00 mail postfix/submission/smtpd[20702]: warning: unknown[198.51.100.200]: SASL LOGIN authentication failed: UGFzc3dvcmQ6

The base64 string at the end is not the password; it decodes to Password:, the server's prompt. Count failures per source IP to spot brute force attempts:

sudo grep 'SASL .* authentication failed' /var/log/mail.log | grep -oP 'warning: \S+\[\K[0-9a-f.:]+' | sort | uniq -c | sort -rn | head
    512 198.51.100.200
     37 203.0.113.99
      2 192.0.2.14

Hundreds of failures from a single IP is a password-guessing attack. Block it with a firewall rule or, better, set up Fail2ban with the postfix-sasl jail.

Dovecot logs failed IMAP and POP3 logins when the client disconnects. The exact wording differs slightly between Dovecot versions, but it always contains auth failed:

sudo grep 'auth failed' /var/log/mail.log | grep dovecot | tail -n 3
2026-09-25T10:03:10.004511+00:00 mail dovecot: imap-login: Login aborted: Connection closed (auth failed, 1 attempts in 2 secs) (auth_failed): user=<[email protected]>, method=PLAIN, rip=203.0.113.99, lip=203.0.113.10, TLS, session=<k3v2PQ8KdMzLqMVj>

And successful logins, which are useful to confirm when a user last connected and from where:

sudo grep 'Login: user=<[email protected]>' /var/log/mail.log | tail -n 5

A single user failing repeatedly from their usual IP usually has an old password saved on a phone or a second device.

Step 7 - Measuring volume and delays

Count deliveries by status in the current log file:

sudo grep -oP 'status=\K\w+' /var/log/mail.log | sort | uniq -c
   1893 sent
     42 deferred
     18 bounced

This includes local deliveries to mailboxes, not only outbound mail. To see who sends the most messages through the server, which quickly reveals a compromised account sending spam:

sudo grep -oP 'qmgr\[\d+\]: [0-9A-F]+: from=<\K[^>]+' /var/log/mail.log | sort | uniq -c | sort -rn | head

Calculate the average and maximum delivery delay of successful deliveries:

sudo grep 'status=sent' /var/log/mail.log | grep -oP ', delay=\K[0-9.]+' | awk '{ s += $1; if ($1 > m) m = $1 } END { if (NR) printf "messages=%d avg=%.2fs max=%.2fs\n", NR, s/NR, m }'
messages=1893 avg=0.84s max=312.40s

A high maximum on its own is normal (a message that was deferred and retried). A high average points to slow DNS or a slow content filter.

Step 8 - Getting a daily report with pflogsumm

Rather than writing your own reporting script, use pflogsumm, which is packaged in Ubuntu and summarizes volume, bounces, rejections, top senders and recipients:

sudo apt install pflogsumm

pflogsumm expects classic syslog timestamps (Sep 25 09:41:12), while Ubuntu 24.04 writes RFC 3339 timestamps to /var/log/mail.log. The reliable way to feed it is the journal, whose default short output uses the classic format. Generate a report for today:

sudo journalctl -u postfix@- --since today -o short --no-pager | pflogsumm
Grand Totals
------------
messages

   1204   received
   1893   delivered
     42   deferred  (118  deferrals)
     18   bounced
    164   rejected (8%)
...

To receive yesterday's summary by email every morning, create a cron file:

sudo nano /etc/cron.d/pflogsumm
15 6 * * * root { echo 'Subject: Postfix daily report'; echo; journalctl -u postfix@- --since yesterday --until today -o short --no-pager | /usr/sbin/pflogsumm; } | /usr/sbin/sendmail [email protected]

Replace [email protected] with your address. The first echo adds a subject header, and sendmail here is Postfix's compatible command, so no extra mail client is needed. Because the journal is queried by date, log rotation does not cut the report in half. Test the pipeline once by hand before relying on it:

sudo sh -c '{ echo "Subject: Postfix report test"; echo; journalctl -u postfix@- --since today -o short --no-pager | /usr/sbin/pflogsumm; } | /usr/sbin/sendmail [email protected]'

The report should arrive in your mailbox within a minute. If the totals are all zero, check that journalctl -u postfix@- --since today prints Postfix lines at all.

Step 9 - Getting more detail when you need it

When the normal logs do not explain a problem, raise verbosity temporarily. For Dovecot authentication issues, edit the logging configuration:

sudo nano /etc/dovecot/conf.d/10-logging.conf
auth_verbose = yes
auth_debug = yes

Reload Dovecot and repeat the failing login:

sudo systemctl reload dovecot

For Postfix, enable debug logging only for the client IP you are investigating, so the log does not explode:

sudo postconf -e 'debug_peer_list = 198.51.100.7'
sudo systemctl reload postfix

Step 10 - Adjusting log retention

On Ubuntu, /var/log/mail.log is rotated by the rsyslog logrotate policy in /etc/logrotate.d/rsyslog: weekly, keeping four old files. If you need a longer history, for example for abuse investigations, change rotate for the mail files. Open the file:

sudo nano /etc/logrotate.d/rsyslog

The mail logs share a block with other files. Increasing rotate 4 to rotate 12 keeps about three months of history. Check the result without rotating anything:

sudo logrotate -d /etc/logrotate.d/rsyslog

Mail logs contain email addresses and IP addresses, which are personal data under the GDPR. Keep them only as long as you actually need them and do not make them readable to more users than necessary.

Conclusion

You now know where Postfix and Dovecot log on Ubuntu 24.04, how to read a delivery line, how to trace a message by queue ID and how to find bounces, deferrals, rejections and login attacks with a handful of grep patterns. pflogsumm gives you a daily overview without maintaining your own scripts.

As next steps, you can:

  • Protect SMTP and IMAP logins with Fail2ban using the postfix-sasl and dovecot jails.
  • Ship the logs to a central system such as Loki or Graylog if you run more than one mail server.
  • Review the testing and troubleshooting guide to check DNS, TLS and authentication when the logs point to a configuration problem.