Run executable
The Run executable action runs a program or script on the milter host when a policy rule matches. You can pass message details to the program as arguments, and choose whether the rule waits for the program to finish or runs it in the background.

The program must be a file in the scripts directory of the milter, the same directory the External script condition uses: SCRIPTS_DIR in the configuration, /opt/msh-zr/scripts by default. A program outside it is not run. The directory ships with two sample scripts, accept.sh and reject.sh, and a README.txt that explains how to add your own.
Rules whose executable lies outside the scripts directory stop running after the upgrade to 1.1. Move the program, or a wrapper script that calls it, into /opt/msh-zr/scripts, run sudo sh /opt/msh-zr/lib/fixperms.sh so it is executable and writable by its owner only, and put its name in the rule in place of the old absolute path.
Executable path
The name of the program or script in the scripts directory.
Example:
notify.sh
Arguments
The arguments passed to the executable, separated by spaces.
Example:
--subject={message:subject} --from={message:envelope:sender}
Variables can be used in the Arguments field, so message details are resolved for each message before the program is run. A variable that resolves to a value containing spaces is passed as a single argument, so joining it to a flag with = (for example --subject={message:subject}) keeps the flag and its value together.
The program also gets the message through the same MSH_* environment variables as an External script: MSH_SENDER, MSH_RECIPIENTS, MSH_SUBJECT, MSH_MESSAGE_ID, MSH_MESSAGE_SIZE and MSH_QUEUE_ID. Prefer them to arguments: values from the message are chosen by the sender, so quote them in the script and never pass them through a shell. See External script for the details.
Wait for finish
When enabled, the rule waits for the program to finish before continuing (synchronous). When disabled, the program is started in the background and rule processing continues immediately (asynchronous); the program still runs under the rules below, and its result goes to the server log instead of the processing trace.
How the program runs
- The program runs only when its real path - after resolving
..and symbolic links - is inside the scripts directory, it is a regular executable file, and neither its group nor other users can write to it. - It runs without a shell and with a cleaned environment that holds only the
MSH_*variables of the message. - It is stopped after 60 seconds, together with any processes it started.
- At most
SCRIPTS_MAX_CONCURRENTprograms and scripts run at the same time (5 by default). - Without a scripts directory (
SCRIPTS_DIRset empty) the action runs nothing.
A program that may not run is reported in the processing trace and in the server log, for example The program was not run: '/usr/local/bin/notify' is outside the scripts directory /opt/msh/scripts.
The program runs on the milter host with the milter's permissions. Only put executables you trust into the scripts directory, and leave Wait for finish disabled for long-running programs so they do not hold up message processing.
Additional resources
- External script - run a script as a condition, before the rule matches, and set up the scripts directory
- How to use Variables