Home / Alt manpages / discard(8postfix)

  • discard(8postfix)
  • Postfix admin command
  • linux

Discard Selected Postfix Mail Safely with discard(8)

A retired test domain keeps generating mail you never want to see, and bouncing it only makes more noise. You will route mail for one chosen destination through Postfix's discard delivery agent: Postfix accepts the message into its queue, records the destination as the reason, marks the matching recipients delivered, and sends it nowhere. That suits a test domain or a retired internal destination you are deliberately suppressing.

  • Time: about 15 minutes for the configuration and a controlled test.
  • You need: a working Postfix installation, root access for files under /etc/postfix, and a destination you are certain may be discarded.
  • Checked against: Postfix 3.8.6-1ubuntu0.1.

1. Check the installed discard service

discard(8) is a Postfix delivery daemon, not a command you run by hand. The queue manager sends it delivery requests through the service definition in master.cf. The daemon speaks that internal protocol, so running the binary directly tells you nothing.

$ postconf -M discard
discard    unix  -       -       y       -       -       discard
$ postconf -h transport_maps
$ dpkg-query -W -f='${Version}\n' postfix
3.8.6-1ubuntu0.1

Checkpoint

The exact spacing can differ. What matters is that the first line names the discard service and ends with the discard daemon. An empty transport_maps value means no transport table is configured yet.

2. Choose a narrow destination

Transport rules match by address, domain or subdomain. Start with a domain you control, such as discard-test.example. A bare domain entry matches that domain. Add a second entry beginning with a dot if its subdomains should be discarded too.

Warning

Do not use a wildcard while you are learning this feature. A rule for * can discard mail for every destination that reaches the transport table, which is a service-wide data-loss event.

Warning

The commands below create /etc/postfix/transport from scratch and overwrite any file already there. If you already have one, back it up and add the two lines by hand instead.

$ sudo install -o root -g root -m 0644 /dev/null /etc/postfix/transport
$ sudo sh -c 'cat > /etc/postfix/transport' <<'EOF'
discard-test.example discard:
.discard-test.example discard:
EOF
$ sudo postmap /etc/postfix/transport
$ postmap -q discard-test.example hash:/etc/postfix/transport
discard:
$ postmap -q [email protected] hash:/etc/postfix/transport
discard:

Checkpoint

The first query confirms the domain rule. If you added the dotted rule, query an address in a subdomain too. No output means that lookup did not match.

3. Enable the transport table

Before changing Postfix, record the current setting. If it already holds another transport map, keep it and add the new map to the existing comma-separated list. Replacing an existing value can silently change unrelated mail routing.

$ postconf -h transport_maps
$ sudo postconf -e 'transport_maps = hash:/etc/postfix/transport'
$ postconf -h transport_maps
hash:/etc/postfix/transport

That command is safe only when the earlier value was empty. If it printed an existing map, edit main.cf deliberately, or set a combined value such as hash:/etc/postfix/other, hash:/etc/postfix/transport, keeping the established order. Check the syntax before reloading:

$ sudo postfix check
$ sudo postfix reload
postfix/postfix-script: refreshing the Postfix mail system

postfix check validates the installation. postfix reload asks the master process to reread configuration. Both need elevated privileges. A reload is a service operation, but it does not flush the queue or deliver a message by itself.

4. Send one controlled test

Use a disposable recipient and a message with nothing sensitive in it. The command below queues one message through the local submission command.

Warning

Do not substitute a real customer address until you have reviewed the transport lookup and accept permanent loss.

$ printf 'From: postmaster@YOUR-HOSTNAME
To: [email protected]
Subject: discard test

This test message should be discarded.
' | sendmail -v [email protected]

The -v option makes submission more visible, but the useful evidence is in the Postfix log. On systems using systemd, look at recent mail records with:

$ sudo journalctl -u postfix --since '5 minutes ago' --no-pager | grep -E 'discard|discard-test.example'

On a traditional syslog setup, the same records may be in /var/log/mail.log.

Checkpoint

You should see a queue ID followed by a delivery record for the discard transport. The exact wording varies by logging daemon and configuration.

5. Understand what discard does

The daemon pretends to deliver every recipient in its request. It:

  • Logs the reason. The transport's next-hop value is recorded as the reason for discarding the message.
  • Finishes the recipients. It updates the queue file and marks them done.
  • Does nothing else. It does not connect to a network service, invoke a local mailbox, or generate a normal bounce.

The value after discard: is empty in this example, so Postfix uses the recipient domain as the nexthop information before handing the request to the discard service. To make the logged reason explicit, put text after the colon, for example discard:automated test traffic. Keep reasons short and free of secrets or personal data.

Warning

Discard is not the error transport. error reports a non-delivery condition and can bounce or defer recipients. discard completes the delivery request successfully from the queue manager's point of view. That is the main safety boundary: a typo in a discard rule causes silent, irreversible mail loss.

6. Remove the rule and recover

When the test is done, remove the two transport entries, rebuild the map, restore the previous transport_maps value, and reload. This stops future matching mail being discarded. It cannot restore messages discard has already processed.

$ sudo sed -i '/^discard-test\.example[[:space:]]/d; /^\.discard-test\.example[[:space:]]/d' /etc/postfix/transport
$ sudo postmap /etc/postfix/transport
$ sudo postconf -e 'transport_maps ='
$ sudo postfix check
$ sudo postfix reload
$ postconf -h transport_maps

Recovery

The last command should print nothing only if transport_maps was empty before step 3. If you had an existing map, restore the exact value you recorded in step 3 instead of clearing it.

Tip

To keep the table for audit, copy it to a protected location before removing entries. Never leave an active wildcard or broad rule in place.

Done means

  • Service present: postconf -M discard shows the installed Postfix discard service.
  • Narrow match: the transport lookup matches only the intended domain or subdomains.
  • Clean checks: postfix check passes before and after the reload.
  • Evidence: a disposable test produces a discard delivery record in the Postfix log.
  • No illusions: you know processed mail cannot be recovered from Postfix's queue.
  • Tidy: the temporary rule and generated map are removed, or their long-term purpose is documented.