Skip to content

qmail multi.8

Manvendra Bhangui edited this page Feb 25, 2024 · 7 revisions

NAME

qmail-multi - queue multiplexor and filter

SYNOPSIS

qmail-multi [qqf] [arg1] [arg2] ...

DESCRIPTION

qmail-multi(8) is a queue multiplexor and filter for qmail-queue(8). The multiplexor can be turned on by defining environment variable QMAILQUEUE=/usr/sbin/qmail-multi. Following programs use qmail-multi(8) to deposit the mail to the queue - qmail-dkim(8), qmail-qfilter(1), qmail-spamfilter(8), qscanq-stdin(8).

qmail-multi(8) invokes qmail-queue(8) to deposit the mail. One can call any other program by passing command line arguments to qmail-multi(8) in QMAILQUEUE. If passed arguments, qmail-multi(8) will call qqf. Any arguments after qqf will be passed as arguments to qqf. You can change the program that qmail-multi(8) calls, by setting the environment variable QUEUEPROG, to the path of any qmail-queue frontend. QUEUEPROG is typically used when you want to use write your own queue frontend, with the queue path available in QUEUEDIR environment variable. If QUEUEDIR is set qmail-multi(8) execs qmail-queue (or program defined by QUEUEPROG without any processing or setting up any environment variables. QUEUEPROG is ignored when qmail-multi(8) is passed command line arguments.

The deposition and balancing of mail across multiple queues is controlled by the following environment variables.

QUEUE_BASE The base directory having all the indimail queues. If this
is not defined, the control file queue_base is used. This is typically /var/indimail/queue.

QUEUE_START This is a number which defines the first queue that
should be used.

e.g. QUEUE_START=1 implies the first queue to be /var/indimail/queue/queue1

QUEUE_COUNT This defines the number of queues that should be used for
load balancing. qmail-multi(8) used a random number to select a queue in a multi-queue setup.

e.g. QUEUE_START=1, QUEUE_COUNT=5 implies 5 queues /var/indimail/queue/queue1, /var/indimail/queue/queue2, ..., /var/indimail/queue/queue5

MIN_FREE
This is the minimum free disk space that should be available in the filesystem containing the queues. When free space goes below this value, qmail-multi(8) will return a temporary disk full error "qq write error or disk full (#4.3.0)". This prevents qmail-send reaching a deadlock in the case when disk becomes full and there are bounce messages to be processed. qmail-send in this case keeps on retrying bounce message which does not succeeed because of insufficient disk space to write the bounce. This effectively stops processing of local and remote messages and thus disk space never gets freed up. qmail-multi(8) prevents this from happening by accepting mails only when disk space greater than MIN_FREE is present. It uses statfs(2) (statvfs on solaris) to get the free space on the filesystem.

DYNAMIC_QUEUE
If this is set, qmail-multi(8) uses a queue with the lowest concurrency to total concurrency ratio. It uses shm_open(3) to open shared memory /qscheduler and /queueN, where N refers to the queue number. The shared memory /qscheduler has the total number of queue qcount, written by qscheduler(8). The shared memory /queueN has the current concurrency C, and the maximum concurrency M configured for the queue. The concurrency details are written to /queueN shared memory by qmail-send(8) qmail-queue(8) cycles through qcount queues and selects the queue with the lowest C / M ratio.

qmail-multi(8) is actually a wrapper for qmail-queue(8) to manage multiple queues. N queues can be set up in /var/indimail as queue1, queue2, ... queueN. qmail-multi(8) does load balancing across these N queues by doing exec of qmail-queue with QUEUEDIR set to the path of one of these N queues. Each of these N queues should be created using queue-fix(1) program. One also needs a program like qscheduler(8) which invokes multiple qmail-send(8) with the QUEUEDIR set individualy to path of these N queues.

qmail-multi(8) has the ability to run any filter defined by setting the FILTERARGS environment variable. Any command defined by FILTERARGS will be run using /bin/sh. The input to this filter will be fd 0 and the output will be piped to qmail-queue(8). e.g.

FILTERARGS="/usr/bin/altermime --input=- --disclaimer=/etc/motd"

will append the output of altermime command to all mails.

The sequence in which the filter program is run is given below

1. create a pipe and fork

2. dup write end of the pipe to descriptor 1 in the child and exec the
filter program

3. dup read end of the pipe to descriptor 0 in parent and exec
qmail-queue.

This gives the ability for the FILTERARG program to read the mail message from descriptor 0 before passing it to qmail-queue through the pipe.

qmail-multi(8) will attempt to make the descriptor 0 seekable if the environment variable MAKE_SEEKABLE is defined. This may be necessary for certain filter programs which require descriptor to be seekable.

qmail-multi(8) will bounce the message if the return status from the filter program is 100. The mail will be blackholed if the return status is 2. If the return status is non-zero, qmail-multi(8) will exit issuing a temporary error.

qmail-multi(8) generates a random number and divides it by QUEUE_COUNT. This remainder is added to QUEUE_START to arrive at which queue to use. It then sets the QUEUEDIR=/usr/sbin/qmail-queue to queue the mail.

qmail-multi(8) sets an alarm of 86400 seconds to quit if it doesn't complete. This can be changed by setting DEATH environment variable. See the man pages for qmail-queue(8) and indimail-mta-internals(7) for more details.

EXIT CODES

qmail-multi(8) does not print diagnostics. It exits 120 if it is not able to exec qmail-queue(8). Apart from this it has the following exit codes.

It exits 51 if it cannot allocate memory
It exits 55 if it is not able get the free space for the queue filesystem.
It exits 53 if the free space is below MIN_FREE value.
It exits 60 if it cannot create pipes or dup file descriptors.
It exits 61 if cannot change directory to /var/indimail
It exits 68 if it cannot create temporary files to make the input seekable.
It exits 121 if fork fails
It exits 31 if the program/script defined by FILTERARGS returns 100
(i.e. mail gets bounced).
If the program/script defined by FILTERARGS returns 2, then the mail
gets blackholed.
If the program/script defined by FILTERARGS exits non-zero status,
it exits 71 and a temporary error is issued.
It exits 88 when the filter program exits with return value of 88 and also
passes the error message printed by the filter program on fd2 to
qmail-queue
It exits 123 if the filter program crashes.
For all other cases where no errors occur, it exits 0.

SEE ALSO

addresses(5), rfc-822(5) qmail-send(8), qmail-inject(8), qmail-smtpd(8), sendmail(8) indimail-control(5), qmail-header(5), qmail-queue(8), qmail-qmqpc(8), qmail-nullqueue(8), qmail-spamfilter(8), qscanq(8), cleanq(8), bogofilter(1), queue-fix(8), spawn-filter(8), qscheduler(8), multi-queue(7), indimail-mta-internals(7),

AUTHORS "Manvendra Bhangui" <manvendra@indimail.org>.

Clone this wiki locally