Mail Services Testing

Posted on 17 2026

A mail server has many moving parts. Postfix, Dovecot, rspamd, DNS records, TLS certificates, DKIM signing, and the PostfixAdmin database all have to work together correctly. Testing each component in isolation, then testing end-to-end delivery, gives confidence that the whole system is working before you rely on it for real mail.

This page works through the tests in order: local delivery first, then SMTP, then IMAP, then TLS, then authentication, then external deliverability. Run each section after initial setup and repeat after any significant configuration change.

Prerequisites

Install the testing tools on the desktop or the mail server container:

sudo apt install -y \
    swaks \
    openssl \
    dnsutils \
    netcat-openbsd \
    mailutils

swaks (Swiss Army Knife SMTP) is the most useful single tool for mail server testing. It handles TLS, authentication, and full SMTP session testing from a single command.

Local delivery test

The simplest test: send a message via the local mail command and verify it arrives.

From the mail server container:

echo "Test message body" | mail -s "Local delivery test" you@yourdomain.net

Check the Postfix log immediately:

sudo journalctl -u postfix -f --since "1 minute ago"

Look for status=sent in the output. If you see status=deferred, the log line will show the reason.

What-if delivery simulation

Test what Postfix would do with a message without actually sending it:

# Show delivery path for an address
/usr/sbin/sendmail -bv you@yourdomain.net

# Show what would happen for an external address
/usr/sbin/sendmail -bv recipient@external.example.com

This reveals routing decisions, virtual alias mappings, and transport selections without sending anything.

SMTP submission testing with swaks

swaks sends complete SMTP sessions and reports every step. It is the definitive tool for testing the submission port.

Basic submission test

swaks \
    --to you@yourdomain.net \
    --from you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 587 \
    --tls \
    --auth-user you@yourdomain.net \
    --auth-password yourpassword \
    --header "Subject: swaks submission test" \
    --body "Testing SMTP submission via swaks"

A successful test shows 250 2.0.0 Ok: queued at the end. Any earlier failure is reported clearly with the SMTP response code and message.

Test without TLS (should be rejected)

The submission port should require TLS and reject plaintext connections:

swaks \
    --to you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 587 \
    --no-tls

This should fail with a rejection message. If it succeeds, the submission port is not enforcing TLS.

Test SMTP (port 25) relay rejection

Port 25 should accept inbound mail from external servers but reject relay attempts from unauthenticated clients:

# This should be rejected - attempting to relay without authentication
swaks \
    --to external@example.com \
    --from you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 25 \
    --no-tls

Expected response: 554 5.7.1 Relay access denied or similar. If this succeeds, the server is an open relay.

Raw SMTP session testing

For testing specific SMTP interactions manually with OpenSSL:

Test submission with STARTTLS

openssl s_client -starttls smtp -connect mail.yourdomain.net:587 -quiet

After the TLS handshake, you will see the SMTP banner. Send SMTP commands manually:

EHLO test.example.com

The server should respond with its capabilities including AUTH PLAIN LOGIN.

Encode credentials for AUTH PLAIN

Auth PLAIN sends username and password in a single base64-encoded string. The format is \0username\0password:

# Note the leading space before echo to avoid saving the password in history
 echo -ne '\0you@yourdomain.net\0yourpassword' | base64 -w0 ; echo

Use the output in the SMTP session:

AUTH PLAIN <base64-output-here>

Expected response: 235 2.7.0 Authentication successful

Encode credentials for AUTH LOGIN

Auth LOGIN sends username and password separately as base64:

 echo -ne 'you@yourdomain.net' | base64 -w0 ; echo
 echo -ne 'yourpassword' | base64 -w0 ; echo

In the SMTP session:

AUTH LOGIN
334 VXNlcm5hbWU6
<base64 username here>
334 UGFzc3dvcmQ6
<base64 password here>

Send a complete test message via raw SMTP

EHLO test.yourdomain.net
AUTH PLAIN <base64-credentials>
MAIL FROM:<you@yourdomain.net>
RCPT TO:<you@yourdomain.net>
DATA
Message-ID: <test-$(date +%s)@yourdomain.net>
Date: $(date -R)
MIME-Version: 1.0
Subject: Raw SMTP test
To: You <you@yourdomain.net>
From: You <you@yourdomain.net>

This is a raw SMTP test message.
.
QUIT

TLS certificate verification

Verify the TLS certificate presented by the mail server:

# Check SMTP STARTTLS certificate (submission port)
openssl s_client -starttls smtp -connect mail.yourdomain.net:587 \
    -servername mail.yourdomain.net 2>/dev/null | \
    openssl x509 -noout -dates -subject -issuer

# Check IMAPS certificate
openssl s_client -connect mail.yourdomain.net:993 \
    -servername mail.yourdomain.net 2>/dev/null | \
    openssl x509 -noout -dates -subject -issuer

Verify the certificate is valid, has the correct subject name, and is not expiring soon.

Check TLS cipher suite

# Show the negotiated cipher
openssl s_client -starttls smtp -connect mail.yourdomain.net:587 \
    -brief 2>/dev/null | grep "Protocol\|Cipher"

The result should show TLS 1.3 or TLS 1.2 and a strong cipher such as TLS_AES_256_GCM_SHA384 or ECDHE-RSA-AES256-GCM-SHA384.

IMAP testing with swaks and openssl

Test that Dovecot accepts IMAP connections and authenticates correctly:

# Test IMAPS connection
openssl s_client -connect mail.yourdomain.net:993 -quiet

# After connecting, you should see the IMAP greeting:
# * OK [CAPABILITY ...] Dovecot ready.

