Mail messages can be either delivered immediately or held for later delivery. Held messages are referred to as “queued.” They are placed into either a single holding directory (usually called mqueue) or several directories from which they are later delivered. There are many reasons a mail message might be queued:
If a mail message is temporarily undeliverable, it is queued and delivery is attempted later. If the message is addressed to multiple recipients, it is queued only for those recipients to whom delivery is not immediately possible.
If the SuperSafe
option (SuperSafe on page 1096) is
set to true (the
default setting required by RFC2821), all mail
messages are queued for safety while delivery is
attempted. The message is removed from the queue
only if delivery succeeds. If delivery fails, the
message is left in the queue, and another attempt is
made to deliver it later. This causes the mail to be
saved in the unhappy event of a system crash during
processing.
If sendmail is run with the
DeliveryMode
option (DeliveryMode on page 1004)
set to queue-only
or to defer, all
mail is queued, and no immediate delivery attempt is
made. A separate queue run is required to attempt
delivery.
If the load (average number of blocked processes)
becomes higher than the value given to the QueueLA option (QueueLA on page 1072),
sendmail will queue a message
rather than attempt to deliver it. (Beginning with
V8.14, this load average cutoff can be more finely
tuned by using the DaemonPortOptions option’s queueLA key; DaemonPortOptions=queueLA= (8.14 and
later) on page 997). A separate queue run is required
later to process the queue.
The sendmail queue is implemented by
placing held messages into one or more directories. Prior to
V8.10, there was only one directory, and its name was
usually mqueue. Now, the directory or
directories to be used are specified in the configuration
file with the QueueDirectory option (QueueDirectory on page 1070):
OQ/var/spool/mqueue ← pre-V8.7 form O QueueDirectory=/var/spool/mqueue ← beginning with V8.7 O QueueDirectory=/var/queues/q.* ← V8.10 multiple directories
If the QueueDirectory
option is missing, the name defaults to mqueue. The location
should never be relative (as mqueue). When it is wrongly specified as
a relative path name, it is taken as relative to the
location where sendmail is run. Because
the sendmail daemon is typically
started from an rc file at boot time,
such relative locations are usually relative to the
root (/) directory.[175]
After sendmail has processed its configuration file, it does a chdir(2) into its base queue directory and does all the rest of its work from there. In the first two lines of the previous example, the base queue directory is /var/spool/mqueue. In the last line, the base queue directory is /var/queues. This change into the base queue directory has three side effects:
Should the sendmail program fault and produce a core dump, the core image is left in the base queue directory.
Any relative pathnames that are given to
options in the configuration file are interpreted
as relative to the base queue directory. (This is
not true for the F configuration command, The F Class Command on page 857. Those
files are processed at the same time as the
configuration file, before the
chdir.)
If you use V8.12 and later queue groups (Queue Groups (V8.12 and Later) on page 408), all the queues used by those queue groups must be subdirectories of the base queue directory.
The base queue directory, and all subdirectories under it,
should be set to have very narrow permissions. They must be
owned by root. We (and CERT) recommend
a mode of 0700. Prior to V8 sendmail,
such narrow permissions would cause C-shell scripts run from
a ~/.forward file to fail. V8
sendmail lets you specify
alternative directories in which to run programs (see the
D= delivery agent
equate, D= on page 741). This allows
you to use mode 0700 queue directories without the
associated problems.
As a further precaution, all the components of the path leading to the queue directories should be owned by root and be writable only by root. In the case of our example of /var/spool/mqueue, permissions should look like this:
drwxr-xr-x root / drwxr-xr-x root /var/ drwxr-xr-x root /var/spool/ drwx------ root /var/spool/mqueue/
For additional security, see the restrictmailq keyword for the PrivacyOptions option
(PrivacyOptions=restrictmailq on page 1069). It allows only users in the same group as
the group ownership of the queue directory to be able to
print its contents with mailq or
-bp (Printing the Queue on page 422).
When a message is stored in the queue, it is split into
pieces. Each piece is stored as a separate file in the queue
directory. That is, the header and other information about
the message are stored in one file, while the body (the
data) is stored in another. All told, six different types of
files can appear in the queue directory. The type of each is
denoted by the first two letters of the filenames. Each
filename begins with a single letter followed by an f character. The complete
list is shown in Table 11-1.
|
File |
§ |
Description |
|
|
The Data (Message Body) File: df on page 398 |
Data (message body) |
|
|
Queue File Locking on page 398 |
Lock file (obsolete and removed as of V5.62) |
|
|
The ID Creation File (Obsolete As of V5.62): nf on page 399 |
ID creation file (obsolete and removed as of V5.62) |
|
|
The Temporary qf Rewrite Image: tf on page 400 |
Temporary |
|
|
The Transcript File: xf on page 401 |
Transcript file |
|
|
The Queue Control File: qf on page 399 |
Queue control file (and headers) |
The complete form for each filename is:
XfidentThe X is one of the leading letters shown
in Table 11-1. The f is the constant letter
f. The
ident is a unique queue
identifier associated with each mail message.
In the following sections, we first describe the identifier
that is common to all the queue file parts, then describe
each file type in alphabetical order. The internal details
of the qf file can vary
depending on the version of sendmail,
so it is discussed separately at the end of this
chapter.
To ensure that new filenames are not the same as the
names of files that might already be in the queue,
sendmail uses the following
pattern for each new
ident:
AApid ← prior to V8.6 hourAApid ← beginning with V8.6 YMDhmsSEQpid ← beginning with V8.10
Here, pid is the process
identification number of the incarnation of
sendmail that is trying to
create the file. Because
sendmail often
fork(2)s to create queue
entries, that pid is
likely to be unique, resulting in a unique
ident. The AA is used as a clock to
prevent duplicate filenames. For V8.6 through V8.9
sendmail, an extra letter
prefixes the AA.
Shown as hour, it is an
uppercase letter that corresponds to the hour (in a
24-hour clock) that the identifier was created. For
example, a file created in hour three of the day
will have a D
prefixed (the hour begins at midnight with A).[176]
For V8.10 sendmail, the identifier is constructed differently. Each character stands for (in this order, reading left to right): the year (minus 1900) modulo 60, the month, the day, the hour, the minute, the second, and a sequence within the second that starts at a random value. Each is used as an offset into a special array that looks like this:[177]
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
Thus, the following identifier:
lC9GgvB04136
means the year is 2007 (the l), the month is December (the C), the day is the 9th
(the 9), the time
is 16:42:57 (the Ggv), the sequence is 11 (the B), and the process ID
of the process that created the file is 04136. The
advantage to this algorithm is that no two
identifiers will ever be the same during a given
60-year period. Although this latest method has
stayed the same from V8.10 through V8.14, there is
no guarantee that it will remain the same in future
releases.
Prior to V8.10, if sendmail could
not create an exclusive filename because a file with
that identifier already existed, it clocked the
second A of the
AA to a
B and tried
again. It continued this process, clocking the
righthand letter from A to Z and the lefthand letter from A to ˜ until it
succeeded:
AA ← start AB ← second try AC ← third try ... and so on ˜W ˜X ˜Y ← last try ˜Z ← failure
If it never succeeded, the
ident became one like
the following and sendmail
failed:
hour˜ZpidBut this ident was unlikely
to ever appear because the clocking provided for
more than 1,600 possibilities.
All the files associated with a given mail message
share the same ident as a
part of their filenames. The individual files
associated with a single mail message differ only in
the first letter of their names.
All mail messages are composed of a header and a body.
When queued, the body is stored in the df file.
Traditionally, the message body could contain only
characters that had the high (most significant) bit
turned off (cleared, set to 0). But under V8
sendmail, with a version 2 or
higher configuration file (The V Configuration Command on page
580) the high bit is left as is until delivery
(whereupon the F=7 delivery-agent flag, see F=7 on page 764, determines
whether that bit will be stripped during
delivery).
Because the message body can contain sensitive or
personal information, the df file should be protected from
reading by ordinary users. If the queue directory is
world-readable, the TempFileMode option (TempFileMode on page 1097) should
specify minimum permissions (such as 0600) for
queued files. But if the queue directory is
protected by both narrow permissions and a secure
machine, the TempFileMode option can be relaxed for
easier administration.
There is currently no plan to provide for encryption
of df files. If
you are concerned about the privacy of your message,
you should use an end-to-end encryption package or
an encrypting filesystem (not discussed in this
book).
When old versions of sendmail
process a queued message (attempt to redeliver it)
they create an empty lock file. That lock file was
needed to signal other running
sendmail processes that the
mail message was busy so that they shouldn’t try to
deliver the message too. Current versions simply
flock(2) or
fcntl(2) lock the qf file.
The method that sendmail uses to initially create an exclusive lock when first queueing a file is twofold. First it attempts to creat(2) the file with the argument:
O_CREAT|O_WRONLY|O_EXCL
If that succeeds, it then attempts to lock the
file. If HASFLOCK (HAS... on
page 114) is defined when
sendmail is compiled, the
file is locked with flock(2).
Otherwise, it is locked with a
fcntl(2) F_SETLK argument.
When mailq is run (or the
-bp
command-line switch is given to
sendmail), the contents of
the queue are listed. In that listing, an asterisk
that appears to the right of an identifier
indicates that a lock exists on the
message:
/var/spool/mqueue/df (1 request)
----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------
dB91UPA04168* 0 Wed Dec 8 17:30 <gw@wash.dc.gov>
↑
<ben@franklin.edu
noteOccasionally, a file will become locked and remain that way for a long time. One indication of a stuck lock is a series of syslog messages about a given identifier:
Apr 12 00:33:38 ourhost sendmail[641]: dB91UPA04168: locked Apr 12 01:22:14 ourhost sendmail[976]: dB91UPA04168: locked Apr 12 02:49:23 ourhost sendmail[3251]: dB91XUs04170: locked Apr 12 02:49:51 ourhost sendmail[5977]: dB91UPA04168: locked Apr 12 03:53:05 ourhost sendmail[9839]: dB91UPA04168: locked
An occasional lock message, such as dB91XUs04170 in the
third line in this example, is normal. But when an
identifier is continually reporting as locked
(such as the dB91UPA04168 lines), an orphaned lock
might exist and should be investigated. Use
ps(1) to look for lines that
list queue file identifiers:
root 5338 160 -dB91UPA04168 To wash.dc.gov (sendmail)
This shows that the queued mail message, whose
identifier is dB91UPA04168, is currently being
processed. If the lock on that file is stuck,
consider killing the sendmail
that is processing it.
Old versions of sendmail used an
nf file when
creating a message identifier to avoid race
conditions.[178] But contemporary versions of
sendmail create the queue
identifier when first creating the qf file. The nf file is
obsolete.
A queued mail message is composed of two primary
parts. The df
file contains the message body. The qf file contains the
message header.
In addition to the header, the qf file also contains
all the information necessary to:
Deliver the message. It contains the sender’s address and a list of recipient addresses.
Order message processing. It contains a priority that determines the current message’s position in a queue run of many messages.
Expire the message. It contains the date that the message was originally queued. That date is used to time out a message.
Explain the message. It contains the reason that the message is in the queue and possibly the error that caused it to be queued.
The qf file is
line-oriented, with one item of information per
line. Each line begins with a single uppercase
character (the code letter), which specifies the
contents of the line. Each code letter is then
followed by the information appropriate to the
letter. The code letters and their meanings are
shown in Table 11-6
on page 446.
Here is an example of a version 8 (for V8.14
sendmail) qf file:
V8
T944703473
K0
N0
P1
I7/22/19133
Fwbs
$_you@localhost
${daemon_flags}c u
Syou@your.domain
Ayou@your.domain
rRFC822; george@wash.dc.gov
RPFD:george@wash.dc.gov
H?P?Return-Path: <you>
H??Received: (from you@localhost)
by your.domain (8.14.1/8.14.1) id g38DcXCL026713
for george@wash.dc.gov; Fri, 14 Dec 2007 17:37:53 −0800 (PST)
H?D?Date: Fri, 14 Dec 2007 17:37:53 −0800 (PST)
H?F?From: Your Name <you>
H?x?Full-Name: Your Name
H?M?Message-Id: <200704081338.g38DcXCL026713@your.domain>This fictional qf
file shows the information that will be used to send
a mail message from you@your.domain
(the S line) to
one recipient: george@wash.dc.gov
(the R line). It
also shows the various headers that appear in that
message (the H
lines). We discuss the individual lines of the
qf file at the
end of this chapter.
When processing a queued message, it is often
necessary for sendmail to
modify the contents of the qf file. This usually occurs if
delivery has failed or if delivery for only a part
of the recipient list succeeded. In either event, at
least the message priority needs to be
incremented.
To prevent damage to the original qf file,
sendmail makes changes to a
temporary copy of that file. The temporary copy has
the same queue identifier as the original, but its
name begins with a t.
After the tf file
has been successfully written and closed,
sendmail calls
rename(2) to replace the
original with the copy. If the renaming fails,
sendmail syslog(3)s at
LOG_CRIT a message such as the following:
cannot rename(tfdB91brx04175, qfdB91brx04175), df=dfdB91brx04175
Failure to rename is an unusual but serious problem: a
queued message has been processed, but its qf file contains old and
incorrect information. This failure might, for
example, indicate a hardware error, a corrupted
queue directory, or that the system administrator
accidentally removed the queue directory.
A given mail message can be destined for many recipients, requiring different delivery agents. During the process of delivery, error messages (such as “User unknown” and “Permission denied”) can be printed back to sendmail by each delivery agent.
While calling the necessary delivery agents,
sendmail saves all the error
messages it receives in a temporary file. The name
of that temporary file begins with the letters
xf. After all
delivery agents have been called,
sendmail returns any
collected error messages to the sender and deletes
the temporary xf
file. If there are no errors, the empty xf file is silently
deleted. A -d51.104 debugging switch setting can
be used to prevent deletion of the xf file.
See Using qf, df, and xf Subdirectories on page 403 for a way to relocate xf files to a
memory-based filesystem.
Beginning with V8.10, sendmail allows the use of multiple queue directories. These multiple queue directories take two forms:
More than one queue directory can be
specified, possibly on separate disks, into which
all the qf,
df, and
xf files are
placed.
Any queue directory can have a subdirectory
named qf,
and/or df,
and/or xf, in
which sendmail stores the
corresponding qf, df, and xf files.
V8.10 sendmail offers the ability to distribute queued messages across multiple directories. In general, this is a good idea. If, for example, a high volume of email is stressing your current disk, you can improve efficiency by using multiple queue directories spread over multiple disks and controllers.
To illustrate, we will set up a machine that has three brand-new disks to use as multiple queue directories. The disks have already been formatted and a filesystem has been placed on each. We next create directories on which to mount them:
#mkdir /var/queues /var/queues/q.1 /var/queues/q.2 /var/queues/q.3#chmod 700 /var/queues /var/queues/q.?
Because of the way multiple queue directories are implemented inside sendmail, the queue directory names must differ only in their suffixes, hence the trailing 1, 2, and 3. First the directories are created with mkdir(1) or a symbolic link, and then the permission on each is reduced to readable and writable only by root for security reasons. Note that these are the permissions after all queue disks are mounted.
Next, arrange for the disks to be mounted by placing the appropriate entries in /etc/fstab or /etc/vfstab. Here, we illustrate with the partial contents of /etc/fstab for Linux:
/dev/hda2 /var/queues/q.1 ext2 defaults 1 1 /dev/hdb1 /var/queues/q.2 ext2 defaults 1 1 /dev/hdc1 /var/queues/q.3 ext2 defaults 1 1
Note that we are mounting a separate disk on each queue directory. Your disk device names will doubtless differ, and you can use any directory locations and names you wish. Note that after you mount the disks, you might need to change the permissions again to 700 for each mount point.
The idea is to prepare the directories for use as multiple queue directories first, and after that, to modify the configuration file so that sendmail can use those queue directories:
define(`QUEUE_DIR',`/var/queues/q.*')
Here, the QUEUE_DIR mc
configuration macro is given the value /var/queues/q.*, which
will become the value for the QueueDirectory option.
The trailing *
character is a literal asterisk (not a wildcard
character) and must appear as a suffix, in the last
position of the path specification. It tells
sendmail to use all the queue
directories that begin with the path
/var/queues/q. and end with
any other characters. In our example,
sendmail will match
/var/queues/q.1,
/var/queues/q.2, and
/var/queues/q.3.
It is not strictly necessary to mount a disk on each queue directory. If the directory name is a symbolic link to another directory, sendmail will use that other directory as a queue directory. The only requirement is that the other directory has as restrictive set of permissions as the original queue has.
After you have configured for multiple queue directories, you will find there is a small difference in the way various versions of sendmail print the queue contents. Prior to V8.10 sendmail, the heading for a queue listing printed like this:
Mail queue is empty ← when nothing is queued (pre-V8.10) Mail queue (1 request) ← when one message is queued (pre-V8.10)
Starting with V8.10 sendmail, that heading now looks like this:
/var/spool/mqueue is empty ← when nothing is queued (V8.10 and later) /var/spool/mqueue (1 request) ← when one message is queued (V8.10 and later)
The full pathname of the queue is printed, regardless of whether you are running multiple queue directories. This behavior is beneficial when running multiple queue directories because it lets you know which queue directory contains what mail:
/var/spool/mqueues/q.1 is empty
/var/spool/mqueues/q.2 (1 request)
----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------
dB9Fdaa06420 4567 Thu Dec 9 07:39 you@your.domain
<gw@us.gov>
Total Requests: 1From this output, it is clear that q.1 is empty and q.2 contains a single message. Unfortunately, the two headings indent differently, but that’s easy to get used to.
In the previous output, also notice that when multiple queue directories are printed, a trailing line is printed after all queue directories are printed that shows the total of all messages in all queue directories. If you run dozens or hundreds of queue directories, you might find it useful to summarize the number of queued messages like this:
% mailq -OMaxQueueRunSize=1 | tail −1
Total Requests: 41291The expression -OMaxQueueRunSize=1 (MaxQueueRunSize on page 1050) causes
sendmail to process each
queue directory extremely fast, regardless of how
many messages are queued in each.
When sendmail processes
multiple queue directories it processes them in
parallel. That is, it forks and runs a queue
processing child of sendmail
for each, all of which run at the same time. The
maximum number of sendmail
queue processors run is limited by the MaxDaemonChildren option
(MaxDaemonChildren on page
1044). If that limit is reached before all the
queue directories can be parallel-processed,
sendmail will remember where
it stopped and perform the next run starting from
where the prior run left off.
The only exception to this behavior occurs
when queue processing with the -v (verbose)
command-line switch. When -v is combined with -q, processing is always
sequential. That is, one queue directory is
processed at a time, and the next is not begun
until the first finishes. The -v allows you to watch
the queue being processed, so it makes sense that
you would want to watch only one queue directory
at a time.
Beginning with V8.10, sendmail
allows the qf,
df, and
xf files to
reside in separate directories. One advantage to
this is that it produces directories that are
one-third smaller. Another advantage is that each
part can reside on a separate disk for further
performance enhancements.
This feature is enabled by simply creating the
appropriately named subdirectories, or symbolic
links, in each queue directory. The names of those
subdirectories or symbolic links are the literals
qf, df, and xf. But be aware that
you should not create those directories or links
when mail is already queued. If you do, that queued
mail will disappear from
sendmail’s view and will
never be delivered. If you need to make the change
while mail is queued, first stop
sendmail, and then execute
the following commands and restart
sendmail:
#mkdir df qf xf#chmod 700 df qf xf#mv df?* df/← if mail is already queued #mv qf?* qf/← if mail is already queued #mv xf?* xf/← if mail is already queued
Here, we first create the new subdirectories in the queue directory. Then we reduce their permissions to the narrow ones that match the queue directory. Finally, if queued mail already existed in the queue directory, we move that mail into the new subdirectories where sendmail will find it.
Because xf files
are empty for all successfully delivered mail, there
is a penalty for creating and deleting those files
just because they might be needed. When performance
is of concern, you can either mount a memory
filesystem on the xf subdirectory, or replace the
xf subdirectory
with a symbolic link to a directory on a memory
filesystem. In the following, we show an
/etc/fstab file for a SunOS
machine that uses the direct-mount approach:
/dev/sd0g /var/spool/mqueue/df 4.2 rw 1 4 /dev/sd2g /var/spool/mqueue/qf 4.2 rw 1 2 swap /var/spool/mqueue/xf tmp rw 0 0
Shortly. we will describe how to use a different type of disk for each part, and how performance is impacted by such choices.
An artifact of using qf, df, and xf subdirectories is seen when printing
the queue. The df
directory is always the one listed:
/var/spool/mqueue/df is empty
To understand the potential problems associated with
deep queues, first consider how
sendmail processes a single
queue when its QueueSortOrder option (QueueSortOrder on page 1073) is set to
the default of priority.[179] When sendmail is
instructed to process a queue it opens the queue
directory for reading and reads that directory to
gather a list of qf files to process. Each qf file
sendmail finds is opened for
reading and scanned for important pieces of
information. The N line in each qf file, for example, holds the number
of times the message has been tried. The P line holds each
message’s current priority.
After all messages have been opened, read, and closed, and after the information from each has been saved internally, sendmail sorts that information. The purpose of the sort is to ensure that new mail is tried before old, and that high-priority mail is tried before low-priority mail.
Under normal circumstances, this process occurs quickly. But when queues get abnormally deep, things can go wrong. In the following, which illustrates a problem that can occur, we show one way that sendmail could be run on a major mail-sending machine:
/usr/sbin/sendmail -bd /usr/sbin/sendmail -q10m
The idea here is to create two mail-handling daemons. The first handles inbound mail, and because this is a mail-sending machine, we expect that this inbound daemon will perform little work. The second daemon sends all mail it finds in its queue. It will fork(2) a copy of itself once every 10 minutes, and that copy will process all the messages in the queue. As described earlier, each queued message is opened and read so that all the messages can be sorted before delivery begins.
Because this hypothetical site is a major mail-sending site, we expect a high rate for the number of sent messages. For the sake of argument, let’s say 30,000 messages need to be sent per hour.
Now suppose a backhoe, a power failure, clumsy fingers, or any of a thousand possible disasters causes this site’s only connection to the Internet to fail for an hour, and the site can neither look up host information with DNS, nor connect to any remote sites. All the mail it tries to send that hour fails, and instead of being removed from the queue, this failed mail is left there to be tried again later (presumably after the problem is fixed).
An hour later, service is restored. First, the default:
/usr/sbin/sendmail -q10m
causes a forked copy of sendmail to start processing the queue. This time, however, the processing is not swift. When a queue fills to 30,000 or more messages, the amount of time it takes to preread the queue (to open and read every message) increases to more than 20 minutes.[180] And those 20 minutes are only for the preread. During those 20 minutes no mail will be sent.
After that, things get worse. Ten minutes later a second sendmail daemon is forked, and it, too, starts to preread the queue. Now, instead of one sendmail daemon opening and reading all messages in a queue, we have two sendmail daemons doing the same thing in parallel.
Contrary to what you might think, twice as much I/O on a disk is not twice as fast. Disks are finite devices that perform a limited number of disk-head moves[181] per second and can transmit only a fixed number of bytes per second. Because the two sendmail daemons are 10 minutes out of step with each other, each is reading and processing separate files. Depending on the size of your in-memory disk cache, neither will likely be able to take advantage of the efficiencies of such caching. In short, two sendmail daemons processing a deep queue in parallel is worse than a single sendmail daemon processing that same queue alone.
And if that weren’t enough, another 10 minutes later a third sendmail daemon starts to process the queue.
By now, the first sendmail daemon might have finished its preread of the queue and might have actually begun to send messages. But even if it has, three sendmail daemons are now processing that single deep queue and a curious thing happens. Because the disk that holds the queue is finite, the addition of a third sendmail daemon slows the operation of the first two. The second one, instead of taking 20 minutes to preread the queue, will now take 30 minutes.
This means that every 10 minutes another sendmail queue-processing daemon is added to the mix. As each is added, each slows all the others that are already running, and it isn’t long before the load on the machine starts to climb and the rate at which messages are delivered falls at an alarming rate. In fact, when this sort of behavior hits a very large-volume site, a sendmail queue-processing daemon can start and seem to never finish.
Depending on the speed of your disk system, even limiting the number of queue processors per queue might not save you from this sluggish performance. Under V8.12 sendmail, for example, you can limit the number of queue runners per queue with a queue group (Queue Groups (V8.12 and Later) on page 408) definition such as this in your mc configuration file:
QUEUE_GROUP(`fastq', `P=/q/fastq*, I=10m, R=10')
Here, the fastq
group uses the queue disks mounted as /q/fastq*, processes
those disks once per 10 minutes (the I=10m), and limits
itself to 10 queue runners maximum (the R=10) across all the
disks. If there are few fastq* queue disks, and if they fill to
more than 30,000 messages each, they too can become
sluggish, even with only 10 runners processing them.
In fact, with sufficient filled queue depth, as few
as two simultaneous queue runners can seriously
affect performance.
In extreme situations such as this, one alternative is to use persistent queue runners (Persistent Queue Runners with -qp on page 434). With persistent queue runners, you maintain a single queue runner that alone reads the queue. After that single queue runner has read the queue, it forks multiple child queue runners to process the queue, with each child sharing the parent’s queue information:
/usr/sbin/sendmail -qp10m
Here, the -qp
causes one or more persistent queue runners to
launch. One is launched for each queue group, and
will persist to run, sleeping 10 minutes between
each reading of the queue. When it awakes, it
gathers a list of queue files and launches multiple
child processes to handle that list. After the last
child has finished delivery and exited, the parent
sleeps again.
Even with queue groups and persistent queue runners, you are encouraged to spread queues across many directories and across many disks and controllers. This increases parallelism and dramatically lessens the likelihood that any given queue will overfill.
When a queue directory is exceptionally full, you will likely notice the problem only when performance on your queue-handling machine becomes unusually sluggish. By that time, however, a drastic measure, such as rebooting the server, might be the only cure. Clearly, early detection is desirable.
Early signs that a queue is filling can be seen in the logging messages that sendmail produces. You can develop scripts that watch for lines such as these:
Dec 13 10:27:53 your.domain sendmail[642]: grew WorkList for /var/spool/mqueue to 2000
Dec 13 10:29:05 your.domain sendmail[642]: grew WorkList for /var/spool/mqueue to 3000
Dec 13 10:34:31 your.domain sendmail[642]: grew WorkList for /var/spool/mqueue to 4000
... etc., to:
Dec 13 12:40:22 your.domain sendmail[642]: grew WorkList for /var/spool/mqueue to
29000
Dec 13 12:42:50 your.domain sendmail[642]: grew WorkList for /var/spool/mqueue to
30000Here, the WorkList
refers to the number of messages preread so far. By
searching for unusual sizes, you can determine when
a queue is about to overfill.
Another technique is to run the mailq command to observe the total number of messages queued across all queues:
%mailq -OMaxQueueRunSize=0 | tail −1← V8.7 through V8.11 Total Requests: 34190 %mailq -bP← V8.12 and later /var/spool/mqueues/q.1/df: entries=34190 Total requests: 34190
For V8.7 through V8.11, the MaxQueueRunSize=0 allows
mailq to run swiftly,
regardless of how deep the queue or queues might be.
Without that option, and with deep queues,
mailq would be just as slow
as the sluggish queue runs, but beginning with
V8.12, the -bP
command-line switch does the same thing more
quickly.
No matter how you detect the problem, the solution will be the same. First, you need to kill all the competing sendmail queue-processing daemons. There are a wide number of ways to do this. The most common is to use ps(1) to gather PID numbers and then kill each queue-processing daemon individually. No matter how you kill the queue-processing daemons, be sure to kill them all. If you don’t, you might find the problem surfacing again before you have had a chance to fix it.
The best way to flush a full queue is with a command line something like this:
#/usr/sbin/sendmail -OQueueSortOrder=filename -q10m -d99.100#/usr/sbin/sendmail -OQueueSortOrder=random -q10m -d99.100← V8.12 and later #/usr/sbin/sendmail -OQueueSortOrder=none -q10m -d99.100← V8.13 and later
Here, the -d99.100
tells sendmail to run in the
foreground (so that you can kill it easily when
done). The -q10m
causes a queue-processing daemon to be launched once
each 10 minutes (just like before). You need this
because one daemon can seem to hang when delivering
mail to a slow host. By running parallel daemons,
you avoid this pitfall.
Sorting by filename
or random (How the Queue Is Processed on page
426) or none
(V8.13 and later) causes
sendmail to skip the opening
and reading of each queued message. Instead, it only
looks at the filename for its sorting or randomizing
order. On the downside, this prevents
sendmail from grouping
messages for optimum delivery. On the upside, this
reduces the time to preread a huge queue from 20 or
so minutes to less than 2 seconds.[182]
The QueueSortOrder=random (QueueSortOrder=random (V8.12 and
later) on page 1074) is just like the QueueSortOrder=filename
shown earlier, except that it randomizes the list
before beginning delivery. This method is preferred,
but is only available beginning with V8.12
sendmail.
After draining the full queue to a more manageable level, you can discontinue this special process and rerun sendmail in its normal manner.
If the full queue has to remain in service while the full state is being solved, you can use the techniques in Handling a Down Site on page 437 to move that full queue out of the way so that it can be processed in the background.
As of V8.12 sendmail, it is possible to group queues according to selected criteria, and then to process each group with custom settings. This versatile ability is enabled and tuned with:
The QUEUE_GROUP mc configuration command, which defines queue groups and sets their group properties
The FEATURE(queuegroup), which allows you
to select queue groups based on recipient hosts
via the access
database
More sophisticated queue group selections, which you can make by writing your own rule sets
You can best tune queue groups by first understanding their limitations. We cover these topics in this section, but first we need to briefly discuss the default queue group.
Prior to V8.12 sendmail, there
were no queue groups. Instead, every -q command and every
queue option (such as QueueDirectory) applied to all the
queue directories you had.[183]
Beginning with V8.12, sendmail
offers a way to define multiple queue directories
and a way to group them by function or specialty.
For compatibility with old versions, a special queue
group named mqueue is the default queue group. It
takes on all the properties of every -q command, and every
queue option, just like before.
When you later declare particular queue groups (as we show in the next section), those additional groups take all their properties from the default group, unless you override a particular property with a specific equate. Those equates and the command-line arguments or options they override are shown in Table 11-2 on page 410.
For example, the following declares two different queue directories:
define(`QUEUE_DIR', `/var/spool/mqueue') QUEUE_GROUP(`regularmail', `') QUEUE_GROUP(`slowmail', `P=/var/spool/mqueue/slowqueue')
The first line declares the queue used by the default
group (always known as mqueue). Any other queue groups that
are declared (such as regularmail) will use that same
directory unless the directory is overridden by the
P= equate, as
shown in the third line. That is, the default queue
group’s queue directory and everything else that is
set for the default queue group is inherited by the
regularmail
group. For the slowmail queue group, however,
everything but the queue directory is inherited.
(See The Path= (P=) queue-group equate on page 413 for a description of the P= equate, and for the
reason queue group directories must be
subdirectories under QUEUE_DIR.)
Queue groups are declared with the Q configuration command.
That command can take a wide range of appearances,
but in all guises it takes the name of the queue
group and then a sequence of equates:
Qgroupname, equatesThe name of the queue group (here
groupname) must follow
the Q with no
intervening spaces. If spaces are present, an error
such as the following is printed and logged, and
that Q line is
ignored:
file.cf: line line number: queue : `=' expected
The equates are optional, but if they are present they must follow the queue group’s name and a comma or whitespace, or both:
Qgroupname, equatesThe equates are formed by selecting one of the
keywords shown in the leftmost column of Table 11-2, and
following it with an equals sign and the value you
wish to assign to that key letter. Note that only
the first letter is looked at by
sendmail, so you can use the
shorthand shown in parentheses if you wish. Also
note that the first letter is case-sensitive—that
is, R and
r are
different.
For example, both of the following declare a queue
directory (the Path= and P=) and a queue-processing interval of
10 minutes (the Interval= and I=):
Qslowmail, Path=/disk1/mail/slowqueues, Interval=10m Qslowmail, P=/disk1/mail/slowqueues, I=10m
A comma separates one equate from another. The comma can be optionally surrounded by whitespace characters (spaces and tabs). If the value following the comma is missing, an appropriate error will be printed and logged.
|
Equate |
§ |
Overrides command-line switch or option |
Description |
|
|
The Flags= (F=) queue-group equate on page 411 |
|
Fork queue runs |
|
|
The Interval= (I=) queue-group equate on page 411 |
|
Interval between queue runs |
|
|
The Jobs= (J=) queue-group equate on page 412 |
|
Maximum number of envelopes per queue run |
|
|
The Nice= (N=) queue-group equate on page 412 |
|
How to renice(3) the queue run |
|
|
The Path= (P=) queue-group equate on page 413 |
|
The queue directory or directories |
|
|
The recipients= (r=) queue-group equate on page 414 |
|
Maximum recipients per envelope |
|
|
The Runners= (R=) queue-group equate on page 414 |
|
Maximum queue processors per queue group |
If an equate other than those shown in the table is
used, an error such as the following is printed and
logged, and that Q line is ignored:
file.cf: line line number: Qgroupname: unknown queue equate bad equate here
The F=
queue-group equate is used to set flags for the
queue group. Currently there is only one flag, the
f flag, which
tells sendmail to fork
multiple times to process the queue group in
parallel (the exact opposite of the -qf command-line switch,
which tells sendmail to not
fork multiple times, but instead to run the queues
serially in the foreground).
When this F= flag is specified,
sendmail forks one queue
processor for each queue directory in the group.
But note that the sendmail
program will fork only up to the total number of
parallel processors set by the R= queue-group equate.
If that limit is fewer than the number of queues,
the remaining queues are handled during the next
queue run, in round-robin fashion.
When the fast processing of a queue group is
required, we recommend you specify this F=f queue group flag. If
speed is not of concern, you can reduce the system
impact by omitting this flag. But if you omit it
and then specify multiple runners with the
R= queue-group
equate, the following message will print and be
logged:
Warning: Q=queuegroup name: R=number: multiple queue runners specified but flag 'f' is not set
As a performance compromise, some parallelism
can be attained and system impact reduced by
setting this flag and limiting the number of
runners specified with the R= queue-group
equate.
The I=
queue-group equate specifies the time interval at
which the queues in the queue group should be
processed. The default interval is set by the
-qinterval
command-line switch, but can be overridden for a
queue group using this I= queue-group equate:
I=intervalThe interval following
the I= is
constructed from an integer and a letter. The
letters and the meaning of each are listed in
Table 11-3.
Integer and letter groups can be combined—for
example, 5d12h means 5 days, 12 hours.
If the trailing letter is missing, the units default to minutes; thus, the following defines an interval of 1 hour, 12 minutes:
Interval=1h12
In general, the use of a trailing letter is recommended for clarity, and to avoid problems in the future should sendmail defaults change.
When a queue processor starts to process a queue directory, it first gathers a list of all the envelopes in that directory. It then sorts, or randomizes that list, and processes the envelopes in the resulting order. If no limit is imposed, all the envelopes will be processed before the queue run is complete.
The default limit, if there is one, is defined
by the MaxQueueRunSize option (MaxQueueRunSize on page 1050). But a
separate limit that will override the default can
be set for a queue group using this J= equate. If the
default is nonzero and if this equate specifies
zero, the default queues will have the default
limit imposed but this group will have none. This
J= queue-group
equate is used like this:
Jobs=numberIf number is zero
or negative, no limit is imposed. If number is positive, that
will be the maximum number of envelopes
processed.
The niceness of a process determines its priority to be run. The larger the nice value, the lower the priority. The default nice value varies from one version of Unix to another. In all cases, however, they generally begin with the same nice value, so all processes generally get an equal chance to run.
With sendmail, the
niceness of its queue processors is set by the
NiceQueueRun
option (NiceQueueRun on page
1059). If that option specifies a positive value,
the priority is reduced. If that option specifies
a negative value, the priority is increased. In
general, queue processors should run at a lower
priority so as to minimize the adverse impact on
other processes. On dedicated mail-sending
machines, you might wish to increase the
priority.
Each queue group inherits its nice value from
the NiceQueueRun option, unless this
N= queue-group
equate is specified. This N= equate is used like this:
Nice=10 ← increase niceness by 10, lower priority Nice=0 ← no change Nice=−10 ← same as zero Nice=b ← same as zero
If the number is missing, nonnumeric, or negative, the niceness change is zero (no change). Otherwise, the niceness is increased (the priority is lowered) by the amount specified.
The default location and name of the queue
directory or directories is set by the QueueDirectory option
(QueueDirectory on page 1070).
That option defines the default directory (for the
default queue group mqueue) and the base path for all the
other queue directories. The P= queue-group equate
does not override the default (as the other
equates do), but instead augments it.
The path specified by the P= queue-group equate
must be a full (absolute) path, and must contain
the name of a subdirectory or subdirectories of
the default path. To illustrate, consider the
following mc file
declarations:
define(`QUEUE_DIR',`/var/spool/mqueues/q.*') ← the default QUEUE_GROUP(`aolmail', `P=/var/spool/mqueues/aolmail') ← good, a subdirectory QUEUE_GROUP(`bobmail', `P=/var/spool/mqueues/bob.*') ← good, a subdirectory QUEUE_GROUP(`hotmail', `P=hotmail') ← bad, not a full path QUEUE_GROUP(`slow', `P=/var/spool/slowqueue') ← bad, not a subdirectory
Here, the first line defines the default
queues, which all begin with the characters
q. and live
under the path
/var/spool/mqueues.
The second line correctly sets the queue for
the aolmail
queue group. The base path,
/var/spool/mqueues, is the
same for both the default and this group. Note
that queue group directories can also specify
multiple queues (as with the
/var/spool/mqueues/bob.* in the third
line).
The fourth line shows that the path specified
with P= must
not be a relative pathname. If it is,
sendmail will print and log
the following error and exit:
QueuePath hotmail not absoluteThe last line shows that the path specified
with P= must
not use a base path different from the default. If
it does, the following error will print and log,
and sendmail will
exit:
QueuePath /var/spool/slowqueue not subpath of QueueDirectory /var/spool/mqueues: No such file or directory
Note, however, that symbolic links under the default queue path are OK. That is, you can declare the last line in the preceding example like the following, and then simply make the path you specify a symbolic link to the real directory somewhere else:
define(`QUEUE_DIR',`/var/spool/mqueues/q.*') ← the default QUEUE_GROUP(`slow', `P=/var/spool/mqueues/slowqueue') ↑ a symbolic link to /var/spool/slowqueue
Note, however, that the path pointed to by the symbolic line must be as trusted as the default path, with narrow ownerships and permission (QueueFileMode on page 1071).
The MaxRecipientsPerMessage option (MaxRecipientsPerMessage on page 1050)
sets the default limit for the number of
recipients allowed per envelope. If there are more
recipients than that limit in an envelope,
sendmail will split the
envelope into two or more envelopes, each with the
limit or fewer recipients. If the MaxRecipientsPerMessage
option is zero, no limit is imposed.
The r=
queue-group equate allows you to override the
default for each queue group. If the default
allows unlimited recipients, or a large limit, you
can use a smaller setting for your queue group.
Or, if the default is too small, you can enlarge
it. You use the r= equate like this:
recipients=99 ← set the limit to 99 recipients recipients=0 ← set unlimited recipients recipients=-99 ← same as r=0 recipients=none ← same as r=0
Note that a zero or negative expression sets the limit to unlimited. A nonnumeric expression, such as in the last line, also sets the limit to zero (unlimited).
The Runners= (R=) queue-group equate tells
sendmail how many queue
processors to launch each queue-processing
interval. The queues are serviced in round-robin
order. So, for example, if your queue group has
three queues, and you set R= to 1, 2, 3, and 4, respectively, you
will see the runs shown in Table 11-4.
|
Runners |
1st run |
2nd run |
3rd run |
4th run |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The Runners= queue-group equate is declared
like the following:
Runners=12 ← 12 per queue run Runners=0 ← no limit, so one per queue each queue run Runners=none ← the same as R=0
If the number of queue-group runners specified
by this equate is more than the number of queue
children allowed by the MaxQueueChildren option (MaxQueueChildren on page 1049), the
number of queue-group runners is reduced to that
amount, and the following error is logged and
printed:
Q=queuegroup: R=number exceeds MaxQueueChildren=limit, set to MaxQueueChildren
If the MaxQueueChildren option is set to zero,
there is no limit to how many queue-group runners
you can declare.
You declare queue groups inside your mc configuration file with the QUEUE_GROUP mc configuration macro. As you saw in the previous sections, it is used like this:
QUEUE_GROUP(`group name', `equates')
The queue group name can contain any characters except a comma or a whitespace character (a space or a tab).[184] It must not be surrounded (inside the quotes) with whitespace characters.
The equates form the second argument to the QUEUE_GROUP mc configuration macro. The equates are described in The Q Configuration Command on page 409.
To illustrate, consider the following QUEUE_GROUP mc configuration macro declaration:
QUEUE_GROUP(`slowmail', `P=/var/spool/mqueues/slowqueue')
Here, the name of the queue group is set to slowmail. The second
argument is a single equate, the P= queue-group equate,
which defines the queue directory or directories to
be used by this queue group.
If you want to define which queue group to use for
certain delivery agents, you can use the Q= delivery-agent equate
(Q= on page 750) as set,
for example, with the LOCAL_MAILER_QGRP
mc macro. For example, the
following tells sendmail to
queue all local mail in the
/queues/lq queue
directory:
QUEUE_DIR(`/queue')
QUEUE_GROUP(`localgroup', `P=/queue/lq')
define(`LOCAL_MAILER_QGRP', `localgroup') ← must be before MAILER(local)
MAILER(`local')In the first line we set the default queue directory.
In the second line we define the queue group
localgroup, and
set its queue directory to be
/queue/lq. In the third line
we declare that the Q= equate for the local delivery agent
will be:
Q=localgroup
The fourth line declares support for the local delivery agent.
Note that the definition of LOCAL_MAILER_QGRP must
precede the MAILER(local); otherwise, that definition will
be silently ignored.
Those four lines cause all mail for local users to be queued in the /queue/lq directory. Note that you can dedicate queue groups for other delivery agents. See Q= on page 750 for a full description of this process.
The easiest way to select queue groups based on
recipient addresses or recipient domains is by using
the FEATURE(queuegroup). It is declared in
your mc configuration file like
this:
FEATURE(`queuegroup') FEATURE(`queuegroup', `default group')
The first line causes the queue group to default to
mqueue if a
queue group in the access
database is missing or nonexistent. The second line
allows you to set a different default queue group.
For example, consider the following lines from an
mc file:
QUEUEGROUP(`localgroup', `/queue/lq') FEATURE(`queuegroup', `localgroup')
This causes sendmail to use the
group named localgroup instead of mqueue as the default if
a queue group in the access
database is missing or nonexistent.
Once you have enabled the FEATURE(queuegroup), the next step is
to add lines such as the following to the source
file for your access
database:
QGRP:slow-poke.com slowgroup QGRP:root@notify.com fastgroup QGRP:your.domain localgroup
Each line that selects queue groups must begin with the literal expression:
QGRP:
This prefix tells sendmail that you wish to map recipient addresses or domains to queue groups.
The first line causes mail to the
slow-poke.com domain to use
the queue group called slowgroup. This shows that you can list
just a domain in the lefthand column and it will
work just as expected.
The second line causes mail to the specific recipient
root@notify.com to use the queue
group named fastgroup. This line demonstrates that
mail to an individual can be used in the lefthand
column.
The third line illustrates your local domain, which
shows that mail to your domain,
your.domain, will use the
queue group named localgroup.
If you omit the name of the queue group (not
recommended), you will need to use the -e command-line switch
with makemap to create the
database. When you omit the name of the queue group
the default queue group is used:
QGRP:another.your.domain
↑
queue group name missing (not recommended)Here, if you defined a default queue group when you
declared the FEATURE(queuegroup), that group will be
selected. Otherwise, the group mqueue will be selected
for this domain.
Normally, the access database,
described earlier, is the easiest way to select
queue groups. There might be times, however, when
selecting by recipient address or domain is not
sufficient. Should such a situation arise, you could
set up your own rule sets. But be forewarned that if
you do, the FEATURE(queuegroup) cannot be used. If
you try to use both, you will get the following
warning every time sendmail
starts to run:
WARNING: Ruleset queuegroup has multiple definitions
The first step in declaring your own rules to select
queue groups is to declare a special rule set called
queuegroup. You
do that in your mc
configuration file using the LOCAL_RULESETS
macro:
LOCAL_RULESETS
Squeuegroup
← your rules hereThe way this rule set works is simple. Any queue group
for a recipient address that a rule selects is
returned following the $# operator. For example, consider the
following:
R $* $: $>canonify $1 R $* <@some.domain> $# somegroup
Here, mail bound for any user at
some.domain will be queued in
the somegroup
queue group.
Normally, queuegroup rule sets are used to select
queue groups based on the recipient. If you wish to
select based on the sender, you can do so using
rules something like the following:
LOCAL_RULESETS Squeuegroup R $* $: $>canonify $&f R $+ <@ lists.domain.> $# lists
First, we fetch the sender address using $&f, and pass it
through the canonify rule set 3 to focus on the
host part. The second rule matches any user at the
domain lists.domain, and
selects the lists
queue group.
Because there are no more rules following the second
one, this rule set returns without selecting a queue
group. If the queuegroup rule set fails to select a
queue group, the default queue group (mqueue) is used.
Other possible uses for the queuegroup rule set might
include:
Queue inbound messages on a disk different from that used for outbound messages.
Queue mail to suspect users in a queue that is not automatically processed so that the mail can be manually screened before delivery.
Queue expendable mail, such as short-lived notification mail (e.g., “tea is served”), on a volatile disk that is erased when the machine is rebooted.
Queue low-priority mail in a queue different from that used for high-priority mail.
Note that there are limitations on the use of this
queuegroup rule
set. First, this rule set is called directly from
inside sendmail, so you should
not call it from inside your own rules (if you do,
the selected queue group will be ignored). And
second, the FEATURE(queuegroup) also uses this rule
set, so you cannot share it with that
feature.[185]
As you saw in The Default Queue Group on page 409, the default queue group (mqueue) is defined by
options and the command line. If any given Q configuration command
is missing a given equate, that queue group inherits
that property as defined by the default queue group.
There are, however, properties for the default queue
group which have no equivalent equates. These
properties are inherited by all queue groups and
cannot be overridden with a queue-group equate. They
are:
DeliveryMode
optionIf the DeliveryMode option (DeliveryMode on page 1004) is set to
queueonly or
deferred, all
mail will be queued rather than delivered. This
affects all queue groups.
FastSplit
optionThis FastSplit option (FastSplit on page 1032), when nonzero,
prevents MX lookups prior to splitting an envelope
and limits the number of envelopes that can be
delivered on the initial attempt. This option,
regardless of its value, affects all queue
groups.
MaxQueueChildren
optionThe MaxQueueChildren option (MaxQueueChildren on page 1049), when
nonzero, limits the number of queue processors
that can simultaneously run across all queues. If
this is fewer than the total queue runners across
all queue groups, it limits the run to this
setting. Any queue groups that are not run are
handled in the next run in round-robin order.
There is no way to limit some queue groups and not
limit others.
MinQueueAge
optionMessages in a queue are processed no more
often than the interval set by this MinQueueAge option
(MinQueueAge on page 1057). This
limit is imposed even if a queue is processed more
often. This limit is global and affects all queue
groups.
-qI,
-qR,
and
-qS
command-line switchesThe -qI
command-line switch restricts a queue run to the
messages that match the queue identifier
specified. The -qR command-line switch restricts a
queue run to the messages that match the recipient
address pattern specified. The -qS command-line switch
restricts a queue run to the messages that match
the sender address pattern specified. Unless the
-qG
command-line switch is also used to limit the
queue group, these limits are imposed across all
queue groups.
QueueFactor, QueueLA, and
RecipientFactor
optionsThe QueueFactor (QueueFactor on page 1071), QueueLA (QueueLA on page 1072), and RecipientFactor (RecipientFactor on page 1077) options
(and beginning with V8.14, the DaemonPortOptions
option’s queueLA key; DaemonPortOptions=queueLA= (8.14 and
later) on page 997) are used to calculate the point at
which sendmail should queue a
message instead of delivering it. This calculation
affects all queue groups.
QueueFileMode
optionBeginning with V8.10
sendmail, the QueueFileMode option
(QueueFileMode on page 1071)
defines the mode (permissions) of all queue files.
This setting affects all queue files across all
queue groups.
Timeout.queuereturn and Timeout.queuewarn
optionsThe Timeout.queuereturn option (Timeout.queuereturn (V8.7 and later) on page 1106) defines the maximum time interval
that a message can remain in the queue before it
is bounced because of a deferred delivery. The
Timeout.queuewarn option (Timeout.queuewarn (V8.7 and later) on page 1107) defines the interval at which a
message, still in the queue, will result in a
first and only warning message being sent to the
sender. Both of these intervals globally affect
all queue groups.
For security reasons, V8 sendmail
performs a number of checks on each qf file before trusting its contents. If
any qf file fails to be
trustworthy, sendmail converts the
leading q in its name to
an uppercase Q.[186] We discuss each possible problem in the sections
that follow.
Note that when sendmail renames a
qf file into a
Qf file, it logs
that it did so. In the following,
qffile is the full path
and filename of the qf
file, before it was renamed:
Losing qffile: reason here
Also note that although sendmail checks
the qf file for a number
of plausible errors, its checking is by no means exhaustive.
The checks we describe here are no substitute for a
well-managed system.
V8.6 sendmail always checks the
form of the qf
file name for correctness. V8.7 through V8.9
sendmail also check the
qf filename,
but do so only if PICKY_QF_NAME_CHECK is defined
when building sendmail (PICKY_HELO_CHECK
on page 133). V8.10 and later no longer check the
form of the qf
filename for correctness.
Prior to V8.10, if the qf filename is incorrectly formed
(The Queue Identifier on page
396), sendmail presumes that
some other program placed the file in the queue and
rejects it:
orderq: bogus qf name bogus name hereFor V8.7 through V8.9, sendmail
made this check only if PICKY_QF_NAME_CHECK was
defined when building sendmail.
This was introduced because some sites allow
legitimate programs (other than
sendmail) to write into
sendmail’s queue. To fix this
problem, either undefine PICKY_QF_NAME_CHECK when
you build sendmail (if your
site allows other programs to write into the queue
directory), or trace down the process that is
placing badly formed qf names in your queue and fix
it.
Each qf file must
be owned by the effective user ID under which
sendmail runs (usually
root). A qf file must not be
group- or world-writable. If a qf file fails either
test, it is considered bogus and is renamed to a
Qf file. Then
sendmail logs these
messages:
id: bogus queue file, uid=owner, mode=permsLosingqffile: bogus file uid in mqueue
Here, id is the identifier
portion of the qf
filename, owner is the
uid of the user that owns the
qf file, and
perms are the file
permissions of the qf file, printed in octal.
This problem might point to bad queue directory permissions that allow anyone (or some group) to place files there. Or it might indicate that some process other than sendmail is writing to your queue.
One form of attack against
sendmail is to append
additional control lines to the end of an existing
qf file. V8.7
sendmail specifically checks
for additional text and rejects the qf file if any is
found:
SECURITY ALERT: extra data in qf: first bogus line printed here
Losing qffile: bogus queue lineV8.7 sendmail terminates its
legitimate list of qf control lines by placing a dot on a
line by itself. Any text following that line,
including comments and blank lines, is considered an
error. This can represent a serious attack against
your machine or site. If you get this message,
investigate at once.
Each line in a qf
file must begin with a known control letter or
character (The qf File Internals
on page 445). If a line begins with any other
character, it is considered bad, and the whole file
is rejected:
readqf:qffile: linenum: bad line bogus line here Losingqffile: unrecognized line
Note that this error is to be anticipated if you go backward, from a later release to an earlier release of sendmail.
An F line in a
qf file is used
to save and restore envelope flag bits.
Unfortunately, the first line of a Unix-style
mailbox also begins with an F:
From someone@site
If a qf file’s
F line begins
with the five characters "From“, V8.7 and later
sendmail will reject the file
and log a possible attack:
SECURITY ALERT: bogus qf line bogus line here
Losing qffile: bogus queue lineThis might represent a serious attack against your machine or site. If you get this message, investigate at once.
In the rare event that sendmail
cannot dispose of a bounced message, it will
preserve the qf
file as a Qf file
and log the message:
savemail: cannot save rejected email anywhere
Losing qffile: savemail panicThe sendmail program tries
everything possible to avoid this state (including
bouncing the message, sending it to the
postmaster, and saving it to
a dead.letter file). Only if
all else fails will it preserve the qf file as a Qf file.
In general, this points to an alias problem with the user named postmaster or the owner of a mailing list. Such users are special. They must be able to receive email messages no matter what. They should be the names of real people, not the names of further mailing lists.
Beginning with V8.13, the -qL command-line switch allows you to
view and handle Qf files. Note, however, that handling
these files, without first repairing the causative
problem, can be risky. One use for this new switch
is to examine the mail queue to see if any lost
files exist:
% mailq -qL
/var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
h7AJG4kr009003? 235 Sun Aug 10 13:16 <you@your.domain>
<bob@other.domain>
Total requests: 1Here, the -qL
command-line switch was used with the mailq command to see if
any lost files were present. This output shows that
a lost file (called Qfh7AJG4kr009003) is located in the
/var/spool/mqueue directory. The
"?" character
following the file’s name indicates that it is a
lost envelope.
This -qL switch can
be combined with other queue-handling switches to
further limit what can be shown.
When sendmail is run under the name
mailq, or when it is given the
-bp command-line
switch, it prints the contents of the queue and
exits.
Before printing the queue’s contents,
sendmail prereads all the
qf files in the
queue and sorts the mail messages internally. This is done
so that the queue’s contents are displayed in the same order
in which the messages will be processed during a queue
run.
If there are no messages in the queue (no qf files),
sendmail prints the following
message and exits or, if there are multiple queues, goes on
to the next queue:
/path is emptyHere, /path is the full pathname of
the queue directory.
If the queue is not empty, sendmail
prints the number of messages (number of qf files) in the
queue:
/path(numrequests)
The num is the number of queued
messages (requests) in the queue directory. If this is more
than the maximum number of messages that can be processed at
one time (defined by the MaxQueueRunSize option [MaxQueueRunSize on page 1050]),[187]
sendmail prints:
/path(numrequests, only ## printed)
The ## is the value of the
MaxQueueRunSize
option.
Note that it can take several minutes to presort and print
extremely full queues (queues with more than 10,000 messages
in them). To see how many messages are queued, and to avoid
the delay of a presort, you can add a small MaxQueueRunSize to your
invocation of mailq:
% mailq -OMaxQueueRunSize=1This will cause sendmail to swiftly print the number of queued messages, regardless of how many are queued.
After sendmail prints the number of messages in the queue, it prints an attractive heading such as the following:
----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------
dB928Xl04182 354 Fri Mar 15 08:32 your@your.domain
george@wash.dc.gov
dB928RR04181* 1972 Fri Mar 15 08:45 your@your.domain
8BITMIME (Timed out waiting to connect to wash.dc.gov)
jefferson@wash.dc.gov
dB928RR04192- 23 Fri Mar 15 09:32 your@your.domain
(Timed out waiting to connect to wash.dc.gov)
jefferson@wash.dc.gov
bobThe heading shows the information that is printed about each message in the queue. The items in that heading and their meanings are as follows:
Q-IDThe queue identifier for the message. This
item can be followed by a character showing the
item’s status. An asterisk (* as in the second item
in the example) means that the message is locked
(an lf file was
found, or the qf file is locked depending on the kind
of locking your version of
sendmail uses). An X means that the load
average is currently too high to allow delivery of
the message. A minus (- as in the third item in the example)
means that the message is too young to be
processed (based on the MinQueueAge option, MinQueueAge on page 1057).
SizeThe size in bytes of the df file. If there is no
df file
(because sendmail is
currently receiving this message and hasn’t
created one yet), this item is absent. If the
message has completed processing, this prints
as:
(job completed)
If the qf
file is empty, this prints as:
(no control file)
Q-TimeThe date and time that the message was first
placed into the queue. This is the T line (T line on page 456) in the qf file converted from
an unsigned integer into a more understandable
date and time.
SenderThe sender of the message as taken from the
S line (S line on page 455) in the qf file. Only the first
45 characters of the sender address are printed.
If there is a B
line (B line on page 447) in the
qf file (as the
BITMIME in the second item in the example),
sendmail prints that body
type (the -B
switch in -B on page 232) on
the line following the sender. If there is an
M line (M line on page 452) in the qf file,
sendmail prints the text of
the error message in parentheses.
RecipientAfter all of the preceding items have been
printed, a list of the recipients (from each
R line, R line on page 454, in the
qf file) is
printed in the order in which they are found. In
the example, there is one recipient for each of
the first two items and two recipients for the
last item.
See Process by identifier/recipient/sender: -q[ISR] on page 431 for a way to limit the printed queue list to include only a subset of messages based on queue ID, sender, or recipient addresses.
The -v command-line
switch can be used in combination with the -bp switch to cause
sendmail to also print
additional details about the queued messages. To
begin, the usual heading shows a new item:
----Q-ID---- --Size-- -Priority------Q-Time----- ---------Sender/Recipient---------dB928Xl04182 35454320Fri Mar 15 08:32 your@your.domain george@wash.dc.gov dB928RR04181* 197239020Fri Mar 15 08:45 your@your.domain 8BITMIME (Timed out waiting to connect to wash.dc.gov) jefferson@wash.dc.gov dB928RR04192- 2330001+Fri Mar 15 09:32 your@your.domain (Timed out waiting to connect to wash.dc.gov) jefferson@wash.dc.gov(---you---)bob
The Priority is the
value from the P
line (P line on page 453) in the
qf file.
Printing the queue does not change a message’s
priority, whereas processing the queue does. See the
RecipientFactor
option (RecipientFactor on page
1077) for a description of how the priority is
calculated.
Verbose mode also causes a + to print after the Priority (as in the
third item in the example) if a warning message has
been sent. See the Timeout.queuewarn option (Timeout on page 1097) for a
description of how messages time out.
If any R line is
preceded by a controlling user (the C line in the qf file, C line on page 447), verbose mode
causes that controlling user’s name to be put in
parentheses and prepended to the recipient name. The
third item in the preceding example illustrates
this.
Prior to V8.8 sendmail, the
M line error
messages were truncated to 60 characters. Beginning
with V8.8, verbose mode causes the full,
nontruncated text of the M line error to be printed.
Beginning with V8.12 sendmail,
the -bP
command-line switch can be used to print the number
of messages in the queue or queues. This
command-line switch relies on shared memory to
gather its information, so it works only if
sendmail is compiled with
shared memory support. The SM_CONF_SHM compile-time
macro determines whether shared memory support was
included (see SM_CONF_SHM on
page 142). If shared memory support is not included,
use of this command-line switch will cause the
following error to be printed:
Data unavailable without shared memory support
If shared memory support is compiled in, but there is a problem with it (possibly at the system level), the following error will print:
Data unavailable: shared memory not updated
Note that you will also get this error if the queue has not been processed at least once to initialize the data.
In addition to enabling shared memory using the
SM_CONF_SHM m4 Build macro, you
must also define a key to be used with that shared
memory with the SharedMemoryKey option. To set this
option in your configuration file, you could add a
line such as the following to your
mc configuration file:
define(`confSHARED_MEMORY_KEY',`13521')
If all goes well, the -bP command-line switch will produce
output such as this:
/var/spool/mqueues/q.1/df: entries=34
/var/spool/mqueues/q.2/df: entries=51
Total requests: 85Here, 85 is the
number of envelopes currently awaiting delivery in
sendmail’s queues. But note
that some shared memory timeouts can lead to an
inexact count. In this latter event, the output
looks like this:
Total requests: 85 (about)
If you lack shared memory support, and you are running pre-V8.12 sendmail, you can still summarize the number of messages in all queues with a simple substitute command:
% mailq -OMaxQueueRunSize=0Over time, messages can gather in the queue awaiting delivery. They remain there until sendmail performs a queue run to process the queue. The sendmail program can be told either to process the queue periodically (when run as a daemon) or to process the queue once, and then exit. Each time sendmail processes the queue, it also performs a series of operations that are intended to improve the efficiency with which it delivers messages.
First the queue directory is opened for reading. If that directory cannot be opened, sendmail syslog(3)s the following message at LOG_CRIT and exits:
cannot opendir(/var/queue): reason hereThis error is usually the result of a user running
sendmail in an unsafe manner,
with a -C command-line
argument, for example. It can also result from
sendmail attempting to open an
NFS-mounted queue directory, where root
is mapped to nobody.
Next, the qf files are read
to gather their priorities and times (the P and T lines). If a qf file cannot be opened,
it is quietly ignored unless a -d41.2 debugging command-line switch is
specified, in which case the following error message is
printed:
orderq: cannot open qfdB928RR04181 (reason)
Prior to V8.7 sendmail, there was a hard limit on the number of messages that could be processed at any time. If more than QUEUESIZE (defined in conf.h, typically 1,000) messages were in the queue, only the first QUEUESIZE (1,000) of them would be processed! Ordinarily, this was not a problem. But it could quickly become one if your queue were clogged with a huge number of undeliverable messages (where the first 1,000 continued to be deferred). In that case, the only solution is to temporarily move the 1,000 messages out of the way by hand (Handling a Down Site on page 437) and clear the queue. The only way to detect this situation is to print the queue (Printing the Queue on page 422).
V8.7 and later sendmail dynamically allocate memory to process the queue. If more than QUEUESIZE messages are found, sendmail will print the following notice and process them:
grew WorkQ for queue_directory to bytes
As an alternative to this dynamic behavior, V8.7 and later
sendmail offer a hard limit
that is somewhat like the old version but is site-tunable
with the MaxQueueRunSize
option (MaxQueueRunSize on page 1050).
After all the qf files
have been gathered, they are sorted in order of cost.
Messages with the lowest value on the P line have the highest
priority (lowest cost) and are processed first.
Beginning with V8.7, sendmail also offers
the QueueSortOrder option
(QueueSortOrder on page 1073),
which allows you to sort by priority (as before), by
priority and hostname, by date queued, or (beginning with
V8.10) by filename or (beginning with V8.12) in random
order. Once all the messages have been sorted,
sendmail processes each in
turn.
A single queued message has a single sender but can have many recipients. When processing a queued message, sendmail attempts to deliver it to all recipients before processing the next queued message.
The first step in processing a queued message is to
lock it so that concurrent runs of
sendmail do not attempt to
process it simultaneously (Current-style file locking on page
398). Then the qf
file is opened and read. The sender and all the
recipients are gathered from the corresponding
S and R lines.
For each recipient, delivery is attempted. If delivery is successful, that recipient’s address is removed from the sendmail program’s internal list of recipient addresses. If delivery fails, that address is either left in the list or bounced, depending on the nature of the error.
After all recipients have been either delivered,
bounced, or left in the list,
sendmail reexamines that
list. If there are no recipients left in it, the
message is dequeued (all the
files in the queue directory that compose it are
removed). If any recipients are left, each recipient
results in an M
line that is assigned the last error message for
that recipient, and the qf file is rewritten with the list of
the remaining recipients and a dot. Finally, the
qf file is
closed, thus freeing its lock.
Under V8 sendmail, the CheckpointInterval
option (CheckpointInterval on page
983) causes checkpointing of this process. When this
option has a positive value, the qf file is rewritten
after that value’s number of recipients have been
processed. For example, consider a mail message to
five recipients. If the CheckpointInterval option is set to a
value of 2, the qf file is rewritten after the first
two recipients have been processed, then again after
four, and again after they all have been processed.
This keeps the qf
file reasonably up-to-date as protection against
sendmail being improperly
killed or the machine crashing.
The sendmail program offers two different methods for processing its queues. It can be told to process them periodically or to process them once and then exit.
The -q command-line
switch is used both to cause queues to be processed
and to specify the interval between queue
runs.
A typical invocation of the sendmail daemon looks like this:
/usr/sbin/sendmail -bd -q1h
Here, the sendmail program is
placed into listening mode with the -bd command-line switch.
The -q1h
command-line switch tells it to process the queue
once each hour. Note that either switch puts
sendmail into the background
as a daemon. The -bd switch just allows
sendmail to listen for
incoming SMTP connections. Consider the
following:
/usr/sbin/sendmail -bd /usr/sbin/sendmail -q1h
This runs two daemons simultaneously. The first listens for incoming SMTP connections. The second processes the queues once per hour.
The time expression following the -q is constructed from
an integer followed by a letter. The letters and the
meaning of each are listed in Table 11-5. Integer and
letter groups can be combined—for example, 5d12h
means 5 days, 12 hours. If a letter is missing, the
default is minutes.
At small sites, where mail messages are rarely queued,
the time interval chosen can be small to ensure that
all mail is delivered promptly. An interval of
15m (15
minutes) might be appropriate.
At many sites, an interval of one hour is probably best. It is short enough to ensure that delays in delivery remain tolerable, yet long enough to ensure that queue processing does not overlap (see Persistent Queue Runners with -qp on page 434 for a way to run a persistent queue runner that avoids overlapping runs).
At large sites with huge amounts of mail and at sites that send a great deal of international mail, the interval has to be carefully tuned by observing how long it takes sendmail to process its queues and what causes that process to take a long time. Points to consider are the following:
Network delays or delays at the receiving
host can cause delivery to that host to time out.
Timeouts are set with the Timeout option (Timeout on page 1097).[188] Each such timeout is logged at
LOG_NOTICE with a message such as this:
timeout waiting for input fromhostduringwhat
Here, host is the
name of the other host, and
what specifies which
timeout triggered the message (such as “client
HELO” for to_helo). In general, timeouts should
be large to ensure that mail to busy sites, and to
large mailing lists, does not time out improperly.
In observing queue processing, you might find that
all messages but one process swiftly. That one,
you might find, takes more than an hour because of
a long SMTP timeout. A possible solution to this
problem is to make all timeouts short so that most
queue runs are processed quickly. Then, for
example, the following command could be run a few
times each night to specifically flush those long
jobs:
/usr/sbin/sendmail -OTimeout=2h -q
A queue can take a long time to process
because too many messages are being queued
unnecessarily. Several options affect the
placement of mail messages into the queue. The
QueueLA option
(QueueLA on page 1072) tells
sendmail to queue, rather
than deliver, a message if the machine load is too
high. Fewer messages will be queued if the value
of that option is increased. (Beginning with
V8.14, this load average cutoff can be more finely
tuned by using the DaemonPortOptions option’s queueLA key; DaemonPortOptions=queueLA= (8.14 and
later) on page 997.) The SuperSafe option (SuperSafe on page 1096) tells
sendmail to queue all
messages for safety. If your machine “never”
crashes, this might not be necessary. Or you might
choose to turn off SuperSafe when sending short-lived
notification mail, or when your queues are on a
volatile filesystem, such as an
async or
tempfs filesystem. (RFC2824
recommends that you never turn off SuperSafe.) The HoldExpensive option
(HoldExpensive on page 1036)
tells sendmail to queue
messages to “expensive” delivery agents (those
with the F=e
flag set, F=e on page
770) rather than delivering them. If the queue is
routinely filled with messages to expensive sites,
you should reconsider your reasons for marking
those sites as expensive.
The queue can fill with messages because
sendmail was run with the
-odq or
-odd
command-line switch (see the DeliveryMode option,
DeliveryMode on page 1004). At
sites that receive a great deal of UUCP mail for
forwarding, the rmail(8)
program is often set up to run
sendmail in “queue-only” mode
with the -odq
command-line switch. If UUCP mail is clogging your
normal mail services, you should consider queueing
it to a separate queue directory. You can then
process that other directory with a separate queue
run of sendmail. (Use of
separate queue directories is discussed in Process Alternative Queues on page
436.)
A slow machine can clog the queue. When a single machine is set up to handle the bulk of a site’s mail, that machine should be as swift as possible. In general, a dedicated mail server should have a fast CPU with lots of memory. It should never allow users to log in to it, and it might need to run its own name server daemon.
On modern servers where a fast CPU with lots of memory is available, the bottleneck will likely be disk I/O. Equip the server with many disks spread over many controllers. Use multiple queue directories (Using Multiple Queue Directories on page 401) or queue groups (Queue Groups (V8.12 and Later) on page 408) to spread the I/O widely over those many disks.
The -q command-line
switch, invoked without a time interval argument, is
used to run sendmail in
queue-processing mode. In this mode,
sendmail processes queues
once and then exits. This mode can be run
interactively from the command line or in the
background via cron(8).
Other command-line switches can be combined with
-q to refine
the way queues are processed. The -v (verbose) switch
causes sendmail to print
information about each message it is processing, and
to process multiple queues sequentially. The
-d (debugging)
switch can be used to produce additional information
about the queue. We’ll discuss the -v switch as it applies
to the queue later in this chapter. Those -d debugging switches
appropriate to the queue can be found in Table 15-3 on page
536.
V8 sendmail allows variations on
-q: -qI allows you to
specify a specific message identifier for
processing; -qR
allows you to specify specific recipient addresses
for processing; and -qS allows you to specify specific
sender addresses for processing.[189]
The -q
command-line switch, without an interval argument,
tells sendmail to process the
queue once, and then exit. As such, this switch is
a handy administrative tool. When the queue fills
unexpectedly between queue runs of the daemon, for
example, the -q
command-line switch can be used to force an
immediate queue run:
# /usr/sbin/sendmail -qWhen multiple queues are run this way, they are all processed in parallel (Processing multiple queue directories on page 403).
On machines that do not run the
sendmail daemon, the -q command-line switch
can be used in conjunction with
cron(8) to periodically
process the queue. The following
crontab(5) file entry, for
example, causes sendmail to
be run once per hour, at five minutes past the
hour, to silently process its queues and
exit:
5 * * * * /usr/sbin/sendmail -q >/dev/null 2>&1
When used in conjunction with other switches
(shown next), the -q switch allows many queue problems to
be conveniently handled.
The -q
switch without an argument prevents
sendmail from running in the
background and detaching from its controlling
terminal. But it also runs silently. To see what
is going on, use the -v command-line switch in combination
with the -q:
% /usr/sbin/sendmail -v -qThe -v
command-line switch causes
sendmail to print a
step-by-step description of what it is doing. When
running multiple queues, it also causes them to be
processed in sequence. To illustrate, consider the
following output produced by using both the
-v and -q command-line
switches:
Running /var/spool/mqueue/dB9JBR106687 (sequence 1 of 2) <adams@dc.gov>... Connecting to dc.gov via ddn... Trying 123.45.67.8... Connection timed out during user open with DC.GOV <adams@dc.gov>... Deferred: Host DC.GOV is down Running /var/spool/mqueue/dB9JDWt06701 (sequence 2 of 2) <help@irs.dc.gov>... Connecting to irs.dc.gov via ddn... Trying 123.45.67.88... connected. 220 irs.dc.gov Sendmail 5.57/3.0 ready at Mon, 27 Jan 92 09:16:38 −0400
Here, two queued messages are being processed. The first fails because of a connection timeout and is requeued for a later queue run. The second succeeds (we omit the full SMTP dialog). After its delivery is complete, it is removed from the queue.
With V8 sendmail you can process a subset of all queued messages. You can select which to process based on queue identifier, recipient address, or sender address:
-qIident ← match any queue ID that contains ident -qRrecip ← match any recipient address that contains recip -qSfrom ← match any sender address that contains from
The -qI
variation is followed by a queue identifier such
as dB9JDWt06701. The -qR is followed by the
address of a recipient. The -qS is followed by the
address of a sender. In all three variations,
there must be no space between the uppercase
letter and the identifier or address.
These variations are used to limit the selection of queued files that are processed. For example:
% /usr/sbin/sendmail -qSroot -qRbiff@hereHere, the queue is processed once. Only messages from root are processed. Of those, only messages that have biff@here as one of the recipients are processed.
In all three variations, a partial specification of queueid, recipient, or sender is viewed by V8 sendmail as a substring. For example:
-qSroot
matches mail from all of the following:
root ben@groots.edu ben@GROOTS.EDU
The last line further illustrates that the
substring match is a case-insensitive one. The
substring match is literal. Wildcard characters
(such as *) and
regular expressions (such as .*@.*edu) won’t work and
might confuse the shell from which you run
sendmail.
Multiple specifications can be combined on the command line (as shown earlier), but they all AND together:
% /usr/sbin/sendmail -qI123 -qSroot -qR@host.eduHere, the queue is processed only for messages with the number 123 anywhere in the queue identifier that are also from root and that are also addressed to anyone at host.edu.
You can use the mailq command to preview the effect of
these switches. For example, the following command
will list (but not send) the messages that would
be processed by the previous command line:
% mailq -qI123 -qSroot -qR@host.eduBeginning with V8.12
sendmail, you can prefix any
of the I,
S, or R specifications to
-q with an
! character.
The presence of an ! character prefix instructs
sendmail to invert the logic
of that particular test. For example:
% mailq -q\!Sroot -qR@host.eduHere, we wish to process the queue for any
message addressed to anyone at
host.edu, just as we did in
the previous section. But this time, we want to
further limit that processing by including only
messages with a sender that is
not (the !) from
root. Note that we prefix the
! with a
backslash to protect it from the
csh or
tcsh shells (the backslash is
not necessary for the Bourn shell and its
derivatives).
In summary, these specifications for how to limit the queue can be mixed and matched, specified and negated, in any combination that works for you:
-qIident ← match any queue ID that contains ident -q!Iident ← match any queue ID that does not contain ident -qRrecip ← match any recipient address that contains recip -q!Rrecip ← match any recipient address that does not contain recip -qSfrom ← match any sender address that contains from -q!Sfrom ← match any sender address that does not contain from
Only the !
character can be used to negate. Any other
character will be interpreted as an argument to
-q. The
! prefix must
not follow the I, R, or S. If it follows, it will be
interpreted as part of the expression to
match.
Beginning with V8.12
sendmail, you can use the
-qG
command-line switch to process queues based on
selected queue groups. It is used like
this:
-qGgroupnameHere, only mail queued in the qroupname directories will be processed. If the name specified is of an unknown group, the following error will print and log, and the queue run will fail:
Queue group groupname unknownThis command-line switch can be used in combination with all the other queue processing switches. Consider, for example, the following:
% /usr/sbin/sendmail -qR@hostA.domain -qGslowHere, sendmail will
deliver queued messages only to users at
hostA.domain, if those
messages were queued in the slow queue group.
Multiple -qG command-line switches cannot be
used at the same time. If you combine them, the
following error will print and be logged:
Cannot use multiple -qG options
Unlike the -q[IRS] switches discussed earlier, the
-qG
command-line switch cannot be negated:
%/usr/sbin/sendmail -q!GmqueueCannot use -q!G
The ESMTP ETRN command, based on RFC1985,
causes V8.8 and later
sendmail to asynchronously
process its queue in a manner similar to the
-qR
command-line switch (Process by identifier/recipient/sender:
-q[ISR] on page 431). This command allows
dial-on-demand sites to make an SMTP connection
and to force the other side to process and send
any mail that is queued for them. The form of this
ESMTP command looks like this:
ETRN hostIf host is missing,
this error message will be returned:
550 Parameter required
Otherwise, the queue will be processed just as though the following command-line argument were given:
-qR@hostIn both cases, a qf file will be processed if it has
host anywhere in the host
part (following the @) of one of its R lines. The only
difference here is that the former (the ETRN)
operates asynchronously. That is,
sendmail forks a copy of
itself, and the forked child processes the
queue.
Beginning with V8.12
sendmail, you can cause
sendmail to process the
queues by queue group. To do this, just replace
the hostname with the name of the queue group, and
prefix it with a literal # character:
ETRN #groupnameIf the groupname has been defined, the queues for that queue group will be processed. Otherwise, the following error will be returned:
459 4.5.4 Queue badname unknownOne way to use ETRN is with a
perl(1) script supplied with
the sendmail source. See the
file:
contrib/etrn.pl
You might have to change the first line of this file to get it to work, depending on where you installed perl(1) on your system. To run this program, just give it the name of your MX server:
%contrib/etrn.plyour.mx.server
The etrn.pl script will
connect to that server, and it will send an ETRN
command to that server for each host you list with
a Cw or
Fw command in
your configuration file. The
etrn.pl script is also its
own manual page, which you can read with a command
such as this:
% nroff -man contrib/etrn.pl | moreV8.12 sendmail introduced
persistent queue runners as a solution to some of
the problems caused by periodic queue runners.
Periodic queue runners are the result of a normal
-qinterval
command-line switch, or a Runners= queue-group equate. Either
causes:
sendmail to fork one or more queue runners to process a queue or queue group each interval
Every queue runner to open and read all the files in the queue to gather a list of envelopes to deliver
Persistent queue runners avoid these problems because
a single process is dedicated to a queue, a queue
group, or a grouping of queue groups (called a
“workgroup”). A persistent queue runner is launched
just like the periodic command-line queue runner,
but with the addition of a p character:
-qpintervalThe p causes one or
more persistent queue runners to be launched, one
per queue group. One will be launched to handle your
default queue group, and one more will be launched
to handle each queue group defined by a QUEUE_GROUP
mc option. Depending on the
number of queue directories in each, these can be
combined into a single workgroup. When you have many
queue groups, you can end up with multiple
workgroups controlling persistent runners.
Each persistent queue runner will sleep for interval. When it awakes, it reads all the files in the queues that belong to its workgroup, and sorts all the envelopes it finds into the proper order needed for delivery. After it has finished ordering the envelopes, it launches one or more regular queue runners to perform delivery using that already processed list. This can significantly reduce the disk I/O compared to that needed by periodic queue runners.
When the last of the regular queue runners has finished processing (and exited), the persistent queue runner goes back to sleep for interval.
In general, persistent queue runners are valuable only at sites that normally have queues that are very full. When a queue is normally near empty, persistent queue runners can introduce unforeseen delays. Note that a persistent queue runner will sleep again only when all of its regular queue runners have finished. One regular queue runner, delivering to a very slow site, can appear to hang, and so can cause the persistent queue runner to also appear to hang. Subsequent queue runs will be delayed until the hung site times out, allowing the persistent queue runner to sleep interval again.
At large sites, such delays will eventually smooth out due to the normal distribution of slow jobs. At small sites, such delays might be noticed and objected to. In general, persistent queue runners should be reserved for sites with full queues.
If interval is omitted, the default interval becomes 1 second:
-qp
When the default interval is used (by omitting the
interval), the persistent queue runner will sleep
one second between queue runs, unless the prior
queue run was empty, in which instance it will sleep
five seconds. If you choose the default interval, we
recommend you also set the MinQueueAge option (MinQueueAge on page 1057).
If interval is specified as zero, the effect is the same as though it were omitted. If interval is negative, the following error is logged and printed and sendmail exits:
Invalid -q value
If interval is nonnumeric (if you specify O when you mean zero), the following error is logged and printed, and sendmail exits:
Invalid time unit `O'
The process that was given the -qp command-line switch
is the controlling process. It could be the
listening daemon (if -bd or -bD were also used), or it could be a
queue processing daemon (if only -qp and other queue
processing limiters were specified). The controlling
process has two special properties:
To restart the persistent queue runners, you must instead restart the sendmail controlling process. You do that with a SIGHUP signal (as normal). If you try to signal the individual persistent queue runners, they will restart but with a penalty (each can be restarted this way only 10 times; see later in this section).
Beginning with V8.14, all persistent queue runners can be restarted by sending a SIGHUP signal to the controlling persistent queue runner.
If a persistent queue runner fails and exits, the controlling process will launch a new persistent queue runner.
If a persistent queue runner core-dumps, the following will be logged and that queue runner will not be restarted:
persistent queue runner=number core dumped, signal=signal
If a persistent queue runner exits because of a caught signal, the following is logged and that queue runner is restarted:
persistent queue runner=number died, signal=signal
If a persistent queue runner is restarted because of a SIGHUP, the following is logged:
restart queue runner=number due to signal signal
If the -dno_persistent_restart debugging
command-line switch is specified, a failed
persistent queue runner will not be restarted, and
the following error will be logged:
persistent queue runner=number, exitedA persistent queue runner will not be restarted if it has already been restarted 10 times. Instead, the following error will be logged and that persistent queue runner marked as bad:
ERROR: persistent queue runner=number restarted too many times, queue runner lostIf this happens, examine your logs. Some nonmail-related process might be signaling your persistent queue runners, or you might have bad memory, or you might have made a mistake when building sendmail and should rebuild it, or you might have a junior system administrator who does not know how to correctly restart sendmail.
Persistent queue runners look like executing periodic queue runners in process listings:
root 22958 476 ? S 08:43 0:00 sendmail: accepting connections root 22947 512 ? S 08:32 0:00 sendmail: running queue: /var/spool/mqueues/ q.1/df
Here, the first line shows the controlling process, and the second line shows a persistent queue runner. Note that even though the second entry says “running,” it might not be.
The sendmail program provides the ability
to use queue directories other than the one listed in the
configuration file’s QueueDirectory option (QueueDirectory on page 1070). Other
queue directories can be used to solve an assortment of
problems. One example is a site being down for an extended
period. When a lot of mail is sent to such a site, messages
collect in the queue and eventually start timing out. By
moving those messages to a separate queue directory and
processing it at a later time (when that site is back up),
unnecessary bouncing of mail can be prevented.
Note that the QueueDirectory option is not safe. If its
value is changed by anyone other than
root,
sendmail runs as an ordinary
user.
If a site is down, messages to that site can collect in the queue. If the site is expected to be down for a protracted period of time, those queued messages will begin to time out and bounce. To prevent them from bouncing, you can move them to a separate queue directory. Later, when the down site comes back up, you can process that separate queue.
There are two ways to move mail to a holding queue. One way is to simply move them to a different directory, but you cannot do that if you are using queue groups. The other way is to use queue groups, as we show later.
If you are not using queue groups, you can move the affected messages to a separate queue using the contrib/qtool.pl script supplied with the sendmail source. If you are using queue groups, you should skip to the next section.
To use qtool.pl, you first make a destination directory, if one does not already exist:
#mkdir /var/spool/newqueue#chmod 700 /var/spool/newqueue
Next, run qtool.pl to move messages from the regular queue to the new holding queue:[190]
# contrib/qtool.pl /var/spool/newqueue /var/spool/mqueues/q.1When the down site comes back up at a later time (say, 50 days later), the messages that have been saved in the holding directory can be delivered by running the following command by hand (it has been wrapped to fit the page):
%/usr/sbin/sendmail -OQueueDirectory=/var/spool/newqueue -OTimeout.queuereturn=51d-OTimeout.queuewarn=0 -q
The -OTimeout.queuereturn=51d causes the
time-to-live in the queue to be extended to 51
days or one day longer than the oldest held
message. This prevents the held mail from wrongly
bouncing when you try to deliver it, should the
site not really be up yet.
The -OTimeout.queuewarn=0 prevents
nondelivery warnings from being sent that might
confuse the sender.
To move mail to a new queue with queue groups, the process is exactly the same as we have shown already, but with a few wrinkles. You have to stop sendmail, move the messages to a queue from which sendmail will not deliver, and then restart sendmail. The key differences between this approach and the one described in the previous section are:
The sendmail program should not be running when you move the messages out of the queue with qtool.pl.
When the down site comes back up, stop
sendmail again, and move the
messages back to the queue from where they came
with qtool.pl. Process them
there by hand with a long Timeout.queuereturn. When all of the
backlogged mail has flushed, you can restart
sendmail to run as
normal.
If it is not possible to stop sendmail for the time needed to flush the old messages, you can leave the messages in the holding queue. For this to work, you will need to generate a configuration file that does not use queue groups, and use that configuration file to flush the holding queue.
Queue quarantining is the process by which envelopes in the
queue are marked as being ineligible for delivery. Such
envelopes may then be manually or automatically reviewed. If
the review uncovers no problems, each such envelope may then
be delivered, bounced, or discarded. Queue quarantining
employs the queue’s qf
file, command-line switches, and the access database. Lost
envelopes (covered in the next section) are also a part of
this system.
A quarantined message is an envelope, containing one or more recipients, that is held in the queue pending review. It can either be an inbound or outbound envelope that, for policy or security reasons, should not be sent or delivered immediately, or not be sent or delivered as is.
For example, consider a user who has a history of sending offensive email. You might want to intercept such a user’s email on its way out, so it can be screened for words or phrases that the user has been previously warned about.
V8.13 sendmail implemented
quarantining by creating a new kind of queued file.
Instead of storing the envelope information in a
qf file, a
quarantined message has its envelope information
stored in an hf
file. The different file allows
sendmail to process messages
normally (quarantined messages are invisible) unless
you specifically ask it to handle quarantined
messages (make them visible).
Note that the mailstats program (The mailstats Program on page 364) automatically (without you needing to ask) includes the total count of quarantined messages in its output.
To ensure that the reason for quarantining a message
is not lost, a new qf file[191] line has been introduced. Called a
q line (q line on page 453), it stores the
reason the message was quarantined. In parallel, a
new macro, called ${quarantine} (${quarantine} on page 841) has also been added. It is intended
for use in rule sets, and contains the reason the
envelope was quarantined.
Note that quarantining integrates well with all the other queuing facilities of sendmail and even works with envelope splitting.
The command line can be used to quarantine and dequarantine envelopes. V8.13 has added one new command-line switch and modified another. We will show the use of the modified switch first, and then the new one.
Normally, the queue is processed by invoking a
-q command-line
switch (Periodically with -q on
page 427). This switch causes all the normally
scheduled (nonquarantined) envelopes to be
processed. By combining that switch with a
Q argument, you
tell sendmail to process
quarantined messages instead.
Note that it is not possible to operate on
both normal and quarantined envelopes at the same
time. That is, listing -q and then -qQ will not process both; it will
process only quarantined messages.
Unless limited with other -q letters, the -qQ switch will process
all the quarantined envelopes currently in the
queue. To further limit the envelopes to be
processed, specify any of these additional
switches in the same command line:
-qIident ← match any queue ID that contains ident (§11.8.2.3 on page 431) -q!Iident ← match any queue ID that does not contain ident (§11.8.2.4 on page 432) -qRrecip ← match any recipient address that contains recip (§11.8.2.3 on page 431) -q!Rrecip ← match any recipient address that does not contain recip (§ 11.8.2.4 on page 432) -qSfrom ← match any sender address that contains from (§11.8.2.3 on pa ge 431) -q!Sfrom ← match any sender address that does not contain from (§11.8. 2.4 on page 432) -qGname ← match any queue group with the name name (§11.8.2.5 on page 432) -qQreason ← match any queue group with the name reason (§11.10.2 on page 439)
For example, the following command line will
only process quarantined envelopes in the queue
group okayclients that were sent by the user
bob:
/usr/sbin/sendmail -qQ -qGokayclients -qSbob
The same switches can also be used to
determine what the mailq command will print. For example,
the following prints the status of all the
currently quarantined envelopes:
mailq -qQ
When the -Q
command-line switch is used with an argument (such
as -Q"reason")
it causes the specified envelopes to become
quarantined. When used without an argument, it
causes the specified envelopes to become
dequarantined.
For example, the following command line causes
all currently queued envelopes destined for the
user bob to
become quarantined:
/usr/sbin/sendmail -qSbob@your.domain -Q"Bob resigned today"
Here, the -qSbob@your.domain causes the queue to
be searched for all envelopes that are from the
sender (the -qS) bob at your domain. The -Q is followed by the
argument "Bob resigned
today", so all those messages are
quarantined using “Bob resigned today” as the
reason.
To dequarantine those same messages you might
use a command line like the following, where the
-Q is not
followed by an argument:
/usr/sbin/sendmail -qQ -qSbob@your.domain -Q
Here, the -qQ tells sendmail
to only operate on quarantined envelopes. The
-qS causes
sendmail to search the
quarantined envelopes for those from the sender
bob at your
domain. And finally, the -Q, without an argument, tells
sendmail to de-quarantine all
the envelopes found.
When the -qQ command-line switch is specified,
the mailq
command displays only quarantined messages and the
reason each was quarantined. For example:
# mailq -qQ
/var/spool/mailqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient----------
h2VJcN3M012024 875429 Thu Mar 24 16:44 bob@your.domain
QUARANTINE: Bob resigned today
fred@compeditor.domain
Total requests: 1Here, the -qQ command-line switch caused mailq to print only the
messages (there is just one in this example) that
were quarantined in the queue. Information about
the message is printed first. The reason the
message was quarantined is printed next. Then the
recipient or recipients of the message are printed
last.
If you have set up a Milter to automatically
quarantine messages, or have set up the access
database or created rule sets to do so, you should
run mailq with
this -qQ
command-line argument periodically, allowing you
to learn whether anything has been automatically
quarantined.
The end-of-message handler, inside a Milter, can call smfi_quarantine(3) (Milter smfi_quarantine() on page 1194) to quarantine the envelope being screened.
The access database
(The access Database on page
277) provides a single, central database with
rules to accept, reject, and discard messages
based on the sender name, address, or IP address.
It is enabled with the FEATURE(access_db) (Enabling the access Database Generally
on page 277).
A source text file used to create an access database might look (in part) like the following. Note that each line is composed of a key on the left and a value on the right, the two separated by tabs:[192]
QUARANTINEkeyQUARANTINE:keyreason
Note that the QUARANTINE term on the right may
optionally be followed by a colon and the
reason the envelope is
being quarantined. The
reason may contain
whitespace, but must not contain newlines and
should not be quoted.
For example, consider the following entries in a source file for an access database:
Connect:192.168.1.23 QUARANTINE:Bob's PC To:your.compeditor.gov QUARANTINE:Review mail to our compeditor From:head.hunter.domain QUARANTINE:Employee theft?
In the first line, Bob’s PC sends email by connecting to the SMTP port on the central mail server. Because of past behavior, or perhaps because of a worm or virus on Bob’s PC, we want to quarantine all outbound mail from that machine.
In the second line, management has requested
that all mail addressed to the domain your.compeditor.gov (using an SMTP
RCPT To:) be
quarantined for review before it is allowed to be
sent.
The last line says that inbound mail addressed
from the domain
head.hunter.domain (using an
SMTP MAIL
From:) be quarantined so that it may be
reviewed to see whether employee theft is being
attempted.
One limitation of the access database is that it cannot conveniently be used to combine tests. If your tests are more complex than the access database can handle, note that you may also test using rules in rule sets.
Any of the check_ rule sets (The Local_check_ Rule Sets on page 252)[193] and any of the header screening rule
sets (Rules Check Header Contents on page 1130) may be used to quarantine
envelopes. Any rule set that returns a $#error (error on page 720) with a $@ part (The parse Rule Set 0 on page 696) that
is the literal quarantine, will cause the message
to be quarantined:
R $* < @ bad.site > $* $# error $@ quarantine $: reasonHere, we show a rule in a rule set that
returns a $#error. Because the $@ part is the literal
quarantine, the
message will be quarantined. Note that the
$: part
contains the reason the message is being
quarantined.
Note that rule set quarantining affects all recipients of that envelope.
To illustrate rule set quarantining, consider
the following mc
configuration lines that cause any message which
contains a special X-review: header to be held for
review:
LOCAL_CONFIG HX-review: $>Xreview LOCAL_RULESETS SXreview R YES $#error $@ quarantine $: X-review held for review
The first part of our example, the LOCAL_CONFIG part,
defines a header. This header definition tells
sendmail to pass all X-Review: header values
through (the $>) the Xreview rule set.
The second part (LOCAL_RULESETS) defines the Xreview rule set (the
S line) which
contains a single rule that looks for a value that
is the literal word YES. If that header’s value is YES, the
message is quarantined with the reason shown. If
that header is missing, or if it has any other
value, this quarantine step is skipped.
Note that rule sets can detect whether a
message has already been quarantined by checking
the ${quarantine}
sendmail macro (${quarantine} on page 841). If that macro has a value, the
message was already quarantined.
Whenever a message is quarantined, the fact that it was quarantined and the reason for doing so are logged using syslog(3). One log line is produced to record the quarantine event. Another is produced for each recipient to show that each was also quarantined.
The information logged for the quarantine event varies depending on the method used to quarantine. If a rule set was used, for example, a log line like the following might be produced:
Oct 9 11:26:00 your.domain sendmail[4788]: f99IPuIH004788: ruleset=check_mail, arg1=bob@compeditor.gov, quarantine=Hold mail from compeditor.gov
This line (wrapped to fit the page) shows that
the check_mail
rule set found the address
bob@compeditor.gov in its workspace
and quarantined the message for the reason
shown.
A Milter can also cause messages to be quarantined. The log line, produced by such a Milter event, might look like the following:
Oct 23 09:25:59 monkeyboy sendmail[52314]: f99IPuIH004787: milter=DocMilter, quarantine=Suspect application/ms-word attachment
Here the Milter named DocMilter found a MIME type that
indicated a possible Microsoft Word document was
included as an attachment.
In addition to logging an event, each recipient is also logged. For example, consider the following log line:
Nov 21 09:32:13 your.domain sendmail[33522]: fALHVwAQ033522: to=<bob@your.domain>, delay=00:00:06, mailer=local, pri=30029, quarantine=Suspect application/ms-word attachment, stat=quarantine
Here the quarantine= equate shows the reason the
message was quarantined, and the stat= equate prints the
literal word quarantine.
When Milters, the access database, and rule sets are
used to automatically quarantine messages, a
script may be devised to detect the quarantine= equate in
the logging output. When run nightly, such a
script might email the postmaster with a summary
of quarantined messages for that day.
The qtool.pl program is located in the contrib subdirectory of the source distribution. It is a perl(1) script that allows you to move envelopes between queues, bounce envelopes, and remove envelopes.
In general, if you use queue groups (Queue Groups (V8.12 and Later) on page 408), you should not use qtool.pl to move queued messages. However, it is always safe to move quarantined messages, because they are invisible to sendmail unless you manually cause sendmail to recognize them.
As of V8.13, the -Q command-line switch tells qtool.pl to operate on
quarantined messages rather than on normal
messages. For example, the following command
causes all the quarantined messages in the main
queue to be moved to a holding queue:
#./qtool.pl -Q /var/spool/hold /var/spool/mqueueAlso, as of V8.13, a new %msg hash variable has
been introduced. Called quarantine_reason, it can be used to
match strings in the literal reason the message
was quarantined. You could use this, for example,
to bounce all messages that were quarantined with
a reason that contained the word Virus:
#./qtool.pl -b -Q -e '$msg{quarantine_reason} =˜ m/Virus/'See the online manual for the qtool.pl program (contrib/qtool.8) for a complete guide to using that program.
As of V8.13, the qf file’s q line is used to store the reason that
an envelope was quarantined. The q line should appear
only in quarantined envelopes, that is, in
hf files, not
in qf files. If
a q line
appears in a qf
file, that file will be silently converted into an
hf file. Thus,
it does no good to simply rename an hf file into a qf file.
The format of a q line looks like this:
qreasonThere may be only one q line in an hf file. The
reason is the reason
the envelope was quarantined.
Each release of sendmail offers more and better ways to handle queue problems. They are mostly implemented as options. Table 24-7 on page 966 lists all options that affect the queue. Whenever you upgrade to a new sendmail release, be sure to read the RELEASE_NOTES for information about new ways to solve queueing problems.
The queue directory should never be shared among machines. Such sharing can make detection of orphaned locks impossible. Bugs in network-locking daemons can lead to race conditions in which neither of two machines can generate a queue identifier.
Homespun programs and shell scripts for delivery of local mail can fail and lose mail by exiting with the wrong value. In the case of a recoverable error (a full disk, for example), they should exit with EX_OSERR or EX_TEMPFAIL. Both of these exit values are defined in <sysexits.h> and cause the message to be re-queued.
Because sendmail does a chdir(2) into its queue directory, you should avoid removing and re-creating that directory while the sendmail daemon is running. When processing the queue, sendmail tries to read the queue directory by doing an opendir(3) of the current directory. When the queue directory is removed, sendmail fails that open and syslog(3)s the following warning:
orderq: cannot open "/usr/spool/mqueue" as ".": No such file or directory
Some very old versions of sendmail had a bug in handling the queue that could cause a message to be lost when that message was the last in a queue run to be processed. This, among other reasons, is good cause to always make sure you are running the latest version of sendmail.
The sendmail program assumes that only it and other trusted root programs will place files into its primary queue directory. Consequently, it trusts everything it finds there that is correctly formatted and has the correct ownership and permissions. The queue directory must be protected from other users and untrusted programs.
If the queue directory is on a disk mounted separately from / and /usr, be certain to mount that disk before starting the sendmail daemon. If you reverse these steps, the sendmail daemon will chdir(2) into the queue before the mount. One effect of the reversal is that incoming mail will use a directory different from that used by outgoing mail. Another effect is that incoming queued mail will be invisible. Yet another effect is that the outgoing queue will never be processed by the daemon.
When using multiple queues, it might be possible to umount a directory while sendmail is still running, but you should avoid this temptation. Never mount or umount queue disks while sendmail is running. Stop sendmail first, do your maintenance, and then restart sendmail.
If a Milter deletes a recipient, and if queue groups are used, that recipient can cause a queue group to wrongly be selected. This defect has been fixed in V8.14.
When using V8.12 and later
sendmail, avoid moving queue
files yourself. The qf file, for example, internally stores
the full pathname of the df file’s directory, which means you
would need to edit that line as part of a move.
Also, sendmail can split
messages at message submission time into multiple
qf files,
possibly in different queues, all sharing a
df file with
hard or symbolic links to it. This complexity
makes moving queue files a complex
undertaking.
The qf file holds all the
information that is needed to perform delivery of a queued
mail message. The information contained in that file, and
its appearance, changes from release to release of
sendmail. Here, we document the
qf file that is
used with V8.14 sendmail. Note that
V8.7 introduced a V
version line that enabled later versions to correctly
process older versions’ queue files.
This section must be taken with a proverbial grain of salt.
The internals of the qf
file are essentially an internal interface to
sendmail and, as such, are
subject to change without notice. The information offered
here is intended only to help debug
sendmail problems. It is
not intended (and we strongly
discourage its use) as a guide for writing files directly to
the queue.
The qf file is
line-oriented, containing one item of information per line.
Each line begins with a single character (the code
character), which specifies the contents
of the line. Each code character is followed, with no
intervening space, by the information appropriate to the
character. The complete list of code characters is shown in
Table 11-6.
|
§ |
Meaning |
Version |
How many | |
| [a] | ||||
|
|
A line on page 446 |
AUTH= parameter |
V8.10 and later |
At most, one |
|
|
B line on page 447 |
Message body type |
V8.6 and later |
At most, one |
|
|
C line on page 447 |
Set controlling user |
V5.62 and later |
At most, one per R line |
|
|
d line on page 448 |
Datafile directory |
V8.12 and later |
Exactly one |
|
|
D line on page 449 |
Datafile name |
Obsolete as of V8.7 |
Exactly one |
|
|
E line on page 449 |
Send errors to |
V8.6 and earlier |
Many |
|
|
F line on page 450 |
Saved flag bits |
V8.1 and later |
Exactly one |
|
|
H line on page 451 |
Header line |
All versions |
Many |
|
|
I line on page 451 |
Inode and device information for the
|
V8.7 and later |
Exactly one |
|
|
K line on page 452 |
Time last processed |
V8.7 and later |
Exactly one |
|
|
M line on page 452 |
Message (why queued) |
All versions |
Many[a] |
|
|
N line on page 452 |
Number of times tried |
V8.7 and later |
At most, one |
|
|
P line on page 453 |
Priority (current) |
All versions |
At most, one |
|
q |
q line on page 453 |
Reason this envelope was quarantined |
V8.13 and later |
At most, one |
|
|
Q line on page 454 |
The DSN ORCPT address |
V8.7 and later |
At most, one per R line |
|
|
r line on page 454 |
Final recipient |
V8.10 and later |
At most, one |
|
|
R line on page 454 |
Recipient address |
All versions |
Many |
|
|
S line on page 455 |
Sender address |
All versions |
Exactly one |
|
|
T line on page 456 |
Time created |
All versions |
Exactly one |
|
|
V line on page 457 |
Version |
V8.7 and later |
Exactly one |
|
|
Z line on page 458 |
DSN envelope ID |
V8.7 and later |
At most, one |
|
|
! line on page 458 |
Deliver-by specification |
V8.12 and later |
At most, one |
|
|
$ line on page 458 |
Restore macro value |
V8.6 and later |
At most, one each macro |
|
|
.line on page 459 |
End of |
V8.7 and later |
Exactly one |
[a] a Prior to V8.12,
there could be only a single | ||||
We discuss the individual lines in the qf file by code letters.
Each letter is presented in alphabetical order rather than
the order in which they should appear in the qf file.
AUTH= parameter V8.10 and later
RFC2554 describes the currently approved method for
SMTP authentication. One part of this method is to
add the AUTH= extension to the MAIL From: command for
ESMTP. This A
line in the qf
file is used to store the value passed in that
parameter.
If you compiled sendmail with
SASL defined (SASL on page 137),
this value will be the actual value passed by the
AUTH=. Otherwise, it is the value of $f ($f on page 824) normalized to
the local domain if $f lacks a domain.
Message body type V8.6 and later
The message body type is described under the -B command-line switch
(-B on page 232). The
B line in the
qf file stores
whatever the body type was set to, either from the
command line or by the SMTP MAIL command. The two
usual body types are 8BITMIME and 7BIT.
The form of the B
line is:
BtypeThere must be no space between the B and the
type. If the
type is missing, the
body type becomes the character value zero. If the
entire B line is
missing, the default is 7BIT. If
type is longer than
MAXNAME as defined in conf.h
(MAX... on page 120) when
compiling sendmail, it is
truncated to MAXNAME-1 characters when the qf file is read.
Note that the type must be
either 7bit or
8bitmime.
Anything else will not be detected when the qf file is read and
might eventually cause the ESMTP dialog to
fail:
501 <sender>... Unknown BODY type badtype
This error will be reproduced at every MX site for the recipient until a site that does not speak ESMTP is found or until the MX list is exhausted.
Set controlling user V5.62 and later
To ensure secure handling of delivery, recipient
addresses that are either a file or a program
require that sendmail perform
delivery as the owner of the file or program rather
than as the user defined by the DefaultUser option
(DefaultUser on page 1000). A
file address is one that begins with a / character. A program
address is one that begins with a | character. Both
characters are detected after quotation marks have
been stripped from the address.
To prevent potential security violations,
sendmail must take special
precautions when addresses in the qf file result from
reading a ~/.forward or :include: file. When such an address is
to be placed into the qf file (whether as a recipient’s
address in an R
line or as an error recipient’s address in an
E line),
sendmail first places a
C line (for
Controlling user) into the file and then the
recipient’s address. The C line specifies the owner of the
~/.forward or :include: file:
Cgeorge RPF:/u/users/george/mail/archive Cben RPF:|/u/users/ben/bin/mailfilter
Here, when sendmail later
delivers to the recipients in this qf file, it first
converts its user identity to that of the user
george, and then resets
itself back to being root
again. The same process repeats with the next
recipient, except that sendmail
changes from root to
ben and back again. If there
is no C line
preceding an R
line, the previous C line’s value is carried down:
Cgeorge
RPF:/u/users/george/mail/archive
RPF:|/u/users/ben/bin/mailfilter ← controlling user is georgeThe form of the C
line in the qf
file is:
Cuser← prior to V8 Cuser:eaddr← V8.1 through V8.7.5 Cuser:uid:gid:eaddr← V8.7.6 and later
The C must begin
the line and be immediately followed by
user, with no
intervening space. If no
user follows the
C, any prior
controlling user is cleared and the identity that is
used reverts to that specified by the DefaultUser option
(DefaultUser on page 1000). If
present, the user is the
login name of the owner of the
~/.forward or :include: file that
yielded the address in the next following R or E line. If
user is the name of a
user who is unknown to the system, prior to V8.7.6
and prior to V8.8 the effect was the same as though
it were missing. Beginning with V8.8 and V8.7.6, an
unknown user causes the
identity to become that of the
uid and
gid. Beginning with V8
sendmail, an optional
eaddr might be last. If
present, the eaddr gives
the address to use for error messages.
There can be only one C line immediately preceding each
R and E line. Two C lines in a row have
the effect of the second superseding the
first.
Data file directory V8.12 and later
Beginning with V8.12 sendmail, it
is possible to split envelopes for more efficient
delivery. When sendmail splits
an envelope, the new qf file will share a df file with the prior
qf file. But to
ensure that each qf file has it own df file,
sendmail creates a hard link
to make a copy of the df file. That way, the old qf file uses the old
df file, and
the new qf file
uses the new df
file. The two df
files are the same because they are hard-linked
together.
A problem arises when the two qf files are saved on two different
disks. Because it is not possible to hard-link
across disks, the new qf file is put on the new disk, but the
new df file is
left on the old disk. That way, an efficient hard
link can still be made, but now the new qf file and its new
df file are on
different disks.
The d qf-file line
was introduced to allow a qf file to find its corresponding
df file when
that df file is
on a different disk. Whenever a qf file has a
corresponding df
file on a different disk, that qf file will contain a
d line that
looks like this:
d/pathThe /path must be the full
pathname of the directory that contains the df part. If
/path is missing, or is
not a directory that was set in the configuration
file, the following error is logged and the qf file is considered
bad, and marked as such (Bogus qf Files on page 419):
Losing qf file: bogus queue file directoryDatafile name Obsolete as of V8.7
Beginning with V8.7, sendmail
looks for its datafile (the file containing the
message body) under the same name as its qf file, but with the
q changed into
a d. Prior to
V8.7, the D line
in the qf file
contained the name of the file that contained the
message body. If the D line was missing, there was no
message body. The form of the qf file D line was:
DfileThe D must begin
the line. The file must
immediately follow with no intervening space. All
text, from the first character following the
D to the end of
the line, is taken as the name of the file. There is
no default for file;
either it must be present, or the entire D line must be
absent.
The sendmail program opens the
df
file for reading. If that
open fails, sendmail syslog(3)s
the following error message at LOG_CRIT and
continues to process the qf file:
readqf: cannot open dfAA12345
Be aware that sendmail attempts
to remove the file after
it has been delivered to all recipients. If
sendmail is unable to remove
the file, and if the
LogLevel option
(LogLevel on page 1040) is
greater than 97, sendmail
syslog(3)s the following warning at
LOG_DEBUG:
file: unlink-fail#
The file is the name of the
file that could not be removed. The
# is the error number,
as defined in
/usr/include/errno.h.
The df file is
opened only when processing the queue file, not when
printing it. When printing the queue, the df is
stated so that its size can
be printed.
Send errors to V8.6 and earlier
Notification of errors often requires special handling
by sendmail. When mail to a
mailing list fails, for example,
sendmail looks for the owner
of that list. If it finds one, the owner, not the
sender, receives notification of the error. To
differentiate error notification addresses from
ordinary sender and recipient addresses, pre-V8.7
sendmail stored error
addresses separately in the qf file, one per E line. Beginning with
V8.7, this E line
is no longer used. Instead,
sendmail uses the S line.
The form of the E
line in the qf
file looks like this:
Eaddr ← V8.6 and earlier
The E must begin
the line. One or more addresses can be entered on
that same line. Whitespace and commas can surround
the individual addresses. Note, however, that
sendmail places only a single
address on each E
line. There can be multiple E lines. Each is processed in
turn.
Each line is fully processed as it is read. That is, the line is scanned for multiple addresses. Each address that is found is alias-expanded. Each resulting new address is processed by rule sets 3 and 0 to resolve a delivery agent for each.
If an alias expands to a program or a file (text that
begins with a /
or | character),
that text is sent out in the delivered message’s
Errors-To: line
in that form. This can cause confusion when the
message is later processed and bounced at the
receiving site.
Saved flag bits V8.1 and later
Under V8 sendmail, the Timeout.queuewarn option
(Timeout on page 1097) can
specify an interval to wait before notifying the
sender that a message could not immediately be
delivered. To keep track of whether such a
notification has been sent,
sendmail stores the state of
its EF_WARNING envelope flag in the qf file. If that flag is
set, notification has already been sent.
Error mail messages sent by
sendmail can occasionally be
queued, rather than immediately delivered. The
Timeout.queuewarn option notification
should not be sent for such mail. If such mail
remains in the queue too long, it should be canceled
rather than bounced. V8
sendmail saves the state of
the EF_RESPONSE envelope flag in the qf file. If that flag is
set, the message is an error notification.
Beginning with V8.8, sendmail
also records the state of the EF_HAS8BIT flag (the
message body contains 8-bit data) and the
EF_DELETE_BCC flag (delete empty Bcc: headers, Bcc: on page 1152).
All envelope flags are listed in Table 15-5 on page
545. The F line
is used to save envelope flags for later
restoration. Its form looks like this:
FflagsHere, the flags are any
combination of those shown in Table 11-7.
|
Flag |
Description |
|
|
Restores the EF_HAS8BIT flag |
|
|
Restores the EF_DELETE_BCC flag |
|
|
Restores the EF_RET_PARAM flag |
|
|
Restores the EF_NO_BODY_RETN flag |
|
|
Restores the EF_RESPONSE flag |
|
|
Restores the EF_SPLIT flag |
|
|
Restores the EF_WARNING flag |
Only the letters listed in the table are recognized. Other letters are silently ignored. Note that these flags might be done away with in later versions of sendmail and new flags might be added without notice.
For security protection, V8 sendmail rejects and logs the following flag sequence:
From
↑
a space hereSee Funny Flag Bits in qf File on page 421 for more information about this.
Header line All versions of sendmail
The lines of text that form the message header are
saved to the qf
file, one per H
line. Any header lines added by
sendmail are also saved to
H lines in the
qf file.
The form of the H
line is:
HdefinitionThe H must begin
the line, and the
definition must
immediately follow with no intervening space. The
definition is exactly
the same as, and obeys the same rules as, the
H commands in
the configuration file (Overview on page 1120). Beginning with V8.10, if the
header lacks header flags, an empty pair of ? characters are
prefixed to the definition.
When sendmail writes header lines
to the qf file,
it pre-expands sendmail macros
(replaces expressions such as $x with their values)
and preresolves conditionals ($?, $!, and $.). Beginning with
V8.10, the headers in the qf file might have been rewritten by
rule sets.
The order in which H lines appear in the qf file is exactly the
same as the order in which they appear in the
delivered message.
Inode and device information for the df file V8.7 and later
When a machine crashes under Unix, files in a directory can become detached from that directory. When this happens, those orphaned files are saved in a directory called lost+found. Because filenames are saved only in directories, orphaned files are nameless. Consequently, Unix stores them in lost+found using their inode numbers as their names.
To illustrate, consider finding these four files in lost+found after a crash:
#1528 #1200 #3124 #3125
Two of these are qf
files, and two are df files. Beginning with V8.7
sendmail, the qf files contain a
record of the inode numbers for their corresponding
df files. That
information is stored in the I line:
Imajor/minor/ino
Here, the major and
minor are the major and
minor device numbers for the disk device that the
df file was
stored on. The ino is the
inode number for the df file. In our
lost+found example, the
following command could be run to pair up the
orphaned files:
% grep "^I.*/.*/" *
#1200:I123/45/3124
#1325:I123/45/1528This shows that the qf file #1200 has
the df file
#3124 and that the qf file
#1325 has the df file
#1528.
The sendmail program does not
check the inode number in the I line against the
actual inode number of the df file. Instead, the I line is generated
afresh each time the qf file is processed.
When df, qf,
and xf subdirectories are used,
and when those subdirectories are on separate disks,
a crash of one disk can leave the df or qf file intact, and the
other in lost+found.
The time last processed from the queue V8.7 and later
The MinQueueAge
option (MinQueueAge on page 1057)
sets the length of time a queued message must remain
queued before delivery can again be tried. Each time
sendmail processes a qf file, it subtracts
the time stored in the K line from the current time and
compares the result to the MinQueueAge. If sufficient time has not
passed, the rest of the processing is skipped. (Note
that this test is performed only if the qf file has been
processed at least once; see the N line in N line on page 452.)
The time stored in the K line looks like this:
K703531020
This number represents the date and time in seconds
since January 1, 1970. Every time the qf file is processed
(delivery is attempted), the K line is updated with
the current time.
Why the message was queued All versions of sendmail
When a mail message is placed into the queue because
of an error during the delivery attempt, the nature
of that error is stored in the M line of the qf file. The error is
usually prefixed with Deferred:
Deferred: reasonDelivery can be deferred until a later queue run
because of a temporary lack of services. For
example, the reason might
be “remote host is down.”
The form of the qf
file M line
is:
MmsgThe M must begin
the line. It is immediately followed by the
msg with no intervening
space. The text of msg is
everything up to the end of the line. The
msg created by
sendmail can include the word
Deferred:
followed by a reason. The envelope-specific M line should appear
before the S
line.
Beginning with V8.12, each recipient also has an
M line
preceding its R
line.
If the msg is missing,
sendmail simply prints a
blank line rather than a reason when showing the
queue with mailq or the
-bp
command-line switch. If the M line is missing entirely,
sendmail prints
nothing.
The maximum number of characters in
msg is defined by
MAXLINE in conf.h (MAX... on page 120). Prior to V8.12,
there could be only one M line in a qf file.
Number of times tried V8.7 and later
Each time delivery is attempted for a message, the
number stored in its qf file’s N line is incremented by one. This
number always begins at zero.
When delivering many messages to a single host, sendmail remembers failures. If one message fails to make it all the way through an SMTP dialog, all the following messages to that same host will be deferred (not attempted during the current queue run). For those deferred messages, the number of tries is correctly incremented as though the delivery was actually attempted.
The value in this N
line is used to determine whether the delay of the
MinQueueAge
option (MinQueueAge on page 1057)
should be triggered. This value, when zero, can also
be used to enable a special first-time connection
timeout (Timeout.iconnect (V8.8 and later)
on page 1103).
Priority when processed from queue All versions of sendmail
Not all messages need to be treated equally. Messages that have failed often, for example, tend to continue to fail. When sendmail processes the messages in its queue, it sorts them by priority and attempts to deliver those with the lowest priority value first.
When a mail message is first placed into the queue, it
is given an initial priority calculated when it was
first created (RecipientFactor on
page 1077), which is stored in the P line:
P640561
This number in the qf file is really a cost. The
lower it is, the more
preferentially the message is treated by
sendmail. Each time the
qf file is
read, the number in the P line is incremented. The size of that
increment is set by the value of the RetryFactor option
(RetryFactor on page 1081). If
that option is negative, this logic is
inverted.
The form of the qf
file P line
is:
PpriThe P must begin
the line. The pri is a
text representation of an integer value. The
pri must immediately
follow the P with
no intervening space. The text in
pri is converted to an
integer using the C-library routine
atol(3). That routine allows
pri to be represented
in text as a signed decimal number, an octal number,
or a hexadecimal number.
If pri is absent, the
priority value used is that of the configuration
file RetryFactor
option. If the entire P line is absent, the priority value
begins at zero.
There should be only one P line in any qf file. Multiple P lines cause all but
the last to be ignored.
Reason an envelope was quarantined V8.13 and later
When an envelope is quarantined (Queue Quarantining on page 438) the
reason is stated in this q line. The q line is not part of a qf file, but is actually
in the quarantined hf file.
qreasonHere, the reason can be manually inserted using sendmail’s command line, or automatically inserted via the access database or rule sets.
The DSN ORCPT address V8.7 and later
When a mail message arrives that includes an ORCPT parameter for the ESMTP RCPT command (see RFC1891), sendmail needs to save that parameter’s information separately from the RCPT recipient address:
RCPT To:<gw@wash.dc.gov> ORCPT=rfc822;gw@wash.dc.gov
↑ ↑
recipient address parameter's informationNot all sites understand DSN. If sendmail forwards the message to such a site, it needs to omit the ORCPT parameter. Consequently, sendmail must not store that parameter with the RCPT address.
The Q line is used
to separately store the ORCPT parameter
information:
Qtype;addr
The type;addr is
defined by RFC1891. The
sendmail program checks the
syntax of addr when that
information is received, but otherwise merely stores
type;addr
as is in the Q
line.
There must be only a single Q line for each recipient R line, and each such
Q line must
precede its corresponding R line.
Final-Recipient DSN address V8.10 and later
When sendmail bounces a mail message, it does so using DSN (T= on page 754). The type of address and the actual address of the final original recipient are reported in the bounce message:
Final-Recipient: RFC822; nosuchuser@site.com
This Final-Recipient line shows the type of
address (here RFC822) and the actual address (here
nosuchuser@site.com) of the final
recipient.
Beginning with V8.10, sendmail
composes this address expression only once (when the
message is queued) and stores it in case the message
bounces. The text following the Final-Recipient: is
stored in the r
line in the qf
file, and looks like this:
rRFC822; nosuchuser@site.com
Note that sendmail performs no
checks on the text following the r. This means that
invalid DSN information placed there will become the
text that follows the Final-Recipient: in the bounce
message.
Recipient’s address All versions of sendmail
The qf file lists
all the recipients for a mail message. There can be
one recipient or many. When
sendmail creates the qf file, it lists each
recipient address on an individual R line. The form of the
R line in the
qf file looks
like this:
Rflags:addr
The R must begin
the line. Only a single address can appear on each
R line. There
can be multiple R
lines. Each is processed in turn.
If the colon is present and if the version of the
qf file is
greater than 0, the characters between the R and the colon are
interpreted as flags that further define the nature
of the address:
P(primary)Addresses can undergo many transformations prior to delivery. When expanding aliases, for example, the address george might be transformed into two addresses via a ~/.forward file: george@here and george@there. In this instance, george is the primary address, and the aliases are secondary addresses. If aliasing yields only a single transformation, the single new address is considered primary. Addresses that are received via an RCPT SMTP command, or on the command line, are always considered primary, as are all other recipient addressees prior to aliasing.
N(notify)Recipient addresses can lead to various
kinds of notification based on the nature of the
DSN NOTIFY extension to the RCPT SMTP command.
That notification can be either NEVER or some
combination of SUCCESS, FAILURE, or DELAY.
Internally, sendmail uses the
absence of the latter three to imply NEVER. This
N flag simply
says that the DSN NOTIFY extension appeared in the
message. If the N is absent, but an S, F, or D is present, DSN
information will not be propagated. Note that
NOTIFY can also be specified by using the -N command-line switch
(-N on page 244).
S,
F, D(success,
failure, delay)The DSN NOTIFY extension to the RCPT SMTP command will specify either NEVER or some combination of SUCCESS, FAILURE, or DELAY. When any of these is specified, its first letter is used as a flag for the recipient address. SUCCESS means to notify the sender that final delivery succeeded. FAILURE is used to notify the sender that some step toward delivery failed fatally. DELAY lets the sender know that the message has been delayed but delivery will continue to be attempted.
AIf the address in the R line is the result of
an alias expansion, this A flag is included to indicate that
fact.
Each R
line is fully processed as it is read. That is,
the line is scanned for multiple addresses. Each
address that is found is alias-expanded. Each
resulting new address is processed by the canonify rule set 3 and
the parse rule
set 0 to resolve a delivery agent for each.
Sender’s address All versions of sendmail
Each mail message must have a sender. The sendmail program can determine the sender in four ways:
If the sender is specified in the envelope of an SMTP connection, that sender’s address is used.
If the -f
command-line argument is used to run
sendmail, the sender’s
address is the address following the -f.
If the sender is not specified in the envelope, the address that is used is that of the user who ran the sendmail program. If that user is unknown, the sender is made to be postmaster.
When processing the queue, the sender’s
address is specified in the S line of the qf file.
The form of the S
line in the qf
file looks like this:
SaddrThe S must begin
the line. Exactly one address must follow on that
same line. Whitespace can surround that address.
There can be only one S line in the qf file.
If the addr is missing,
sendmail sets the sender to
be the user who ran sendmail.
If that user is not known in the
passwd file (or database),
sendmail syslog(3)s the
following message and sets the sender to be
postmaster:
Who are you?
The resulting address is then processed to extract the
user’s full name into $x ($x on page
851). Finally, the sender’s address is rewritten by
the canonify rule
set 3, the parse
rule set 0, and the final rule set 4.
Under all versions of sendmail,
the address in the S line will include any RFC822 comment
text that appeared with the original message. Under
V8.7, if the F=c
flag (F=c on page 768) is
set for the sender’s delivery agent, all comment
text is stripped from the address.
If sendmail is compiled with
USERDB defined (USERDB on page
150), the sender address can optionally be rewritten
by the User Database before it is placed into the
S line. Such
rewriting is allowed only if the delivery agent for
the sender includes the F=i flag (F=i
on page 772).
Time created All versions of sendmail
To limit the amount of time a message can remain in
the queue before being bounced,
sendmail must know when that
message was first placed in the queue. That time of
first placement is stored in the T line in the qf file. For example,
the following number represents the date and time in
seconds since January 1, 1970:
T703531020
Each time sendmail fails to
deliver a message from the queue, it checks to see
whether too much time has passed. It adds the
T line value to
the value specified in the Timeout.queuereturn option (Timeout on page 1097). If that sum is
greater than the current time, the message is
bounced instead of being left in the queue.
Messages are occasionally left in the queue for longer than the normal timeout period. This might happen, for example, if a remote machine is down but you know that it will eventually be brought back up. There are two ways to lengthen the amount of time a message can remain in the queue.
The preferred way is to create a temporary separate
queue directory and move the necessary queued file
to that temporary holding place. When the remote
site comes back up, you can later process the files
in that other queue by running
sendmail with an artificially
long Timeout.queuereturn value (Process Alternative Queues on page
436).
A second way to extend the life of messages in the
queue is to edit the qf file and change the value stored in
the T line. Just
add 86400 to that value for each day you want to
extend. Care is required to avoid editing a file
that is currently being processed by
sendmail.[194]
There is currently no plan to give sendmail the ability to rejuvenate queued messages (make old messages appear young).
The form of the T
line in the qf
file is:
TsecsThe T begins the
line, and the secs must
immediately follow with no intervening space. The
numeric text that forms
secs is converted to an
integer using the C-library routine
atol(3). That routine allows
secs to be represented
in text as a signed decimal number, an octal number,
or a hexadecimal number.
If secs is absent or the
entire T line is
absent, the time value is zero. A zero value causes
the mail message to time out immediately.
There should be only one T line in any qf file. Multiple T lines cause all but
the last to be ignored.
Version of the qf file V8.7 and later
As sendmail evolves, it will
continue to add new abilities to the qf file. To protect old
versions of sendmail from
wrongly misinterpreting new configuration files, the
V line has been
introduced. Note that prior to V8.7
sendmail there was no
V line. The
V line, and
qf file version
numbers for more modern implementations of
sendmail, are shown in Table 11-8.
|
qf version |
sendmail versions |
|
V1 |
V8.7.5 and earlier |
|
V2 |
V8.7.6 through V8.9.3 |
|
V4 |
V8.10 through V8.11 |
|
V5 |
V8.10 through V8.11 with _FFR_QUEUEDELAY defined |
|
V6 |
V8.12 |
|
V7 |
V8.12 with _FFR_QUEUEDELAY defined |
|
V8 |
V8.13 added support for Queue Quarantining |
If the version found in a qf file is greater than that currently
supported by sendmail, the
following error will be printed if in verbose
mode:
Version number in qf (bad) greater than max (max)
and the following message will be logged:
Losing qf file unsupported queue file versionThe bad qf file
will then be turned into a Qf file (marked as lost).
DSN ENVID envelope identifier V8.7 and later
The MAIL ESMTP command can optionally be followed by an RFC1891 ENVID envelope identifier:
MAIL From: <address> ENVID=envelopeID
ENVID is used to propagate a consistent envelope
identifier (distinct from the Message-ID: header,
Message-ID: on page 1159)
that is permanently associated with a
message.
The Z line holds
that ENVID envelope identifier information:
ZenvelopeIDThe ENVID information needs to be held separately from
the S sender line
because sendmail has no way to
determine in advance whether a recipient host speaks
ESMTP.
There must be only a single Z line in any qf file. The ${envid}
sendmail macro (${envid} on
page 823) also stores the ENVID value.
Deliver-by specification V8.12 and later
Beginning with V8.12, sendmail
supports the DELIVERBY SMTP extension (defined by
RFC2825). If the DeliverByMin option (DeliverByMin on page 1003) was defined
with a positive value, a BY= equate can follow the SMTP MAIL From: command for
inbound email. The BY= equate defines the window of time
during which the message should be delivered. That
equate’s time value can optionally be followed by a
flag that states what to do upon delivery (an
r flag), or
upon delivery failure (an n flag). There can also be a flag that
advises sendmail to trace
delivery (a v
flag). The BY=
information is saved in the qf file on an ! line:
!flag timeHere, the time is the time
specified by the By= and the
flag is a 1-byte
integer that encodes a value of 1 (notify the sender
upon delivery), or 2 (return the message if it
cannot be delivered in time). Additionally, the
flag can be OR’d with a 0x10
(trace the delivery).
This ! line appears
for inbound mail only, and appears only if you have
configured your mc file to
define the DeliverByMin option with a positive
value.
Restore macro value V8.6 and later
The sendmail program uses the
$r
sendmail macro ($r on page 842) to store the
protocol used when sendmail
first received a mail message. If the message was
received by using SMTP, that protocol is smtp. Otherwise, it is
NULL.
The sendmail program uses the
$s
sendmail macro ($s on page 844) to store the
full canonical name of the sender’s machine.
The sendmail program uses the
$_
sendmail macro ($_ on page 801) to
store RFC1413 identd(8)
information and IP source-routing
information.
When sendmail creates a qf file, it saves the
values of the $r,
$s, and
$_
sendmail macros in lines that
begin with $.
The form of the $
line in the qf
file looks like this:
$Xvalue${XXX}value
The $ must begin
the line, and the sendmail
macro’s single-character name (the
X) or multicharacter
name (the {XXX}) must immediately
follow with no intervening space. The
sendmail macro’s name is
followed (again with no intervening space) by the
value of the macro.
If value is missing, the
value given to the macro is NULL. If the macro name
and value are missing,
the macro \ is
given a value of NULL. If both are present, the
macro whose name is specified is given the value
specified (value).
There can be multiple $ lines. The
sendmail macro names to be
stored in the qf
file are listed in the $={persistentMacros} class ($={persistentMacros} on page 873).
Mark EOF in qf file V8.7 and later
One form of attack against
sendmail involves appending
information to an existing qf file. To prevent such attacks, V8.7
introduced the dot line. In a qf file, any line that
begins with a single dot:
.followed by anythingis considered to mark the end of the file’s useful
information. Upon encountering that dot,
sendmail continues to read
the qf file. If
any line follows the dot line,
sendmail logs the following
message and changes the qf file into a Qf file (Extra Data at End of qf File on page
420):
SECURITY ALERT: extra data in qf: bogus line here[175] * Of course, if sendmail is started somewhere else or by someone else, the queue directory will be a subdirectory under that other starting directory.
[176] * Programs should not depend on the lead letter actually encoding the hour. It is intended only to ensure that all identifiers be unique within any 24-hour period and as an aid to scripts that need to extract information from logfiles.
[177] † Omission of the
letters y and
z is
intentional.
[178] * Historical footnote: this stems from the days when the only atomic filesystem call was link(2).
[179] * The degenerate case of multiple queues is a single queue. We examine a single queue here, for simplicity.
[180] * Again, for simplicity, we assume a standard hard disk. Naturally, reads will be much faster on specialty hardware such as memory-based disks.
[181] † Operations that cause the disk head to move, such as file unlinks, are called IOPs. Typical hard disks are limited to about 120 IOPs per second. When sendmail successfully delivers a message it can consume from 10 to 13 IOPs per message.
[182] * As measured on a 300 MHz Intel machine running Berkeley Software Design Inc. (BSDI) Unix version 3.
[183] * Unless you ran a separate queue-processing daemon for each set of queues. Then you could call them queue groups.
[184] * However, we recommend that you use only letters, the dash character (hyphen), and the underscore character. Other characters might become illegal in future releases of sendmail.
[185] * You can copy the rules created by that feature and paste them into your own. However, that is not recommended because the copied rules might change with new releases of sendmail, and then the old copied rules will fail.
[186] * This letter might
change from a Q
to a different letter in the future.
[187] * Prior to V8.7, this was determined by defining QUEUESIZE in conf.h.
[188] * Note that prior
to V8 sendmail, the r option set one timeout
for all SMTP timeouts.
[189] * IDA and pre-V8
SunOS sendmail offer three
command-line switches for processing the queue.
The -M switch
allows you to specify a specific message for
processing. The -R switch allows you to specify
specific recipient addresses for processing. The
-S switch
allows you to specify specific sender addresses
for processing.
[190] * We fudge on
this command. It actually moves all mail from the
current queue to the new queue directory. You
might have to supply other arguments to
qtool.pl to select specific
qf files to
move. See the manual page, called
contrib/qtool.8, for more
information.
[191] * We say qf file, even though
this new line appears only in the new hf file type.
[192] * Or another
separation character specified by the -t command-line switch
with makemap.
[193] * Except the
check_compat
rule set.
[194] * The
nvi(1) editor uses the same
file locking as sendmail and
so can safely be used to edit qf files.