The queue is where mail is held
until
it can be successfully delivered. The queue holds mail for later
delivery when a temporary error is encountered during the delivery
process. Most sendmail administrators have seen
“Deferred” appear in an error
message and know that it means the mail will be held in the queue
until the next queue run. Mail is also placed in the queue when the
system load exceeds the load average defined by the
sendmail.cf
QueueLA
option,
and when certain delivery modes are used. Queuing is an important
component of creating a robust, reliable mail delivery system.
Each mail message in the queue can be represented by up to four queue files:
The df file contains the message body.
The qf file contains the message headers and the queue control information needed to deliver the message.
The xf file is a temporary file that contains a transcript of any error messages sendmail receives when attempting to deliver the message. Any error messages collected in the xf file are returned to the sender, and the xf file is deleted after the delivery attempt.
The tf file is a temporary work file that sendmail uses to produce the updated qf file. The queue control information in the qf file is updated each time a message is requeued. Any changes to that information take place in the tf file to safeguard the qf file. After the tf file is successfully updated, it is renamed as a qf file.
Of the four file types, only the df and qf files are long-term residents of the queue. The content of these files, even of the qf files that contain queue control information, have no impact on the recipes in this chapter, and therefore, we won’t describe the content of these files in any more detail. If you’re curious about the internals of the qf file, see Section 11.11 of the sendmail book.
df, qf, xf, and tf are filename prefixes that identify the type of queue file. The full name of a queue file is composed of one of these prefixes followed by the unique queue identifier associated with an individual message. For example, this ls command lists all of the df files in the queue:
# ls df*
dfg7KEK4W9001253 dfg8Q82lkj002190 dfg8RDYB6v001254
While this ls command lists all of the files associated with a specific mail message:
# ls *g8Q82lkj002190
dfg8Q82lkj002190 qfg8Q82lkj002190
These ls commands are used to illustrate the structure of a queue filename. ls is not normally used to examine the queue. Use the mailq command to see what messages are queued.
By default, the sendmail.cf configuration uses the /var/spool/mqueue directory for the queue files. The submit.cf configuration uses /var/spool/clientmqueue as the default. However, several of the recipes in this book contain commands that change the default queue and create a more complex and flexible queue directory structure for the sendmail.cf configuration, and those same commands can be used in the submit.cf configuration.
The queue can be processed immediately by running sendmail with the
-q
commandline option. More typically, however,
the -q
option is provided with a time interval
argument, which causes sendmail to process the queue periodically.
For example, -q15m
would process the queue every
15 minutes.
Timing, and not just the timing of how often the queue is processed, is part of the nature of a queue. After all, a queue is created to store undelivered messages for a specified amount of time. A sendmail queue also has timers for how often the sender is warned that the message is still undelivered and waiting in the queue. These timers can be configured for normal, urgent, and non-urgent messages. The timer options in the sendmail.cf file that relate to how long messages are held in the queue are:
Timeout.queuereturn
The Timeout.queuereturn
option defines
the amount of time a message is kept in
the queue before it is returned to the sender as undeliverable. This
option is configured by the confTO_QUEUERETURN
define. This timer, which defaults to five days
(5d
), applies to most mail messages.
Timeout.queuereturn.normal
This option defines the amount of time a message containing a
Precedence
: normal
header is
kept in the queue before it is returned to the sender as
undeliverable. This option is configured by the
confTO_QUEUERETURN_NORMAL
define. The default is
five days (5d
).
Timeout.queuereturn.urgent
This option defines the amount of time a message containing a
Precedence
: urgent
header is
kept in the queue before it is returned to the sender as
undeliverable. This option is configured by the
confTO_QUEUERETURN_URGENT
define. The default is
two days (2d
).
Timeout.queuereturn.non-urgent
This option defines the amount of time a message containing a
Precedence: non-urgent
header is kept in the queue
before it is returned to the sender as undeliverable. This option is
configured by the confTO_QUEUERETURN_NONURGENT
define. The default is seven days (7d
).
Timeout.queuewarn
The Timeout.queuewarn
option defines the amount of
time sendmail waits before sending a warning message telling the
sender that a message is still undelivered. This option is configured
by the confTO_QUEUEWARN
define. This timer, which
defaults to four hours (4h
), applies to most mail
messages.
Timeout.queuewarn.normal
This option defines the amount of time sendmail waits before sending
a warning message telling the sender that a message containing a
Precedence
: normal
header is
still undelivered. This option is configured by the
confTO_QUEUEWARN_NORMAL
define. The default is
four hours (4h
).
Timeout.queuewarn.urgent
This option defines the amount of time sendmail waits before sending
a warning message telling the sender that a message containing a
Precedence
: urgent
header is
still undelivered. This option is configured by the
confTO_QUEUEWARN_URGENT
define. The default is one
hour (1h
).
Timeout.queuewarn.non-urgent
This option defines the amount of time sendmail waits before sending
a warning message telling the sender that a message containing a
Precedence
: non-urgent
header
is still undelivered. This option is configured by the
confTO_QUEUEWARN_NONURGENT
define. The default is
12 hours (12h
).
As an example, adding the following
confTO_QUEUERETURN
define to the sendmail
configuration would reduce to three days the amount of time a normal
message is allowed to remain in the queue before it is returned to
the sender as undeliverable:
dnl Return normal messages after three days in the queue define(`confTO_QUEUERETURN', `3d')
Timing might be changed on any system. The recipes in this chapter, however, are primarily of interest to large sites that have large queues. On most systems, the queue is so small that the amount of time spent processing the queue is negligible. However, when the queue grows to tens of thousands of messages, significant time can be used on each queue run. If your system normally has a small queue of a few hundred or a few thousand queued messages, the default sendmail configuration is probably adequate. If your queue often grows to tens of thousands of messages, read on.
You have been asked to create multiple mail queues spread over multiple physical devices in order to efficiently handle a large amount of mail.
Prepare the physical devices that will hold the mail queues. Each device must be formatted according to the requirements of your system and must contain a filesystem that is compatible with your operating system. Formatting devices and building Unix filesystems is beyond the scope of this book. See Essential System Administration, Third Edition, by Æleen Frisch (O’Reilly).
Create the directories needed for the various mail queues:
#cd /var/spool/mqueue
#mkdir queue.1 queue.2 queue.3
#chmod 700 queue.?
Mount the physical devices on the newly created directories. This example uses Linux device names:
#mount /dev/hda1 /var/spool/mqueue/queue.1
#mount /dev/hdb2 /var/spool/mqueue/queue.2
#mount /dev/hdd1 /var/spool/mqueue/queue.3
Edit the /etc/fstab or /etc/vfstab file to mount the devices during every boot. Here are the sample mounts defined in an /etc/fstab file on a Red Hat Linux system:
/dev/hda1 /var/spool/mqueue/queue.1 ext3 defaults 1 2 /dev/hdb2 /var/spool/mqueue/queue.2 ext3 defaults 1 2 /dev/hdd1 /var/spool/mqueue/queue.3 ext3 defaults 1 2
Note that the lines above are added to the current /etc/fstab file. Overwriting or deleting the existing entries in the fstab file could severely impact the system—rendering it incapable of rebooting. Use care when adding lines to the fstab file.
Add the QUEUE_DIR
define to the sendmail
configuration to use the new queue directories. Here is an example of
the define:
dnl Declare the queue directory path define(`QUEUE_DIR', `/var/spool/mqueue/queue.*')
Build sendmail.cf. Copy it to /etc/mail/sendmail.cf, and restart sendmail, as shown in Recipe 1.8.
By default, sendmail uses a single
queue
directory, which is usually named
/var/spool/mqueue in the
sendmail.cf file. The queue directory pathname
is defined by the QueueDirectory
option. A
grep of a basic sendmail configuration shows the
default:
$ grep QueueDirectory generic-linux.cf
O QueueDirectory=/var/spool/mqueue
Use the m4
QUEUE_DIR
define
to set the value of the QueueDirectory
option.
After reconfiguring sendmail with the QUEUE_DIR
define shown in Recipe 9.1.2, another
grep shows the change:
$ grep QueueDirectory sendmail.cf
O QueueDirectory=/var/spool/mqueue/queue.*
This recipe uses a special pathname format. The asterisk at the end
of the pathname indicates that there are multiple
queue directories. Only an
asterisk can be used to indicate multiple queues, and it must appear
at the end of the pathname. Given the
QueueDirectory
option shown above, sendmail looks
for queues with names that begin with
/var/spool/mqueue.queue
. followed by any other
string of characters.
This recipe mounts a separate physical device on each queue directory. While this is not absolutely necessary, it illustrates a common use of multiple directories. Placing multiple directories on a single device provides performance gains, but using multiple devices can provide even larger performance gains. sendmail Performance Tuning, by Nick Christenson (Addison Wesley), provides insight into these performance gains.
Multiple queues, as implemented in this recipe, speed the processing of large queues. If your server sometimes has more than 10,000 messages waiting in the queue, Recipe 9.1 may help improve your server performance and reliability.
Note that it is not necessary to use QUEUE_DIR
to
create multiple queues simply to organize mail into specific queues.
qf, df, and
xf subdirectories organize the queue by queue
file types, as described in Recipe 9.2.
Queue groups, which are discussed in Recipe
Recipe 9.3, organize mail in separate queues. The
separate queues used for queue groups can be subdirectories of a
single default queue. Although qf,
df, and xf subdirectories
and queue groups can be used with multiple queues defined by a
QUEUE_DIR
command, they do not require that
command.
Recipe 9.2 describes another technique for
creating multiple queues that can be combined with this recipe. The
sendmail book covers multiple queues in Section
11.3. The QueueDirectory
option is explained in
the Sendmail Installation and Operations Guide
found in the doc/op directory of the sendmail
distribution.
Special configuration is required to use multiple mail queues for the different queue file types.
Create a new queue directory structure with separate directories for df, qf, and xf queue files. Here is an example:
#umask 077
#mkdir /var/spool/mqueue.new
#cd /var/spool/mqueue.new
#mkdir df qf xf
Move the old queue directory out of the way so that the new queue
directory structure can be given the pathname defined by the
QueueDirectory
option in the
sendmail.cf file. Here is an example:
#mv /var/spool/mqueue /var/spool/mqueue.old
#mv /var/spool/mqueue.new /var/spool/mqueue
Start another copy of sendmail as a queue runner to drain the old
queue. Use the -O
argument on the
sendmail command line to point the queue runner
to the old queue. Here is an example:
# sendmail -L sm-oldq -q15m -O QueueDirectory=/var/spool/mqueue.old
sendmail stores df, qf, and xf files in separate directories when the default queue directory contains subdirectories named df, qf, and xf. As with the multiple queues described in Recipe 9.1, df, qf, and xf subdirectories reduce the size of any individual queue directory, and they allow the subdirectories to be placed on separate devices to overcome the I/O limitations of a single device. These benefits aid in the processing of a very large mail queue. Additionally, using separate subdirectories for the different queue files allows you to select a device that is optimized for the type of queue file that it will handle. These are the file characteristics to consider when selecting a device:
A df file contains the body of the mail message. Usually, it is the largest of the three files. A df file is written to the queue once and read once for each delivery attempt, so it is usually handled less than the other files. Storage capacity is the primary consideration when selecting a device for df files.
A qf file contains the delivery and queuing instructions for the message, as well as the message headers. A qf file is small, but it is rewritten each time a delivery is attempted. When a message has many recipients or is requeued several times, sendmail handles the qf file many times. Performance is an important consideration when selecting a device to handle qf files.
An xf file is created for each delivery attempt and is valid only for that attempt. xf files are small and they have a short life. Performance is the primary consideration when selecting a device for xf files.
These subdirectories can be created in any combination. You could,
for example, create just an xf
directory—sendmail would place xf files in
that directory and place df and
qf files in the base directory. This recipe
creates a temporary directory,
/var/spool/mqueue.new, as the base directory.
All three subdirectories, df,
qf, and xf, are then
created within that directory. The old queue directory is moved out
of the way and the new directory is renamed to the value defined by
the sendmail.cf
QueueDirectory
option, which, in the example, is
/var/spool/mqueue. sendmail will begin to use
the new directory structure as soon as it is renamed.
As Nick Christenson explains in his book, sendmail Performance Tuning (Addison Wesley), the apparent race condition caused by renaming sendmail’s queue directory while sendmail is running is minimal. Mail sent by the MSP uses the queue directory defined in submit.cf, which is usually /var/spool/clientmqueue, so it is unaffected when mqueue is renamed.[1] A process that is running when the directory is renamed is unaffected because it uses the inode of the queue directory not the logical name. Therefore, if the process started with the old queue, it will continue with the old queue even after the queue directory is renamed. After the master sendmail process is restarted, all subsequent sendmail processes will use the new queue.
Of course, mail queued in the old directory will remain there after
the directory is renamed unless a process is started to drain the old
queue. Use the -O
argument on the command line to
point the queue runner to the old queue, as shown in Recipe 9.2.2. Periodically check the old queue to
see if it has drained using a command such as the following:
# sendmail -bp -O QueueDirectory=/var/spool/mqueue.old
When the old queue is empty, kill the special queue runner and remove the unneeded directory.
The df, qf, and
xf subdirectories can be placed on separate
physical devices. For example, on a Linux system, the
xf subdirectory could be placed on
/dev/shm, which is a shared memory device using
the Linux tmpfs
filesystem format. Placing the
xf subdirectory on a volatile, memory-based
filesystem that provides very high performance at the cost of
long-term storage works because xf files do not
need to be preserved between queue runs or reboots.
Multiple queues, such as those created in Recipe 9.1, can be combined with df, qf, and xf subdirectories to gain the advantages of both multiple queues and subqueues for a system that handles a very large mail queue. Recipe 9.1 created three queue directories. Within each of those, we could create df, qf, and xf subdirectories for a total of nine different directories, which could then be allocated to physical devices in any manner you wished.
Recipe 9.1 also creates multiple queues that can be combined with this recipe. The sendmail book covers the df, qf, and xf subdirectories in Section 11.3.2 and in Section 6.5. sendmail Performance Tuning, by Nick Christenson (Addison Wesley), covers this topic in Section 3.4.4.
Special configuration is required to define different mail queues with unique characteristics.
Create the directories for the queue groups. The queue group directories must be subdirectories under the default queue directory. In this example, four queue group directories are created:
#cd /var/spool/mqueue
#mkdir slowq fastq.1 fastq.2 fastq.3
#chmod 700 slowq fastq.?
Add QUEUE_GROUP
macros to the sendmail
configuration to use the queue group directories created in the first
step. Here are sample QUEUE_GROUP
macros:
dnl Define a queue group QUEUE_GROUP(`slowq', `Path=/var/spool/mqueue/slowq') dnl Define a queue group QUEUE_GROUP(`fastq', `Path=/var/spool/mqueue/fastq.*, I=10m, F=f, R=3')
Build sendmail.cf. Copy it to /etc/mail/sendmail.cf, and restart sendmail. See Recipe 1.8.
The first step in Recipe 9.3.2 creates
four queues in the /var/spool/mqueue directory:
slowq, fastq.1,
fastq.2, and fastq.3. These
queues are then referenced by the QUEUE_GROUP
macros as the slowq and
fastq queue groups. The directories for queue
groups are created in the base path of the default queue. When a
single directory is used for the default queue, the base path is the
path specified by the QueueDirectory
option. When
QUEUE_DIR
is used to define multiple queue
directories, as it was in Recipe 9.1, the
default queue pathname specified by the
QueueDirectory
option and the base pathname are
not exactly the same. For example:
define(`QUEUE_DIR', `/var/spool/mqueue/queue.*')
This QUEUE_DIR
define sets the default queue to
/var/spool/mqueue/queue.*. The base pathname in
this case is /var/spool/mqueue, not
/var/spool/mqueue/queue.*. The directory that
contains the subdirectories used for multiple queues is the base path
in which the queues used for other queue groups should be placed.
Use the QUEUE_GROUP
m4 macro
to declare queue groups. The syntax of the
QUEUE_GROUP
command is:
QUEUE_GROUP(`groupname
', `equates
')
The groupname
is an arbitrary name
assigned to a queue. The groupname
is used
to reference the queue from within the sendmail configuration and in
QGRP
: records in the access
database. The default queue is named mqueue, and
it can be referenced by that name.
The equates
are a comma separated list of
queue attributes written in the form
keyword
=
value
.
The equates
field must be present,
although it can be explicitly empty. The
QUEUE_GROUP
commands in Recipe 9.3.2 have values in the
equates field. Here is an example with an empty
equates field:
QUEUE_GROUP(`normalq', `')
Notice the single quotes enclosing the empty
equates
field in the example above. When
the equates
field is empty, the queue
group inherits all of the attributes of the default queue,
mqueue. Given the QUEUE_GROUP
command shown above, normalq would use the same
queue directory and all of the same attributes as the
mqueue queue group.
All queue groups inherit the
attributes of the default queue.
The
keyword
=
value
equates defined in the equates
field are
used to override the default values for specific queue attributes.
Table 9-1 lists
the available keywords and describes
the queue attribute associated with each keyword.
Keyword |
Function |
|
Sets optional runtime flags. |
|
Specifies the time interval between queue runs. |
|
Limits the number of envelopes processed during a single queue run. |
|
Defines the |
|
The full pathname of the queue directory used for this queue group. |
|
Sets the maximum number of recipients allowed for one envelope. |
|
Defines the maximum number of queue processors that can be used in any one queue run. |
The effect of the equates listed in Table 9-1 can be altered by other configuration options:
confFAST_SPLIT
The number assigned
to this option sets the
maximum number of envelopes that can be delivered during the initial
delivery, without regard to the value set by Jobs
.
Additionally, assigning a positive number to this option prevents MX
lookups of recipient addresses when the envelope is being split.
Skipping the MX lookup can speed up envelope processing, and limiting
the number of delivery processes can enhance performance on a heavily
loaded system. By default, sendmail performs MX lookups when
splitting envelopes, and it runs as many delivery processes as needed
to deliver all of the envelopes in parallel.
confMAX_QUEUE_CHILDREN
The number assigned to this option is the maximum number of queue
processes allowed across all queue groups. The upper limit set by
this option is not affected by the values set for
Runners
or Flags
. If
confMAX_QUEUE_CHILDREN
is set to 10 and the total
number of Runners
is set to 15, sendmail limits
the number of queue processes to 10. By default,
confMAX_QUEUE_CHILDREN
is set to 0, which means
that sendmail allows an unlimited number of queue processes (up to
the limit set by Runners
).
confMAX_RUNNERS_PER_QUEUE
This option sets the default maximum number of queue runners allowed
per queue group. The value set by Runners
in a
QUEUE_GROUP
macro overrides this default value for
a specific queue group.
confMIN_QUEUE_AGE
This option sets the minimum amount of time that a queued message
must wait in the queue before a delivery attempt is made. This value
is not affected by how frequently the queue is processed. If the
Interval
is set to 10 minutes (10m) and
confMIN_QUEUE_AGE
is set to 1 hour (1h), it is
possible for a message to sit in the queue for 6 queue runs before
sendmail attempts to deliver it. This option is used to reduce the
load on systems that have very large queues, yet use a short queue
interval. By default, sendmail attempts to deliver all of the mail in
the queue (up to the limit set by Jobs
) every time
the queue is processed.
confNICE_QUEUE_RUN
This option sets the default nice
value used for
queue runs. It can be overridden for a specific queue group by using
Nice
in a QUEUE_GROUP
macro.
confMAX_QUEUE_RUN_SIZE
This option sets the maximum
number of queue messages that will be
processed during a queue run across all queue groups. By default,
sendmail attempts to deliver all of the mail in the queue. This
option sets an upper limit on the number of messages sendmail will
attempt to process, much like Jobs
does for a
single queue group.
The sendmail configuration in this recipe contains two
QUEUE_GROUP
commands:
QUEUE_GROUP(`slowq', `Path=/var/spool/mqueue/slowq') QUEUE_GROUP(`fastq', `Path=/var/spool/mqueue/fastq.*, I=10m, F=f, R=3')
The first QUEUE_GROUP
command defines a queue
group and assigns it the name slowq. The path to
the slowq group’s queue
directory is defined as /var/spool/mqueue/slowq.
All of the other attributes used by slowq are
the default queue attributes.
The second QUEUE_GROUP
command defines the
fastq queue group. The
fastq group uses multiple queues, as indicated
by the asterisk suffix on the queue directory’s
pathname. The asterisk is used to define multiple queues for any
queue group in exactly the same way that it is used to define
multiple queues for the default queue group. See Recipe 9.1 for more about multiple queues and the
asterisk suffix.
In addition to the Path
attribute, the second
QUEUE_GROUP
command defines three other
attributes: Interval
, Flags
,
and Runners
. Notice that the keyword in each
equate does not need to be spelled out; only the first character of
the keyword is significant. Thus I=10m
is
equivalent to Interval=10m
, and the
Path
attribute could have been set with
P=/var/spool/mqueue/fastq.*
. Also, notice that
each item in the equate list is separated by a comma. The whitespace
used in the example enhances readability, but it is not required.
Setting the attribute I=10m
means that sendmail
will process the queues in this queue group every 10 minutes. Setting
the f
flag, F=f
, tells sendmail
to fork queue runners for each queue, up to the limit of queue
processes defined with the Runners
keyword.
f
is the only value currently valid for
Flags
. Always use F=f
when you
use the Runners
keyword.
Setting R=3
means that sendmail can use up to
three separate processes to process the queues in this queue group.
This recipe created three queues (fastq.1,
fastq.2, and fastq.3) for
the fastq group. Setting R=3
means that each queue will have a single queue processor for each
queue run. Setting R=15
would have dedicated five
processes to each queue during each queue run. However, a large
number of queue runners is not always a good thing. To find out why,
see Recipe 9.5.
The QUEUE_GROUP
macros create Q
commands inside the sendmail.cf file. The
Q
commands created by this recipe are:
# grep '^Q' recipe9-3.cf
Qslowq, Path=/var/spool/mqueue/slowq
Qfastq, Path=/var/spool/mqueue/fastq.*, I=10m, R=3
Queue groups are used by queue management features. For example, you
can configure a sendmail mailer to use a particular queue group as
its default mail queue. The Q
parameter of the
mailer definition tells the mailer which queue group it should use.
All mailers have an m4 define for the
Q
parameter; all of these defines are used in
exactly the same way; and most have names in the form of
NAME
_MAILER_QGRP
, where
NAME
is the mailer’s
internal name. For example, use
PROCMAIL_MAILER_QGRP
to set Q
if the name of the mailer is procmail
.
Additionally, queue groups can be used in the access database. Recipe 9.4 shows an example of this.
Recipe 9.1 covers the QUEUE_DIR
command and discusses multiple queues. Recipe 9.2 covers the df, qf, and xf
subdirectories, which can be created in the queue directory of any queue group. The
sendmail book covers queue groups in Section 11.4, confQUEUE_FILE_MODE
in 24.9.84, confFAST_SPLIT
in
24.9.32, confMAX_QUEUE_CHILDREN
in 24.9.65, confMIN_QUEUE_AGE
in 24.9.72, confMAX_QUEUE_RUN_SIZE
in 24.9.66, confNICE_QUEUE_RUN
in 24.9.74, and confMAX_RCPTS_PER_MESSAGE
in 24.9.67.
To use queues optimized for the characteristics of the destination host, you must route mail bound for recipient addresses on those hosts to the optimized mail queues.
Create the directories for the queue groups and, if necessary, the physical devices the queue group directories will use. See Recipe 9.1 and Recipe 9.3 for details.
Add QGRP
: records to the
access database to specify the queue groups used
for specific recipients. The key of each entry is the tag
QGRP
: followed by a full or partial recipient
address. The return value of the entry is the name of the queue group
that should be used for the specified recipient.
Create a sendmail configuration that defines the queue groups, enables the access database, and uses the queuegroup feature. Here are sample lines that might be added to the sendmail configuration:
dnl Define a queue group QUEUE_GROUP(`slowq', `Path=/var/spool/mqueue/slowq, I=2h') dnl Define a queue group QUEUE_GROUP(`fastq', `Path=/var/spool/mqueue/fastq.*, I=10m, R=10') dnl Enable the access database FEATURE(`access_db') dnl Enable the queue group feature FEATURE(`queuegroup')
Build and install /etc/mail/sendmail.cf, then restart sendmail, as shown in Recipe 1.8.
The access database provides
the most flexible means to
utilize queue groups. QGRP
: records in the
access database allow you to assign individual
domains, and even individual users, to specific queue groups. This
makes it possible to create queue groups that have characteristics
that are compatible with the characteristics of a recipient site. For
example, the queue for a site that has repeated, long-duration
outages might have a large Interval
value, or
multiple queues might be dedicated to a few domains that constitute
the bulk of your outbound traffic.
Here is a sample QGRP
: entry:
QGRP:example.com slowq
The QGRP
: record tells sendmail to use the
slowq queue group to queue mail for every user
on all hosts in the example.com domain. The
recipient address in a queue group entry can identify an individual
user or a group of hosts. The possible recipient address formats are:
A full address in the format
user
@
host.domain
.
This format matches a specific user on a specific host.
QGRP:[email protected]
is an example.
A hostname in the format host.domain
;
e.g., QGRP:crab.wrotethebook.com
. Any user on the
specified host is matched.
A domain name to match every user on every host in the specified
domain. For example, QGRP:wrotethebook.com
would
match every recipient in the wrotethebook.com
domain.
A username written in the form
user
@
; e.g.,
QGRP:craig@
. This format matches any recipient
with the specified username on any host in any domain.
A blank field, which matches every possible recipient address.
Mail addressed to recipients not covered by a
QGRP
: entry is queued in the default queue.
Recipe 9.3 covers the
QUEUE_GROUP
macro. The access
database is used extensively in recipes throughout this book, with
particularly detailed coverage in Chapter 3 and
Chapter 6. The sendmail book
covers the QGRP
: record in Section 11.4.4.
In the system startup files, locate the command that starts sendmail
with the -bd
flag. Look for a line that is
something like the following:
/usr/sbin/sendmail -bd -q15m
Change the -q
argument to a -qp
argument. For example:
/usr/sbin/sendmail -bd -qp
Terminate the currently running sendmail daemon queue processor:
# kill -TERM `head -1 /var/run/sendmail.pid`
Start a new daemon process using the new command-line arguments:
# /usr/sbin/sendmail -bd -qp
The first step in this recipe modifies the startup script so that sendmail starts with the correct command-line arguments every time the system reboots. On some systems, finding and changing the line that starts sendmail at boot time is simple; on some other systems it is more complicated. Different Unix versions use different techniques to start sendmail at boot time, but all have some technique.
Most versions of Unix use a command similar to the following one to start the sendmail daemon:
/usr/sbin/sendmail -bd -q15m
This line contains two options: -bd
and
-q
. Use -bd
to accept inbound
mail. The -bd
argument causes sendmail to listen
for inbound mail on the configured TCP ports, which, by default, are
ports 25 and 587. Without a daemon running with
-bd
set, a properly configured system can still
send outbound mail, but it will not collect inbound mail.[2] The
-q
option causes the daemon to periodically start
queue processors. In this particular example, the daemon is told to
start queue processors every 15 minutes (15m
).
This recipe changes the -q
flag to
-qp
. Changing the -q
flag to
-qp
runs this daemon as a persistent queue
processor. The difference between forking a queue runner every 15
minutes with -q15m
and requesting a persistent
queue runner with -qp
is significant. In the first
case, a new queue runner is launched every 15 minutes without regard
to the status of the previous queue run. In the second case, a new
queue runner is launched one second after the previous queue run
completes. One second is the default interval timer for the
-qp
option. It can be changed on the command line
by defining a different interval value; for example,
sendmail
-qp15s
would set the
interval to 15 seconds. However, one second is a good value. It
provides essentially continuous queue processing without any
interference between queue runners because the interval timer for the
next queue runner doesn’t start until the current
queue run finishes.
At the start of every queue run, the queue runner
reads all
of the qf files, extracts certain control
information, sorts it, and uses it to control the order in which
queued messages are delivered. A persistent queue runner can be
beneficial when an individual queue is so large that this first step
takes longer than the selected queue interval. For example, using
-q15m
sets the queue interval to 15 minutes. If
the initial step took 30 minutes, sendmail would start another queue
runner at the 15-minute point and a third at the 30-minute point.
Each runner would repeat the initial step only to be succeeded by
additional runners doing the same job. Unfortunately, additional
queue runners do not always speed up this first step. In fact, they
sometimes interfere with each other so much that they slow things
down. Using persistent queue runners avoids this problem.
When a persistent queue runner is used, it is allowed to finish its job without the interference of other queue runners. The persistent queue runner finishes the first step, forks multiple processes to deliver the mail it has sorted, and sleeps the queue interval before awaking to do it again. Because the queue interval does not start until after the persistent queue runner has finished the sort, no other queue runners are started while it is running. This completely avoids the problems associated with multiple runners sorting the same queue.
In addition to modifying the boot script, Recipe 9.5.2 closes out the current sendmail
process with a SIGTERM and reruns sendmail from the command line
using the new options. After restarting sendmail, a
cat of the sendmail.pid
file would show the command line
/usr/sbin/sendmail
-bd
-qp
. Subsequent restarts of the daemon can be done
with the HUP signal because HUP uses the command found in
sendmail.pid to restart sendmail.
Because this recipe permanently changes the system’s default configuration, it is intended for systems where processing a very large queue is a chronic system problem. Manually running sendmail with settings that skip the time-consuming initial step is an alternative solution that can be used when the queue grows extremely large because of some unusual circumstance. In that case, kill all of the currently running sendmail processes and then enter the following command:
# /usr/sbin/sendmail -OQueueSortOrder=filename -q15m
This QueueSortOrder
option tells
sendmail to deliver the mail in filename
order. Alternatives are to deliver the queued mail in random order by
using -OQueueSortOrder=random
or in order of
modification time from the oldest to the newest by using
-OQueueSortOrder=modtime
. In all of these cases,
the qf files are not opened and read. Therefore
the delivery order is not optimized. However, an enormous amount of
time is saved at the start of the queue process, which is just what
is needed to clear out an overstuffed queue. Once the queue is clear,
kill this special copy of sendmail and restart the normal
configuration.
Use Recipe 9.5 when chronic system
performance problems are routinely caused by the overhead of
processing very large mail queues. Use the
QueueSortOrder
option as a quick fix for an
unusual queue processing problem.
The sendmail book describes persistent queue
runners in Section 6.1 and the QueueSortOrder
option in Section 6.1.1. The sendmail book
provides interesting statistics about the queue processing time based
on queue size and on the performance gains using these alternate
solutions. Chapter 3 of sendmail Performance
Tuning, by Nick Christenson (Addison Wesley), covers queue
contention and recommends solutions for this problem.
Special configuration is required to route mail to a queue server instead of queuing it locally.
Configure a system with a large amount of storage to act as a queue server. Configure the server to:
Have abundant queue storage. See Recipe 9.1 for information on creating multiple queues that span multiple physical devices.
Use a long queue interval. It should be at least one hour; e.g.,
-q1h
.
Act as a relay server for its queue clients. See Chapter 3 for information on granting relaying privileges to clients.
Configure clients to use the queue server using the
confFALLBACK_MX
define in the
client’s sendmail configuration. Assume that the
queue server created in the first step is
jamis.wrotethebook.com. Here is a sample define
that could be added to the client’s sendmail
configuration to use that server:
dnl Use jamis as the fallback mail exchanger define(`confFALLBACK_MX', `jamis.wrotethebook.com')
Rebuild and install /etc/mail/sendmail.cf, then restart sendmail (see Recipe 1.8).
MX records tell sendmail where to deliver mail. sendmail looks up the MX records for a recipient address. If there are no MX records for the recipient host, sendmail attempts to deliver to the recipient host itself using the host’s address record or CNAME record. If DNS returns MX records for the recipient host, sendmail attempts to deliver mail to each mail exchanger in order. If none of these delivery attempts is successful, sendmail queues the mail. For example, imagine sendmail needs to deliver mail to wrotethebook.org and that the MX records provided are:
wrotethebook.org. IN MX 10 mail.example.com. wrotethebook.org. IN MX 20 oreilly.com.
sendmail first tries delivering the message to
mail.example.com. If it works, sendmail is done.
If delivery fails, it tries delivering to
oreilly.com.[3] If that delivery fails, the mail is queued.
confFALLBACK_MX
changes this last step.
The host defined by confFALLBACK_MX
is treated as
the mail-exchanger-of-last-resort for all deliveries. When mail
cannot be successfully delivered to any of the mail exchangers listed
on the MX records provided by DNS, sendmail sends the mail to the
host specified by the confFALLBACK_MX
define. If
there are no MX records for the recipient host, sendmail attempts to
send the mail using the host’s A or CNAME record,
and if that attempt fails, the mail is sent to the
confFALLBACK_MX
host. Additionally, if DNS does
not respond to any of sendmail’s queries for the
recipient host’s MX, A, or CNAME records, the mail
is sent to the host defined by confFALLBACK_MX
.
All of this prevents the mail from being queued on the client.
When the fallback mail exchanger receives the mail, it treats it as mail being relayed to the recipient. This means that it will only accept the mail if the client has been granted relaying privileges. If the fallback mail exchanger accepts the mail, it retrieves the recipient’s MX records from DNS and attempts delivery. If it is unable to deliver the mail, it queues it.
The advantage of this approach is that the bulk of systems (i.e., the clients) can be optimized to handle the average case, and the queue server can be optimized to handle queue processing. Recipe 9.7 describes one case of optimizing clients to operate in this environment. The disadvantage of using a queue server is that there are two failed delivery attempts before the mail is queued, although this does not result in any delay in delivering the mail.
A sendmail
-bt
test shows the
effect of this recipe:
#sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >/mx aol.com
getmxrr(aol.com) returns 5 value(s): mailin-02.mx.aol.com. mailin-04.mx.aol.com. mailin-03.mx.aol.com. mailin-01.mx.aol.com. jamis.wrotethebook.com. >/mx sendmail.org
getmxrr(sendmail.org) returns 5 value(s): smtp.neophilic.net. services.sendmail.org. smtp.gshapiro.net. playground.sun.com. jamis.wrotethebook.com. >/quit
The /mx
command returns the MX list sendmail will
use to deliver to the specified recipient host. No matter what
recipient host is entered with the /mx
command,
the last system in the list is the host defined by
confFALLBACK_MX
.
Important background information for configuring a queue server is
found in Chapter 3 and earlier in this chapter.
The sendmail book covers
confFALLBACK_MX
in Section 24.9.45, and it
provides an excellent discussion of using a queue server in Section
6.2.2. Section 6.3.1 of sendmail Performance
Tuning, by Nick Christenson (Addison Wesley), provides
additional information on using queue servers.
Create a queue server as described in Recipe 9.6.
On the clients of that server, add defines to the sendmail
configuration to quickly timeout bad connections and to quickly
timeout remote systems that fail to respond to or provide SMTP
commands in a timely manner. Here are sample protocol timer defines
that could be used with the confFALLBACK_MX
define:
dnl Use jamis as the fallback mail exchanger define(`confFALLBACK_MX', `jamis.wrotethebook.com') dnl Set the protocol timers to low levels define(`confTO_CONNECT', `15s') define(`confTO_COMMAND', `5m') define(`confTO_DATABLOCK', `5m') define(`confTO_DATAFINAL', `5m') define(`confTO_DATAINIT', `15s') define(`confTO_HELO', `15s') define(`confTO_HOSTSTATUS', `15s') define(`confTO_ICONNECT', `15s') define(`confTO_INITIAL', `15s') define(`confTO_MAIL', `15s') define(`confTO_QUIT', `15s') define(`confTO_RCPT', `15s') define(`confTO_RSET', `15s')
Build sendmail.cf, copy it to /etc/mail/sendmail.cf, and restart sendmail, as described in Recipe 1.8.
The confFALLBACK_MX
define sets the value of the
FallbackMXhost
option in the
sendmail.cf file. Mail is sent to the server
defined by FallbackMXhost
when the client cannot
successfully deliver the mail.
This recipe sets various protocol timers low so that mail to slow or unresponsive hosts is also passed to the queue server for delivery. This recipe also optimizes the client for the average case—quick, successful mail deliveries—and sends all problematic mail to the queue server for delivery.
By default, sendmail has very generous SMTP protocol timers. These generous timers mean that sendmail will not give up delivery until it is sure the remote end is dead. This is great for ensuring delivery, but it ties up the sending system waiting for the remote system to respond. Setting short timeouts, such as those in this recipe, means that more deliveries fail, but it also means that the client is not tied up by slow deliveries. Because the queue server uses the default timeouts, much of the undelivered mail that timed out on the client is successfully delivered by the queue server on the first attempt.
Table 9-2 lists each timeout define used in this recipe, its purpose, and the default that is normally used.
The define command |
Sets timeout for |
Default |
|
The |
|
|
Waiting for the next command |
|
|
A read to complete |
|
|
Acknowledgment of the . at the end of the
|
|
|
Acknowledgment of the |
|
|
Acknowledgment of the |
|
|
How long host status information is saved |
|
|
Completion of the initial connection attempt |
|
|
Receipt of the greetings message |
|
|
Acknowledgment of the |
|
|
Acknowledgment of the |
|
|
Acknowledgment of the |
|
|
Acknowledgment of the |
|
This recipe reduces the timeout for most of these protocol timers to
15 seconds (15s
), which is enough time for most
computers to respond. Some exceptions are the timeout values set for
confTO_DATAFINAL
,
confTO_DATABLOCK
, and
confTO_COMMAND
, which are given a more generous
five minute timeout.
The values set in this recipe are based on the fast daemon example in Section 6.2.1 of the sendmail book. The values used here are more generous than those used in the sendmail book, but these values are more appropriate for our sample network. You need to create your own values based on the performance of your system and your network. The sendmail Performance Tuning book discusses protocol timers in Section 6.1.1.
Recipe 9.6 provides related material that should be reviewed before implementing this recipe. The sendmail book covers the use of these timers in Section 6.2, and, in particular, covers an alternate solution that uses the quick timers and the default timers on a system that does not use a queue server. The sendmail book also covers the timers in Section 24.9.109. sendmail Performance Tuning, by Nick Christenson (Addison Wesley), covers fallback MX hosts in Section 6.3.1.
[1] sendmail prior to Version 8.12 did not use the submit.cf file.
[2]
Recipe 10.1 configures sendmail to send
outbound mail without running a daemon with the
-bd
option.
[3] MX records are
looked up for every system in the MX list, except for the system
added by the confFALLBACK_MX
define.
3.145.94.251