The queryprogram router routes an address 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 precondition options (domains, local_parts, etc) to skip this router for most addresses, it could sensibly be used in special cases, even on a busy host. There are the following private options:
This option must be set. It specifies the command that is to be run. The command is split up into a command name and arguments, and then each is expanded separately (exactly as for a pipe transport, described in chapter 29).
This option specifies a gid to be set when running the command. It must be set if command_user specifies a numerical uid. If it begins with a digit, it is interpreted as the numerical value of the gid. Otherwise it is looked up using getgrnam().
This option must be set. It 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.
This option specifies an absolute path which is made the current directory before running the command.
If the command does not complete within the timeout period, its process group is killed and the message is frozen. A value of zero time specifies no timeout.
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 (case-insensitive):
Accept: routing succeeded; the remaining fields specify what to do (see below).
Decline: the router declines; pass the address to the next router, unless no_more is set.
Fail: routing failed; do not pass the address to any more routers. Any subsequent text on the line is an error message. If the router is run as part of address verification during an incoming SMTP message, the message is included in the SMTP response.
Defer: routing could not be completed at this time; try again later. Any subsequent text on the line is an error message which is logged. It is not included in any SMTP response.
Freeze: the same as defer, except that the message is frozen.
Pass: pass the address to the next router (or the router specified by pass_router), overriding no_more.
Redirect: the message is redirected. The remainder of the line is a list of new addresses, which are routed independently, starting with the first router, or the router specified by redirect_router, if set.
When the first word is accept, the remainder of the line consists of a number of keyed data values, as follows (split into two lines here, to fit on the page):
ACCEPT TRANSPORT=<transport> HOSTS=<list of hosts>
The data items can be given in any order, and all are optional. If no transport is included, the transport specified by the generic transport option is used. The list of hosts and the lookup type are needed only if the transport is an smtp transport that does not itself supply a list of hosts.
The format of the list of hosts is the same as for the manualroute router. As well as host names and IP addresses, it may contain names followed by /MX to specify sublists of hosts that are obtained by looking up MX records.
If the lookup type is not specified, Exim behaves as follows when trying to find an IP address for each host: First, a DNS lookup is done. If this yields anything other than HOST_NOT_FOUND, that result is used. Otherwise, Exim goes on to try a call to getipnodebyname() or gethostbyname(), and the result of the lookup is the result of that call.
If the DATA field is set, its value is placed in the $address_data variable. For example, this return line
accept hosts=x1.y.example:x2.y.example data="rule1"
routes the address to the default transport, with a host list containing two hosts. When the transport runs, the string rule1 is in $address_data.