Home / Alt manpages / smtp-sink(1)

  • smtp-sink(1)
  • User command
  • linux

Test an SMTP Client Safely with Postfix smtp-sink

Before you point a new mail client at a real server, test it against smtp-sink, a throwaway listener that speaks SMTP and discards every message. You will run it on a local test port, send it one message, and confirm that the client receives a normal SMTP response while the sink discards the message. You can then capture transactions to files or deliberately exercise client timeouts and rejection paths. Allow 10 to 15 minutes. You need the Postfix package, a shell, and a test client that can connect to the chosen port.

1. Check the installed command

smtp-sink is a Postfix test program, not a mail service configuration tool. The installed version on this machine is Postfix 3.8.6-1ubuntu0.1. Its manual describes this program as unsupported between successive versions, so confirm the local syntax before copying a test into a script.

$ command -v smtp-sink
/usr/sbin/smtp-sink
$ dpkg-query -W -f='${Package} ${Version}\n' postfix
postfix 3.8.6-1ubuntu0.1
$ smtp-sink -? 2>&1 | head -1
smtp-sink: invalid option -- '?'

The last command is only a quick presence check. This version prints its usage text after the invalid option; the useful result is that the executable starts. No elevated privilege is needed for the examples below because they use an unprivileged, high-numbered port.

2. Start a disposable local sink

Choose a port that is free on your machine. Bind explicitly to 127.0.0.1 so other hosts cannot connect. The final argument is the listen backlog, not a message count. Add -c to show counters as sessions and messages finish; stop this foreground test with Ctrl-C after the client has completed.

$ smtp-sink -4 -c 127.0.0.1:25251 5

Leave this terminal running. It normally prints nothing until a client connects. The -4 option restricts this instance to IPv4, while the default without it can accept IPv4 or IPv6 endpoints. If the port is already in use, stop and choose another port rather than killing an unrelated process.

Checkpoint

The sink is listening on loopback port 25251, with a maximum pending connection queue of five. It will remain available until you stop it.

3. Send one test message

From a second terminal, use a client that is already installed. The Postfix smtp-source utility is a convenient choice for a controlled test. Its output and options vary with the installed release, so the example uses only the basic destination, message count and payload-length arguments.

$ command -v smtp-source
/usr/sbin/smtp-source
$ smtp-source -c -m 1 -l 128 127.0.0.1:25251
delivering message 1

The sink accepts the SMTP transaction and throws the message away. There is no delivery mailbox to inspect. The counter in the first terminal should update when the session or message completes. Press Ctrl-C there when you have finished. If your client does not support these smtp-source options, use its own SMTP test mode or connect with a local SMTP library.

If the client reports a connection refusal, check that the sink is still running and that the address and port match. If it hangs, check the client and sink timeout settings before increasing them. The default sink timeout is 100 seconds for receiving a command or sending a response.

4. Capture a transaction instead of discarding it

Use -d when you need one file per message. The template is expanded with strftime(3), then a pseudo-random hexadecimal suffix is added. Use a directory under /tmp for a short-lived test, and create it before starting the sink.

$ capture_dir=$(mktemp -d /tmp/smtp-sink.XXXXXX)
$ smtp-sink -4 -d "$capture_dir/%Y%m%d-%H%M%S." 127.0.0.1:25252 5

Send one message to port 25252 from the second terminal. When the sink exits, inspect the generated file:

$ find "$capture_dir" -type f -maxdepth 1 -print
/tmp/smtp-sink.A1b2C3/20260927-143012.7f3a91c2
$ sed -n '1,18p' "$capture_dir"/*
X-Client-Addr: 127.0.0.1
X-Client-Proto: ESMTP
X-Helo-Args: client.example
X-Mail-Args: FROM:<[email protected]>
X-Rcpt-Args: TO:<[email protected]>
Received: from client.example ([127.0.0.1])
by smtp-sink (smtp-sink) with ESMTP id 7f3a91c2;

The timestamp, random suffix, client arguments and received message differ. The generated headers include the client address and protocol, plus HELO, MAIL and RCPT details when the client supplied them.

Warning

Do not capture real mail: addresses, headers and message bodies may contain personal or confidential data.

5. Add controlled failure conditions

Use command-specific options to test how a client handles SMTP failures. For example, -r RCPT rejects every RCPT command with a soft 4xx response and disables pipelining. This is useful for retry logic, but it is not a realistic production policy by itself.

$ smtp-sink -4 -r RCPT -n 1 127.0.0.1:25253 5

-n 1 stops after one session, even if that session does not complete a message. For a hard failure use -f RCPT. To test a client that should notice a broken connection, -q DATA disconnects without replying after DATA, while -Q DATA sends a 421 reply first. Treat these as test cases: do not point a normal mail queue at them unless you intend to generate retries or failures.

To slow a response, -w 2 waits two seconds before responding to DATA. -W MAIL:2:50 applies a delay to MAIL with the optional random multiplier described by the manual. Keep delays and connection counts small; the point is to observe client behaviour, not to consume the host's file descriptors or worker processes.

6. Stop cleanly and remove test captures

A sink using -M or -n exits on its own when its limit is reached. For an unbounded test, return to the terminal running the sink and press Ctrl-C. If you started a capture in /tmp, inspect it first, then remove only that known temporary directory:

$ find "$capture_dir" -type f -maxdepth 1 -print
$ rm -rf -- "$capture_dir"
$ test ! -e "$capture_dir" && echo 'temporary capture removed'
temporary capture removed

Destructive action

The removal is irreversible. Do not substitute a broad path or a variable whose value you have not checked. If you need the capture for later analysis, copy its files to an approved location before cleanup.

Done means

  • Command confirmed. smtp-sink was confirmed as the installed Postfix 3.8.6 command.
  • Bound to loopback. The sink listened only on a chosen test port, preferably loopback.
  • One transaction completed. A test client completed a message transaction and the sink exited at its configured limit.
  • Capture handled carefully. Any capture used a temporary, known directory and was treated as potentially sensitive.
  • Failure tests bounded. Failure tests used explicit limits and did not point a production mail queue at the sink.
  • Cleanup confirmed. The test process and temporary files are gone, or the remaining capture has a deliberate owner and purpose.