# Login manually:
. LOGIN you@yourdomain.net yourpassword

# List mailboxes:
. LIST "" "*"

# Logout:
. LOGOUT

Test with swaks over IMAP (submission path)

The easiest IMAP test from the desktop is simply configuring Evolution or a test mail client with the server details and confirming the INBOX loads. But for command-line testing from the server or over SSH:

# Test IMAP authentication and capability
openssl s_client -connect mail.yourdomain.net:993 2>/dev/null | head -5

DKIM signature verification

Send a message to an external service that reports DKIM results:

# Send to a test address that reports authentication results
swaks \
    --to check-auth@verifier.port25.com \
    --from you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 587 \
    --tls \
    --auth-user you@yourdomain.net \
    --auth-password yourpassword \
    --header "Subject: DKIM verification test"

The Port25 verifier replies to you@yourdomain.net with a report showing whether SPF, DKIM, and DMARC passed.

Check DKIM locally

Verify the DKIM key is published in DNS:

dig TXT 2026-01._domainkey.yourdomain.net +short

Check whether outgoing messages are being signed:

# Send a test message and check the log for DKIM signing
swaks --to you@yourdomain.net --from you@yourdomain.net \
    --server mail.yourdomain.net --port 587 --tls \
    --auth-user you@yourdomain.net --auth-password yourpassword

# Check the log for DKIM signature
sudo journalctl -u rspamd --since "1 minute ago" | grep -i dkim

Spam filter testing

Test that rspamd is processing messages and not blocking legitimate mail.

Send a test message with the GTUBE spam test string

The GTUBE string triggers spam filters the same way EICAR triggers antivirus. It should be detected as spam:

swaks \
    --to you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 25 \
    --data - << 'EOF'
Subject: Spam filter test
From: test@example.com
To: you@yourdomain.net

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
EOF

The GTUBE string should cause rspamd to reject or quarantine this message. Check the rspamd log:

sudo journalctl -u rspamd --since "1 minute ago"

Check rspamd statistics

# rspamd statistics (if rspamd is running)
rspamc stat

Test spam scoring via mail-tester.com

The source material links to https://www.mail-tester.com/. This site is still the most comprehensive external spam score test available. It provides a unique test address: send a real message to that address from your mail server and the site reports:

  • SPF, DKIM, DMARC results
  • Spam filter scores
  • Blacklist status
  • Content analysis
  • HTML/text ratio
  • Link reputation
# Get a test address from mail-tester.com, then send:
swaks \
    --to test-xxxxxxxx@mail-tester.com \
    --from you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 587 \
    --tls \
    --auth-user you@yourdomain.net \
    --auth-password yourpassword \
    --header "Subject: Mail server test" \
    --body "This is a test message from my self-hosted mail server."

A score of 9 or 10 out of 10 indicates a well-configured server. Anything below 8 suggests something needs attention.

End-to-end delivery test

Send a message from your server to an external address and verify delivery:

# Send to a Gmail or Outlook address you control
swaks \
    --to youraddress@gmail.com \
    --from you@yourdomain.net \
    --server mail.yourdomain.net \
    --port 587 \
    --tls \
    --auth-user you@yourdomain.net \
    --auth-password yourpassword \
    --header "Subject: End-to-end delivery test" \
    --body "Testing outbound delivery from $(hostname -f)"

Check:

  • The message arrives in the inbox (not spam)
  • The sender address shows correctly
  • The message headers show dkim=pass and spf=pass in the Authentication-Results header

Receiving test

Send a message from an external address (Gmail, Outlook, or similar) to you@yourdomain.net. Verify:

  • The message arrives in the inbox
  • The Postfix log shows status=sent for the delivery to Dovecot
  • The message appears in Evolution or SnappyMail

Postfix log reference

The journalctl command for Postfix logs uses the correct spelling (the source material has a typo journalctrl):

# Follow Postfix logs in real time
sudo journalctl -t postfix -f

# Specific Postfix processes
sudo journalctl -t postfix/smtpd -f      # Inbound SMTP daemon
sudo journalctl -t postfix/smtp -f       # Outbound SMTP client
sudo journalctl -t postfix/submission/smtpd -f  # Submission daemon
sudo journalctl -t postfix/qmgr -f       # Queue manager
sudo journalctl -t postfix/lmtp -f       # Local delivery to Dovecot

# All mail-related logs
sudo journalctl -u postfix -u dovecot -u rspamd -f

Test checklist

Run through this checklist after initial setup and after any significant change:

TestCommandExpected result
Local deliveryecho test | mail -s test you@yourdomain.netstatus=sent in log
Submission TLSswaks --port 587 --tls --auth-user ...250 2.0.0 Ok
Submission no-TLSswaks --port 587 --no-tlsConnection rejected
Open relay checkswaks --to external@example.com --port 25554 Relay denied
IMAPS connectionopenssl s_client -connect mail.yourdomain.net:993OK Dovecot ready
TLS certificateopenssl x509 -noout -datesValid, not expired
DKIM DNS recorddig TXT 2026-01._domainkey.yourdomain.netKey returned
DKIM signingPort25 verifierdkim=pass
SPFPort25 verifierspf=pass
DMARCPort25 verifierdmarc=pass
Spam filterGTUBE testMessage rejected or quarantined
Spam scoremail-tester.comScore 9-10/10
Outbound deliverySend to Gmail/OutlookArrives in inbox, not spam
Inbound deliverySend from Gmail/OutlookArrives in mailbox

After making any change to Postfix or Dovecot configuration, always test authentication before logging out of your current session. A misconfigured authentication setup that locks you out of the submission port is frustrating to recover from. Test first, log out after.