Test Postfix body_checks Rules Before They Reject Mail

Test a Postfix body_checks rule against real message lines before it rejects a single email. You will finish with a rule that logs a match, a repeatable way to test it without sending mail, and a safer path from observation to enforcement. Allow about fifteen minutes.

The examples use Postfix 3.8.6, installed from package postfix 3.8.6-1ubuntu0.1 on the machine where this guide was checked.

1. Check lookup-table support

Run these ordinary, read-only commands first:

$ postconf -h mail_version
3.8.6
$ postconf -m | grep -E '^(pcre|regexp)$'
pcre
regexp

body_checks is a lookup-table setting. The installed system supports both PCRE and POSIX regular-expression tables, so this guide uses PCRE. If the second command prints nothing, pick a table type listed by postconf -m and adjust the file syntax to its manual page.

Checkpoint: Record the output of postconf -h body_checks. It may be empty, which is the default and means no body rule is configured. If it already names a table, inspect that file before changing anything.

2. Create a rule that only logs

Use a dedicated file for the first test. This example matches a distinctive marker in a message body and logs a warning while processing carries on:

# sudo sh -c 'install -o root -g root -m 0644 /dev/null /etc/postfix/body_checks.pcre'
# sudo sh -c 'cat > /etc/postfix/body_checks.pcre <<"EOF"
/^BODY-CHECK-DEMO$/    WARN body_checks demo marker matched
EOF'

How the rule behaves:

Recovery: The shell command changes a configuration file. To undo it, remove the added rule or restore your saved copy before reloading Postfix.

3. Query the rule without sending mail

Use postmap with standard input to ask the configured map what it returns:

$ postmap -q - pcre:/etc/postfix/body_checks.pcre <<'EOF'
BODY-CHECK-DEMO
EOF
WARN body_checks demo marker matched
$ postmap -q - pcre:/etc/postfix/body_checks.pcre <<'EOF'
an ordinary line
EOF

The first query prints the action. The second prints nothing and returns a non-zero status, because no pattern matched. Capture the status immediately if a script needs it:

$ postmap -q - pcre:/etc/postfix/body_checks.pcre <<'EOF'
an ordinary line
EOF
$ printf 'query status: %s\n' "$?"
query status: 1

This checks lookup behaviour, not the complete SMTP path. It does not prove that a message will reach the cleanup service, or that a downstream Milter will behave the same way.

4. Connect the table to Postfix

Only after the query behaves as expected, set the parameter with elevated privileges:

# sudo postconf -e 'body_checks = pcre:/etc/postfix/body_checks.pcre'
# postconf -h body_checks
pcre:/etc/postfix/body_checks.pcre

Check the configuration, then reload:

# sudo postfix check
# sudo postfix reload

Warning: These commands can affect mail processing, although this particular rule only logs. If postfix check reports an error, do not reload.

Recovery: Undo the setting with sudo postconf -X body_checks if the parameter was newly added, or restore its previous value with sudo postconf -e 'body_checks = PREVIOUS_VALUE'. Replace PREVIOUS_VALUE with the value you saved in step 1, and do not type the placeholder literally.

5. Watch a real match, then pick an action

Submit a harmless test message through the normal local submission path, with the marker on its own line. This may queue mail, so use a test recipient and follow your site's mail-handling policy:

$ /usr/sbin/sendmail -t <<'EOF'
From: [email protected]
To: [email protected]
Subject: body_checks test

BODY-CHECK-DEMO
EOF

Look in the Postfix log for the text from the WARN action. On systemd systems, a common read-only check is:

$ sudo journalctl -u postfix --since '5 minutes ago' --no-pager | grep 'body_checks demo marker matched'

Log locations vary, and a missing line can mean the message used a different Postfix instance or submission path. Check the queue and service logs before changing the pattern.

When the observation is right, replace WARN with the action your policy needs:

Warning: These are operational and security-sensitive decisions. Keep the working WARN version so you can revert quickly.

6. Know the limits that cause surprises

Done means