Chapter 9. Managing the Queue

Introduction

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.

9.1. Creating Multiple Queues

Problem

You have been asked to create multiple mail queues spread over multiple physical devices in order to efficiently handle a large amount of mail.

Solution

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

Warning

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.

Discussion

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.

See Also

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.

9.2. Using qf, df, and xf Subdirectories

Problem

Special configuration is required to use multiple mail queues for the different queue file types.

Solution

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

Discussion

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:

df

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.

qf

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.

xf

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.

See Also

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.

9.3. Defining Queue Groups

Problem

Special configuration is required to define different mail queues with unique characteristics.

Solution

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.

Discussion

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.

Table 9-1. Queue group attributes

Keyword

Function

Flags=

Sets optional runtime flags.

Interval=

Specifies the time interval between queue runs.

Jobs=

Limits the number of envelopes processed during a single queue run.

Nice=

Defines the nice value used for the queue run.

Path=

The full pathname of the queue directory used for this queue group.

Recipient=

Sets the maximum number of recipients allowed for one envelope.

Runners=

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.

See Also

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.

9.4. Assigning Recipients to Specific Queues

Problem

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.

Solution

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.

Discussion

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.

See Also

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.

9.5. Using Persistent Queue Runners

Problem

Queues can become so large that queue runners interfere with each other.

Solution

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

Discussion

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.

Emergency queue clearance

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.

See Also

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.

9.6. Using a Queue Server

Problem

Special configuration is required to route mail to a queue server instead of queuing it locally.

Solution

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).

Discussion

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.

See Also

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.

9.7. Setting Protocol Timers

Problem

Clients require special configuration to quickly move problem mail to the queue server.

Solution

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.

Discussion

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.

Table 9-2. The SMTP protocol timers used in this recipe

The define command

Sets timeout for

Default

confTO_CONNECT

The connect system call to finish

5m

confTO_COMMAND

Waiting for the next command

1h

confTO_DATABLOCK

A read to complete

1h

confTO_DATAFINAL

Acknowledgment of the . at the end of the DATA block

1h

confTO_DATAINIT

Acknowledgment of the DATA command

5m

confTO_HELO

Acknowledgment of the HELO/EHLO command

5m

confTO_HOSTSTATUS

How long host status information is saved

30m

confTO_ICONNECT

Completion of the initial connection attempt

5m

confTO_INITIAL

Receipt of the greetings message

5m

confTO_MAIL

Acknowledgment of the MAIL From: command

10m

confTO_QUIT

Acknowledgment of the QUIT command

2m

confTO_RCPT

Acknowledgment of the RCPT To: command

1h

confTO_RSET

Acknowledgment of the RSET command

5m

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.

See Also

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.94.251