--- title: "How to Test and Troubleshoot a Postfix and Dovecot Server" description: "Test a Postfix and Dovecot mail server end to end: DNS records, SMTP ports, TLS, SASL login, delivery, the mail queue and IMAP, then fix the usual faults." category: "Email Server" language: en source: https://cubepath.com/docs/email-server/email-server-testing-and-troubleshooting updated: 2026-09-25 --- # How to Test and Troubleshoot a Postfix and Dovecot Server A mail server can look healthy on the surface and still fail in ways users only notice later: messages stuck in the queue, mail rejected by Gmail, clients that cannot log in. In this tutorial you will test a Postfix and Dovecot server layer by layer, from DNS to SMTP, TLS, authentication, delivery and IMAP, so you can pinpoint exactly where a problem lives. The commands target Ubuntu 24.04 but work the same on Debian 12. ## Prerequisites To follow this guide you need: - A mail server running Postfix and Dovecot on Ubuntu 24.04, for example a CubePath VPS, with a non-root user with `sudo` privileges. - A domain whose mail you host. This guide uses `example.com` for the domain, `mail.example.com` for the server hostname and `203.0.113.10` for its public IP. Replace them with your own values. - A mailbox you can test with (`user@example.com`) and an external mailbox at another provider, such as Gmail. - A second machine, like your workstation, to run tests from outside the server. ## Step 1 - Installing the testing tools Most checks rely on `dig`, `swaks` (a scriptable SMTP client), `openssl` and `nc`. Install them on the server, and ideally on your workstation too: ```bash sudo apt update sudo apt install dnsutils swaks openssl netcat-openbsd ``` Confirm that `swaks` is available: ```bash swaks --version ``` ```output swaks version 20240103.0 ``` ## Step 2 - Checking DNS records Delivery problems very often start in DNS. Check each record from a public resolver so you see what the rest of the internet sees, not a local cache. Check the MX record, which tells other servers where to deliver mail for your domain: ```bash dig +short MX example.com @1.1.1.1 ``` ```output 10 mail.example.com. ``` The MX target must be a hostname with an A (and optionally AAAA) record, never an IP address or a CNAME: ```bash dig +short A mail.example.com @1.1.1.1 ``` ```output 203.0.113.10 ``` Check the reverse DNS (PTR) record of the server IP. Large providers reject or penalize mail from IPs whose PTR does not resolve back to the sending hostname: ```bash dig +short -x 203.0.113.10 ``` ```output mail.example.com. ``` The PTR value should match Postfix's `myhostname`. Compare them: ```bash postconf myhostname ``` ```output myhostname = mail.example.com ``` Next, check the SPF, DMARC and DKIM TXT records. Replace `default` with the DKIM selector you configured: ```bash dig +short TXT example.com @1.1.1.1 dig +short TXT _dmarc.example.com @1.1.1.1 dig +short TXT default._domainkey.example.com @1.1.1.1 ``` ```output "v=spf1 mx -all" "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com" "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." ``` A domain must have exactly one SPF record. Two `v=spf1` records make SPF fail with a `permerror`. If you use OpenDKIM, it can also check that the published key matches the private key on disk (the tool is in the `opendkim-tools` package): ```bash sudo opendkim-testkey -d example.com -s default -vvv ``` ```output opendkim-testkey: key OK ``` `key not secure` in that output only means the zone is not DNSSEC-signed and is not an error. ## Step 3 - Testing SMTP connectivity Confirm that Postfix and Dovecot listen on the expected ports: ```bash sudo ss -tlnp | grep -E ':(25|465|587|143|993)\s' ``` ```output LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=1234,fd=13)) LISTEN 0 100 0.0.0.0:587 0.0.0.0:* users:(("master",pid=1234,fd=17)) LISTEN 0 100 0.0.0.0:465 0.0.0.0:* users:(("master",pid=1234,fd=21)) LISTEN 0 100 0.0.0.0:993 0.0.0.0:* users:(("dovecot",pid=987,fd=38)) ``` Port 25 receives mail from other servers, 587 (STARTTLS) and 465 (implicit TLS) are for your users' mail clients, and 993 is IMAP over TLS. If a port is missing, check `/etc/postfix/master.cf` for the `submission` and `submissions` services, and the `protocols` setting in Dovecot. Listening locally is not enough: the firewall must allow the traffic too. With UFW: ```bash sudo ufw status ``` ```output Status: active To Action From -- ------ ---- 22/tcp ALLOW Anywhere 25,465,587/tcp ALLOW Anywhere 993/tcp ALLOW Anywhere ``` Now test from your workstation, outside the server. A successful connection proves that both the firewall and the network path are open: ```bash nc -zv mail.example.com 25 nc -zv mail.example.com 587 ``` ```output Connection to mail.example.com (203.0.113.10) 25 port [tcp/smtp] succeeded! Connection to mail.example.com (203.0.113.10) 587 port [tcp/submission] succeeded! ``` > Note: Many residential ISPs block outbound port 25, so the port 25 test can fail from a home connection even if the server is fine. Use an online checker such as MXToolbox or run the test from another server. Finally, check that the server itself can reach other mail servers on port 25. Without this, outgoing mail stays in the queue: ```bash nc -zv -w 5 gmail-smtp-in.l.google.com 25 ``` If this times out, outbound SMTP is blocked by your provider or by an egress firewall rule. Many hosting providers block port 25 on new accounts; open a support request with your provider to have it enabled. ## Step 4 - Checking TLS certificates Mail clients refuse to connect, and other servers may fall back to plain text, when the certificate is expired or does not match the hostname. Retrieve the certificate Postfix offers on the submission port and print its subject and validity dates: ```bash openssl s_client -connect mail.example.com:587 -starttls smtp -servername mail.example.com /dev/null | openssl x509 -noout -subject -issuer -dates ``` ```output subject=CN = mail.example.com issuer=C = US, O = Let's Encrypt, CN = R12 notBefore=Aug 30 08:14:02 2026 GMT notAfter=Nov 28 08:14:01 2026 GMT ``` Repeat the check for the implicit TLS ports, which do not need `-starttls`: ```bash openssl s_client -connect mail.example.com:465 -servername mail.example.com /dev/null | openssl x509 -noout -subject -dates openssl s_client -connect mail.example.com:993 -servername mail.example.com /dev/null | openssl x509 -noout -subject -dates ``` To confirm the full chain validates, look for the verification result: ```bash openssl s_client -connect mail.example.com:993 -servername mail.example.com /dev/null | grep 'Verify return code' ``` ```output Verify return code: 0 (ok) ``` Any other code, such as `21 (unable to verify the first certificate)`, usually means the configuration points to the leaf certificate instead of the full chain. With Let's Encrypt, use `fullchain.pem` in both `smtpd_tls_cert_file` (Postfix) and `ssl_cert` (Dovecot). ## Step 5 - Testing SMTP authentication Postfix delegates authentication to Dovecot through a socket. Test the layers from the bottom up. First, ask Dovecot directly whether the credentials are valid: ```bash sudo doveadm auth test user@example.com ``` Enter the password when prompted: ```output passdb: user@example.com auth succeeded extra fields: user=user@example.com ``` If this fails, the problem is in Dovecot's user database, not in Postfix. If it succeeds, check that the socket Postfix uses exists: ```bash sudo ls -l /var/spool/postfix/private/auth ``` ```output srw-rw---- 1 postfix postfix 0 Sep 25 09:00 /var/spool/postfix/private/auth ``` Then test an authenticated submission exactly like a mail client would, over STARTTLS on port 587. Run this from your workstation, with a real recipient at an external provider: ```bash swaks --server mail.example.com --port 587 --tls \ --auth LOGIN --auth-user user@example.com \ --from user@example.com --to you@gmail.com \ --header "Subject: swaks submission test" ``` swaks prompts for the password and prints the whole SMTP conversation. The lines that matter are: ```output <~ 235 2.7.0 Authentication successful ~> MAIL FROM: <~ 250 2.1.0 Ok ~> RCPT TO: <~ 250 2.1.5 Ok <~ 250 2.0.0 Ok: queued as 4C7D21A0F3 ``` A `535 5.7.8 Authentication failed` here, with `doveadm auth test` succeeding, points to the Postfix side: confirm that the submission service enables SASL: ```bash sudo postconf -P 'submission/inet/smtpd_sasl_auth_enable' 'submission/inet/smtpd_tls_security_level' ``` ```output submission/inet/smtpd_sasl_auth_enable = yes submission/inet/smtpd_tls_security_level = encrypt ``` If no output appears, those options are not set on the submission service in `/etc/postfix/master.cf`, and the main settings in `main.cf` apply instead. ## Step 6 - Testing inbound delivery Send a message to your own domain from outside, without authentication, the way another mail server would. Run this from your workstation or a different server: ```bash swaks --server mail.example.com --port 25 \ --from tester@gmail.com --to user@example.com \ --header "Subject: swaks inbound test" ``` ```output <~ 250 2.0.0 Ok: queued as 7E2B41A0F9 ``` Also confirm the server is not an open relay. An unauthenticated attempt to send to an external domain must be refused: ```bash swaks --server mail.example.com --port 25 \ --from tester@gmail.com --to someone@outlook.com ``` ```output <** 554 5.7.1 : Relay access denied ``` If this message is accepted, fix `smtpd_relay_restrictions` immediately; spammers find open relays within hours. ## Step 7 - Inspecting and managing the mail queue Messages that cannot be delivered right away wait in the queue. List it: ```bash sudo postqueue -p ``` ```output -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient------- 9A1F2B3C4D* 1523 Fri Sep 25 09:41:12 user@example.com you@gmail.com -- 1 Kbytes in 1 Request. ``` An asterisk after the ID means the message is being delivered now; an exclamation mark means it is on hold. For deferred messages, Postfix shows the last error in parentheses under the sender, which is usually enough to identify the problem. To see a message's headers and content: ```bash sudo postcat -q 9A1F2B3C4D | less ``` Once you have fixed the cause, ask Postfix to retry all deferred messages now instead of waiting for the next retry interval: ```bash sudo postqueue -f ``` To delete a single message, or everything in the deferred queue (for example backscatter after a spam incident): ```bash sudo postsuper -d 9A1F2B3C4D sudo postsuper -d ALL deferred ``` > Warning: `postsuper -d ALL` without a queue name deletes every queued message, including legitimate mail waiting to be delivered. ## Step 8 - Testing IMAP access Connect to Dovecot over TLS and log in manually. This isolates server problems from mail client configuration: ```bash openssl s_client -connect mail.example.com:993 -servername mail.example.com -quiet ``` After the `* OK [CAPABILITY ...] Dovecot ready.` greeting, type these commands one at a time. Each starts with an arbitrary tag: ```text a1 LOGIN user@example.com your_password a2 SELECT INBOX a3 LOGOUT ``` ```output a1 OK [CAPABILITY IMAP4rev1 ...] Logged in * 3 EXISTS a2 OK [READ-WRITE] Select completed (0.001 + 0.000 secs). * BYE Logging out ``` `* 3 EXISTS` shows how many messages the inbox holds; it should include the test message from Step 6. The password stays in your terminal scrollback, so use a test mailbox or clear the terminal afterwards. ## Step 9 - Checking deliverability and authentication results Send a message from your server to an external mailbox you control, then open the raw headers. In Gmail, open the message and choose **Show original**. You should see: ```text SPF: PASS with IP 203.0.113.10 DKIM: 'PASS' with domain example.com DMARC: 'PASS' ``` For a scored report, send a message to the address shown on mail-tester.com and open the result page. It checks SPF, DKIM, DMARC, reverse DNS, blocklists and content in one go. ## Step 10 - Reading the logs Every failure in the previous steps leaves a trace in the logs. On Ubuntu, Postfix and Dovecot log to `/var/log/mail.log`. Follow it while you repeat a failing test: ```bash sudo tail -f /var/log/mail.log ``` To see everything Postfix logged about one message, search for its queue ID: ```bash sudo grep 9A1F2B3C4D /var/log/mail.log ``` ```output 2026-09-25T09:41:12.318201+00:00 mail postfix/submission/smtpd[20114]: 9A1F2B3C4D: client=unknown[198.51.100.7], sasl_method=LOGIN, sasl_username=user@example.com 2026-09-25T09:41:12.402117+00:00 mail postfix/qmgr[1402]: 9A1F2B3C4D: from=, size=1523, nrcpt=1 (queue active) 2026-09-25T09:41:13.771954+00:00 mail postfix/smtp[20120]: 9A1F2B3C4D: to=, 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 ``` `status=sent` means the receiving server accepted the message. For a full walkthrough of log formats and useful search patterns, see the email logs analysis guide. ## Troubleshooting **Outgoing mail stays in the queue with `Connection timed out`**: outbound port 25 is blocked. Confirm with the `nc` test in Step 3 and ask your provider to enable outbound SMTP. **Gmail or Outlook rejects mail with `550 5.7.1` or a message about PTR or authentication**: check the PTR record, SPF and DKIM from Step 2. The PTR must resolve to your hostname and that hostname must resolve back to the same IP. **Incoming mail never arrives, but the queue is empty**: the sending server cannot reach you. Check the MX record with `dig`, confirm port 25 is open from outside, and look in `/var/log/mail.log` for `NOQUEUE: reject` lines showing why a message was refused. **Clients get `Authentication failed` but `doveadm auth test` works**: the client is connecting to port 25 instead of 587 or 465, or sends a different username format (for example `user` instead of `user@example.com`) than the one Dovecot expects. **Mail client warns about the certificate**: the hostname in the client must match the certificate subject (for example `mail.example.com`, not `example.com`), and the server must present the full chain. Recheck Step 4. **Postfix refuses to start after a change**: run `sudo postfix check` to validate the configuration and `sudo journalctl -u postfix@- -n 50` to read the startup error. ## Conclusion You have tested every layer of the mail server: DNS, network reachability, TLS, SASL authentication, inbound and outbound delivery, the queue and IMAP access. Working through the layers in this order lets you narrow down a fault quickly instead of guessing. As next steps, you can: - Learn to read and search the mail logs in depth to track individual messages and spot abuse. - Set up DMARC aggregate reports (`rua`) to see who is sending mail on behalf of your domain. - Add Fail2ban jails for Postfix SASL and Dovecot to block password guessing.