Every local message is delivered to the local part of its target address, the part of the address to the left of the at-sign. The local part may come directly from an incoming message, or it may be generated internally by qmail, particularly for mail to virtual domains (see Chapter 12), which construct the local part from a combination of the incoming address and information about the virtual domain. If the local part of an address contains one or more hyphens, the part before the first hyphen is consider the user and the rest is the extension. If the local part doesn't contain a dash (hyphen), the local part is the user and there's no extension. 10.1.1 Identifying the UserThe first step in a local delivery is to identify the user corresponding to the local part and retrieve several items about the user. The items are:
Qmail uses two techniques to retrieve the user information. First it checks the users database, which the qmail manager can and usually should create. (I discuss it in more detail Chapter 15.) If there is no users database or an address doesn't appear in the database, it runs qmail-getpw to get the information from the Unix password file. If both of those fail, it prepends alias- to the address and tries again, so that unknown addresses are treated as subaddresses of the alias user. 10.1.2 Locating the .qmail FileAll local deliveries are controlled through a .qmail file. Once qmail has the user information corresponding to a local part, selecting the qmail file is straightforward. All .qmail files are located in the user's home directory.[1] If the local part has no extension, the .qmail file is called .qmail. If Fred's home directory is /home/fred, mail for the address fred is handled by /home/fred/.qmail. If there's an extension, it's .qmail-extension; for example, mail to fred-fishing would be handled by /home/fred/.qmail-fishing. If the .qmail file for an address with an extension doesn't exist, qmail also looks for a .qmail file, replacing the extension with -default, as in /home/fred/.qmail-default. If there are multiple levels of extension, qmail searches for defaults one level at a time, and mail for fred-fishing-lures is now handled by /home/fred/.qmail-fishing-lures, or /home/fred/.qmail-fishing-default, or /home/fred/.qmail-default. Notice that a single extension is not defaulted to the plain .qmail file, so the final default for any address with an extension is .qmail-default, not .qmail. To prevent funny business, any dots in the address are replaced by colons in the filename, so the .qmail file for fred-fishing.stories is /home/fred/.qmail-fishing:stories.
If a .qmail file is empty, qmail uses the default delivery instructions passed to qmail-start at startup time. If there is no plain .qmail file, qmail also uses the default delivery instructions. On the other hand, if .qmail-default doesn't exist, mail to addresses with an extension bounces. The alias user is handled the same as any other user. This means that mail to unmatched addresses is handled by ~alias/.qmail-address if it exists, otherwise ~alias/.qmail-default. That means you can handle arbitrary addresses by creating .qmail files in ~alias. You can also handle arbitrary addresses by running fastforward from ~alias/.qmail-default, to look up addresses in a sendmail-style /etc/aliases database. I cover that later in this chapter. 10.1.3 Processing the .qmail FileOnce qmail has selected a .qmail file, it reads and processes the file one line at a time. The first character on the line determines the type of line:
A .qmail file can have any combination of these kinds of lines. The lines are interpreted one at a time. Command and mailbox lines are interpreted in sequence. (Maildir and mbox deliveries are handled by internal routines in qmail-local that return exit codes like commands do to indicate whether the delivery was successful.) If a command exits with a failure code (anything other than 0 or 99), the delivery failed and qmail-local stops immediately. If a command exits with code 99, the command is considered to have succeeded, but the rest of the .qmail file is ignored. If a command exits with code 100, the failure is permanent and the message bounces. If with code 111, the failure is temporary and qmail will retry the delivery (the entire .qmail file, not just the command that failed) later. For historical reasons, exit codes 64, 65, 70, 76, 77, 78, and 112 are also considered permanent failures, any other nonzero exit code is temporary failure, but for compatibility with future versions of qmail, programs should only return 0 for success, 99 for success and skip the rest of the file, 100 for permanent failure, or 111 for temporary failure. If you want qmail to continue interpreting a .qmail file if a command fails, the qmail documentation suggests putting each command in a separate .qmail-whatever file and having the main .qmail file forward the mail to the subaddresses corresponding to each of those files. A much easier approach is to just force the exit code of each command line to zero: | somecommand ; exit 0 The cabalistically inclined can abbreviate to: | somecommand ;: Forward lines are noted but not acted on until all of the lines in the .qmail have been interpreted. At the end of the file, if there were any forward lines and no command or mailbox line has failed, qmail-local calls qmail-queue to requeue the message to the forwarding addresses. If a command or mailbox delivery fails, qmail-local does no forwards, even if the forward lines preceded the failing delivery line in the .qmail file. 10.1.4 Defensive Features in qmail-localMail deliveries can be fouled up in a remarkable number of ways. qmail-local has several features intended to prevent mail foul-ups, or to limit the damage when a foul-up occurs:
|