| < Free Open Study > |
|
Mail users don't usually use the Mail Transfer Agent (MTA) directly to send messages. Typically, messages are composed and sent using an MUA such as Pine or Mutt, which then calls the MTA to deliver the message. The process of handing a new message to the MTA is called injection.
There are two ways to inject messages into most MTAs: via the Simple Mail Transfer Protocol (SMTP) or by using a program provided by the MTA for that purpose.
MUAs can open a TCP connection to port 25, the standard SMTP port, on the local host or a designated mail server. The MUA and the MTA then engage in a dialogue that results in either
The message being transferred to the MTA
An error status being returned to the MUA
Alternatively, MUAs can invoke the SMTP daemon directly by running qmail-smtpd, but this is not a common practice.
Plain SMTP has no authentication mechanism, so no username or password is required to send a message. However, many MTAs refuse to accept messages that don't appear to be either from or for a local user. If a properly formatted message is rejected, such restrictions are the most likely cause. See Chapter 3, "Configuring qmail: The Basics," for more information about relay configuration.
Normally, SMTP injection is performed by an MUA, so it's transparent to the user. Occasionally it's convenient to manually inject a message via SMTP, usually for troubleshooting mail delivery problems. Of course, it can also be used to forge messages from third parties because SMTP is unauthenticated.
See Appendix C, "An Internet Mail Primer," for information about SMTP.
The example.net mail administrator is investigating problems delivering mail to the example.com system. She uses telnet to open a connection to the SMTP daemon on example.com and inject a test message to the postmaster:
$ telnet example.com 25 Trying 192.168.1.5. . . Connected to example.com. Escape character Is '^]'. 220 example.com ESMTP helo example.net 250 example.com mail from:<postmaster@example.net> 250 ok rcpt to:<postmaster@example.com> 250 ok data 354 go ahead From: postmaster@example.net To: postmaster@example.com Subject: testing Please ignore . 250 ok 989155531 qp 15669 quit 221 example.com Connection closed by foreign host. $
For many years, Sendmail was the Unix MTA. It was so ubiquitous that many programmers assumed it was available on all systems. As a result, Sendmail's local injection mechanism became the de facto standard programmer's interface for local mail injection. qmail and most other non-Sendmail MTAs provide a sendmail program that works the same way as the original Sendmail's sendmail command for local injection. qmail's sendmail program is a fairly simple wrapper around qmail-inject.
The qmail sendmail, which is normally in /var/qmail/bin/sendmail, usually replaces the Sendmail sendmail on qmail systems. Typical locations of the sendmail program include:
/usr/lib/sendmail
/usr/sbin/sendmail
On a qmail system, ls -l path-to-sendmail should show that sendmail is a symbolic link to /var/qmail/bin/sendmail:
$ ls -l /usr/lib/sendmail lrwxrwxrwx 1 root root 29 Feb 19 11:04 /usr/lib/sendmail -> /var/qmail/bin/sendmail $
The sendmail command supports the following options and arguments:
sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ recipient ... ]
The message to be sent is read from standard input.
For Sendmail compatibility, sendmail silently ignores the B, p, v, i, x, m, e, o, E, J, and bm options.
-t extracts recipients from the message. The To, Cc, and Bcc header fields will be scanned for recipients. (The Bcc field will be removed before sending the message).
Caution | The qmail and Sendmail implementations of this option differ.With Sendmail, only the recipients specified in the message will receive copies—any recipients specified on the command line are ignored.With qmail, both recipients specified on the command line and recipients specified in the message will receive copies. |
-fsender sets the envelope sender to sender—doesn't affect the From header field.
-Fname sets the MAILNAME environment variable to name.
Note | See the "qmail-inject Injection" section on environment variables. If the message contains a From field, qmail-inject won't override it unless QMAILINJECT contains the f flag. Also, MAILNAME will be overridden by QMAILNAME,if it's set. |
-bp runs qmail-qread to display the contents of the queue.
Note | qmail-qread requires superuser privileges. |
-bs uses the SMTP protocol. Input must be a valid sequence of SMTP commands, not a message.
A user creates a simple message in a file called msg using a text editor (see Listing 4-1).
Listing 4-1: The msg file
From: me@example.com To: you@example.net Subject: test Test message sent using qmail's sendmail command.
To send the message to you@example.net, the user enters the following command:
$ /var/qmail/bin/sendmail -t <msg $
Tip | Add /var/qmail/bin to your PATH to avoid having to enter the full path to sendmail. Check the man page for your shell for complete details, but either PATH=$PATH:/var/qmail/bin; export PATH or set path=($path/var/qmail/bin) should work for the current shell session, depending on which shell you're using. Use type sendmail or which sendmail to verify that the shell is using the qmail sendmail. |
To send the message to you@example.net and me@example.com, the user simply adds the additional recipient to the command line:
$ sendmail -t me@example.com <msg $
To send the message to you@example.net with an envelope sender address of info@example.com, the user adds an –f option:
$ sendmail -t -f "info@example.com" <msg $
Note | In all three of these examples, the messages received look exactly like the message contained in msg: The From and To header fields are not altered, even though the envelope sender and recipient might differ from them. The envelope sender and recipient might be added to the message by the receiving MTA. For example, qmail puts the envelope sender in a Return-Path field and the envelope recipient in a Delivered-To field. |
To view the contents of the queue as root:
# sendmail -bp 6 May 2001 12:32:11 GMT #93881 97390 <dave@sparge.example.com> remote dave@mash.example.net #
This shows that there is currently one message in the queue, delivery number 93881, which is a message of 97,390 bytes from dave@sparge.example.com to dave@mash.example.com.
In addition to emulating the sendmail interface, qmail has its own injection program: qmail-inject. In fact, sendmail is just a wrapper around qmail-inject— a program that emulates Sendmail's injection process, converting its inputs from the Sendmail style to the format qmail-inject requires.
As a programmer's interface, sendmail is probably better because it's much more widely available. The qmail programmer's interface provided by qmail-inject will only work on systems with qmail, but the sendmail interface is nearly universal.
For example, to send a blank message to eunice@example.com:
$ echo To: eunice@example.com | /var/qmail/bin/qmail-inject $
This takes a message consisting solely of a To header field and passes it to qmail-inject, which adds additional header fields and places the message in qmail's delivery queue.
Because users usually run qmail-inject indirectly though their MUAs, and those MUAs might even think they're calling Sendmail, qmail-inject's behavior is controllable through the use of environment variables. Environment variables are name/value pairs stored in the environment of a process and inherited by child processes. Most environment variables are set in one of the user's shell configuration files (for example, .profile or .cshrc), so they're inherited by all of the user's processes.
Most of these variables are used to override default values supplied by qmail-inject or the MUA. You don't need to set any of these variables unless you're not satisfied with the results that can be achieved by configuring your MUA.
One common application of these settings is user or host masquerading: hiding real usernames or host names behind aliases either for security or for aesthetics.
The From field identifies the sender of a message. It consists of a local part (a username or alias), a domain (host name), and an optional comment (usually the sender's name) in this format:
From: Optional-Comment <localpart@domain>
For example:
From: "Dave Sill" <dave@sparge.example.com> From: dave@sparge.example.com From: dave.sill@example.com From: "D E Sill" <dave@example.com>
qmail-inject uses a series of variables to set each of the three parts of the From field, ranging from qmail-specific variables to common Unix variables also used by other programs.
Note | The QMAILINJECT environment variable must contain the f option if you want the From field constructed from qmail-inject environment variables to override a From field inserted in the message by the MUA. |
qmail-inject looks for the following environment variables, in order:
QMAILUSER
MAILUSER
USER
LOGNAME
If it finds one of them, its value overrides the local part of the address in the From header of the message.
For example, if the environment contains this:
USER=dave QMAILUSER=david.sill
The From header will contain david.sill.
qmail-inject looks for the following environment variables, in order:
QMAILHOST
MAILHOST
If it finds one of them, its value overrides the domain of the address in the From header of the message.
For example, if the environment contains this:
MAILHOST=duvel.example.net QMAILHOST=example.net
The From header will contain example.net.
qmail-inject looks for the following environment variables, in order:
QMAILNAME
MAILNAME
NAME
If it finds one of them, its value overrides the personal name in the From header of the message.
For example, if the environment contains this:
NAME=Dave Sill MAILNAME=David Sill
The From header field will contain "David Sill" in addition to my e-mail address.
Environment variables can also be used to override the default value of the nvelope sender address. The envelope sender is usually taken from the From header field.
The QMAILSUSER (qmail sender user) environment variable specifies the username in the envelope sender address. For example, if the environment contains this:
QMAILSUSER=dave.sill
and the local domain (from the defaultdomain control file) is example.net, the envelope sender address will be dave.sill@example.net.
The QMAILSHOST (qmail sender host) environment variable specifies the host (domain) name in the envelope sender address. For example, if the environment contains this:
QMAILSHOST=example.net
and the user (from the From header field) is dave, the envelope sender address will be dave@example.net.
The user can override all of qmail-inject's control files through the use of environment variables (see Table 4-1). See Chapter 3, "Configuring qmail: The Basics," for explanations of the functions of these control files.
ENVIRONMENT VARIABLE | CONTROL FILE |
---|---|
QMAILDEFAULTDOMAIN | defaultdomain |
QMAILDEFAULTHOST | defaulthost |
QMAILIDHOST | idhost |
QMAILPLUSDOMAIN | plusdomain |
Note | The QMAILINJECT environment variable must contain the i option if you want the Message-ID field constructed from QMAILIDHOST to override a Message-ID field generated by the MUA. |
The QMAILINJECT environment variable can be set to a string of one or more letters that enable optional behavior by qmail-inject.
When set, qmail-inject uses "address-comment" style From fields instead of the default "name-address" format. For example, the name-address formatted From field:
From: "Dave Sill" <dave@hallertauer.example.com>
would be written in address-comment style as
From: dave@hallertauer.example.com (Dave Sill)
Note | This format is outdated and the "name-address" format should be used. |
When set, qmail-inject replaces the From field in a message with one of its own creation. Without the f option, a From field in the message overrides the From field created by qmail-inject.
For example, if the environment contains this:
QMAILINJECT=f QMAILHOST=example.net QMAILUSER=donna
The resulting message will contain the From field:
From: donna@example.net
When set, qmail-inject replaces the Message-ID field in a message with one of its own creation. Without the i option, a Message-ID field in the message over-rides the Message-ID field created by qmail-inject.
For example, if the environment contains this:
QMAILINJECT=i QMAILIDHOST=davesill.example.net
The resulting message will contain a Message-ID field like this:
Message-ID: <20011030124709.A17455@davesill.example.net>
When set, qmail-inject uses a per-message Variable Envelope Return Path (VERP). qmail-inject will append a date stamp and its process ID (PID) to the envelope sender. This will allow the sender to reliably detect bounce messages resulting from the message.
For example, if the environment contains this:
QMAILINJECT=m
The message will contain an envelope sender address like this:
dave-987343616.11608@example.net
When set, qmail-inject uses a per-recipient VERP. qmail-inject appends each recipient's address to the envelope sender of the copy of the message sent to that recipient, substituting the equal sign (=) for the at sign (@) in the recipient's address. This allows the sender to reliably determine which address is having delivery problems by examining the address to which the bounce message is sent. This is useful because some bounce messages don't clearly identify the offending address.
For example, if the environment contains this:
QMAILINJECT=r
and a message is sent to eunice@scraps.example.com, the message will contain an envelope sender address like this:
dave-eunice=scraps.example.com@example.net
When set, qmail-inject ignores Return-Path header fields. Without this option, qmail-inject will use a Return-Path header to set the envelope sender address, overriding any of the environment variables normally used to set the envelope sender. Whether option s is set or not, qmail-inject will remove the Return-Path field.
Most MUAs have two kinds of reply functions: a reply to sender and a reply to all. The reply to sender directs the reply to the person who wrote the original message. The reply to all function sends the reply to the originator and all recipients listed in the Cc header field.
This works well for messages addressed to individuals but has problems with messages sent to mailing lists. In that case, a reply to all will usually send the originator two copies: one directly and one through the mailing list.
To avoid this problem, qmail creator Dan Bernstein devised a new header field: Mail-Followup-To. When set, this field provides the address to which a reply to all replies should be sent.
To automate the creation of Mail-Followup-To fields, qmail-inject looks for the environment variable QMAILMFTFILE, which should be set to the name of a file containing a list of the mailing lists to which the user is subscribed. When qmail-inject sees a message containing a mailing list in the To or Cc fields, it creates a Mail-Followup-To field containing all of the addresses in the To and Cc fields.
For example, if a user's environment contains this:
QMAILMFTFILE=$HOME/.mailinglists
and their $HOME/.mailinglists file contains this:
qmail@list.cr.yp.to
And the user sends this message:
From: newbie@isp.example.net To: qmail@list.cr.yp.to Subject: qmail slow to connect Why does qmail take so long to respond to incoming SMTP connections?
Then qmail-inject will add this header field:
Mail-Followup-To: qmail@list.cr.yp.to
Users with MUAs that understand the Mail-Followup-To header field will then direct reply to all replies to qmail@list.cr.yp.to. At the time of this writing, the current versions of Mutt, nmh, and Gnus support Mail-Followup-To.
All messages that enter qmail's queue come in via qmail-queue, whether they were injected using SMTP, qmail-inject, or sendmail. qmail-queue is qmail's injection primitive. It's not intended to be run directly by users: The interface is user-unfriendly and it does nothing to the message to verify that it's valid according to RFC 2822.
Nevertheless, savvy users can use it to efficiently inject messages.
qmail-queue reads a message from descriptor 0 (zero) and a specially formatted envelope from descriptor 1 (one). If the message is successfully queued, qmail-queue exits with a status of 0. If the message is not successfully queued, it exits with a status between 1 and 99. Exit status codes between 11 and 40 indicate permanent failures, and everything else indicates temporary failure. Table 4-2 shows all of the status codes used by qmail-queue.
CODE | MEANING |
---|---|
0 | Success |
11 | Address too long |
51 | Out of memory |
52 | Timeout |
53 | Write error; for example, disk full |
54 | Unable to read the message or envelope |
61 | Problem with the qmail home directory |
62 | Problem with the queue directory |
63 | Problem with queue/pid |
64 | Problem with queue/mess |
65 | Problem with queue/intd |
66 | Problem with queue/todo |
81 | Internal bug; for example, segmentation fault |
91 | Envelope format error |
The envelope format is this:
Fsender^@Trecip^@Trecip. . .^@^@
where ^@ represents a zero byte (ASCII NUL), sender is the address of the sender, including an @ followed by a fully qualified domain name, and recip is the address of a recipient, also including an @ and a fully qualified domain name. The list of recipients is terminated by two consecutive zero bytes.
Using a text editor, a user creates a file called msg containing the message (header and body) he wants to send (see Listing 4-2).
Listing 4-2: The msg file
From: "Joe" <big.cheese@isp.example.com> To: Mr White, Mr Orange Subject: Breakfast at Uncle Bob's Let's meet tomorrow at 9:00 to discuss the job. -Joe
Note | The To header field in the msg file violates RFC 2822. Do that at your own risk. |
Also using a text editor, the user creates a file called env containing the envelope information (see Listing 4-3).
Listing 4-3: The env file
Fbig.cheese@isp.example.com^@Tlarry@example.net^@Tfreddy@isp.example.com^@^@
The user uses qmail-queue to send the message:
$ /var/qmail/bin/qmail-queue < msg 1< env $ echo $? 0 $
The first command calls qmail-inject with msg on descriptor 0 and env on descriptor 1. The second command displays the exit status code from the previous command, which indicates that the message was successfully queued.
| < Free Open Study > |
|