Go to the first, previous, next, last section, table of contents.


32. The queryprogram router

The queryprogram router routes a domain by running an external command and acting on its output. This is an expensive way to route, and is intended mainly for use in lightly-loaded systems, or for performing experiments. However, if it is possible to use the domains, local_parts or condition generic options to skip this router for most addresses, it could sensibly be used in special cases. There are the following private options:

command (queryprogram)

Type: string, expanded
Default: unset

This option must be set, and must start with a slash character. It specifies the command that is to be run. It is expanded before use. Failure to expand causes delivery to be deferred and the message to be frozen.

command_group (queryprogram)

Type: string
Default: unset

This option specifies a gid to be set when running the command. If it begins with a digit it is interpreted as the numerical value of the gid. Otherwise it is looked up using getgrnam().

command_user (queryprogram)

Type: string
Default: unset

This option specifies the uid which is set when running the command. If it begins with a digit it is interpreted as the numerical value of the uid. Otherwise, it is looked up using getpwnam() to obtain a value for the uid and, if command_group is not set, a value for the gid also.

current_directory (queryprogram)

Type: string
Default: unset

This option specifies an absolute path which is made the current directory before running the command. If it is not set, `/' is used.

timeout (queryprogram)

Type: time
Default: 1h

If the command does not complete within the timeout period, its process group is killed and the message gets frozen. A value of zero time specifies no timeout.

If command_user is not specified, the command is run as `nobody'. If the main configuration has not defined a user and group for `nobody', it is looked up using getpwnam(). If this fails, delivery is deferred and the message is frozen.

In previous versions of Exim the command_group and command_user options were called group and user. Their names were changed when group and user became generic router options.

The standard output of the command is connected to a pipe, which is read when the command terminates. It should consist of a single line of output, containing up to five fields, separated by white space. The first field is one of the following words:

When the first word is not OK, the remainder of the line is an error message explaining what went wrong. For example:

FAIL  queryprogram cannot route to unseen.discworld.fict.book

Otherwise, the line must be formatted as follows:

OK <transport name> <new domain> <option> <arbitrary text>

The second field is the name of a transport instance, or a plus character, which means that the transport specified for the router using the generic transport option is to be used, if set.

If the third field is not empty or a single plus character, it is a new domain name to replace the current one. If a transport is specified and the fourth field is not empty or a plus character, it specifies the method of looking up the new name. This can be one of the words `byname', `bydns', `bydns_a', or `bydns_mx'. For example,

OK  smtp  gate.star.fict.book  bydns_a

causes the message to be sent using the smtp transport to the host gate.star.fict.book, whose address is looked up as a DNS address record. If the host turns out to be the local host, what happens is controlled by the generic self option.

The fifth field, if present, is made available to the transport via the expansion variable $route_option. For example, a line such as

OK special + + /computed/filename

sends the message to the special transport, which can use $route_option in its configuration to access the text `/computed/filename'.

The fourth and fifth fields are ignored and the new domain name (if any) is passed to the next router if no transport is specified in the response line (that is, a plus character is given) and the generic transport option is also unset. This counts as an explicitly configured `pass', and overrides no_more.


Go to the first, previous, next, last section, table of contents.