An MTA (mail transfer agent) transports email messages from one user
to another. Users typically don't invoke an MTA directly; instead, they
use an MUA (mail user agent) like Pine, mutt, or Outlook Express. But,
to get complete control of the message header, body, and envelope, you
can invoke the MTA directly, as an MUA might do. In this page, we'll show
examples of using an MTA directly.
Not all hosts have local MTAs. Also, some MUAs make a network
connection and talk SMTP to their MTA. So, if you can't get this
example to work, try running it on a "bigger" host, especially your
mail server. MTA command lines vary; we'll show
sendmail's.
NOTE: Be careful. You're
experimenting with an important system resource! Mistakes can cause
bounced mail, mail loops, or other problems. If you're unsure, we
suggest checking with an experienced mail user or administrator first.
To use an MTA directly, you'll need a file (or standard input) with
a legal message header and body; see
the article
for details. Note: a
lot can go wrong here: stray CTRL-M characters from Windows machines is
just one problem. You may need to experiment. It's safest to start with
a well-formatted short email message copied from your mail spool file or
one of your MUA's folders, then edited with a plain text editor like
Emacs or vi that doesn't try to make the file "pretty". Here's an
example. We've shown the commands you type in boldface type; they're
explained below:
1$ ls -l /var/spool/mail/jpeek
-rw-rw---- 1 jpeek mail 7540 Jun 23 07:14 /var/spool/mail/jpeek
2$ cp -i /var/spool/mail/jpeek message
3$ vi message
4$ cat -t -v -e message
From: "Joe D. Oakes" <joe@foo.xyz>$
To: Some test user <myfriend@foo.xyz>$
cc: Other test user <someone@foo.xyz>, Jerry Peek <jpeek@foo.xyz>$
Subject: test message$
$
This is a test message.$
Etc. etc. etc.$
5$ /usr/sbin/sendmail -v -f me@remote.xyz me@local.xyz < message
me@local.xyz... Connecting to mail.local.xyz...
220 mail.local.xyz ESMTP Sendmail 8.12.3/8.12.3
>>> EHLO myhost.local.xyz
250-mail.local.xyz Hello myhost.local.xyz [192.168.2.109], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-EXPN
250-VERB
250-8BITMIME
250-SIZE 16000000
250-DSN
250-ETRN
250-DELIVERBY
250 HELP
>>> MAIL From:<me@remote.xyz> SIZE=166
250 2.1.0 <me@remote.xyz>... Sender ok
>>> RCPT To:<me@local.xyz>
250 2.1.5 <me@local.xyz>... Recipient ok
>>> DATA
354 Enter mail, end with "." on a line by itself
>>> .
250 2.0.0 h241RoDe084181 Message accepted for delivery
me@local.xyz... Sent (2.0.0 h241RoDe084181 Message accepted for delivery)
Closing connection to mail.local.xyz.
>>> QUIT
221 2.0.0 mail.local.xyz closing connection
Command 1 checks whether you
have email in your mail spool file. If you get a "file not found" error,
check the pathname. Or, if the spool file is empty, send yourself a
short message. Then use command 2
to copy the spool file to a file in your current directory. (If your
mail spool file is on another host, copy it to your current host with a
command like scp.)
Now edit the message file
(as in command 3) to leave a
single message:
-
Remember to delete the "From " separator line (which
isn't part of a legal header) and/or any Content-Length: header field.
-
Note that, unless you're trying to relay
an existing complete message to another address (as we'll do, later,
from procmail), delete any Message-ID: and Date: fields from the header.
(If the MTA doesn't add those two fields as it sends the message,
though, you'll need to create your own.) We're deleting those fields
because each unique email message in the world should have its own
unique Message-ID: -- and,
typically, always have the Date:
that it originally was sent.
Command 4
shows the complete message; the options make cat show TAB
characters as ^I, mark non-7-bit "printable"
characters (which shouldn't be in a plain-text email message)
specially, and mark the end of each line with $. Be sure that the empty line
between the header and body is completely empty: it should have
$ as the only character (at the left margin).
If you have two separate email accounts (that is, two accounts that
don't auto-forward messages to each other -- for instance, a home
address and a business address), use both of them on the MTA's command
line -- but don't put either of them in the message
header. Use some other addresses in the header, such as friend's
addresses. (We want to show that the message is still delivered to you
-- via the address in the envelope, not any address in the header.) You
might ask or warn your friends -- the ones listed in the message header
-- in case they accidentally do
get your test message!
When you send the message (as in command
5), use your remote address as the envelope sender and your
local address (the one where you can read the mail spool file) as the
envelope recipient. That way, if all goes well, you'll see the message
in your local mailbox -- and, if it doesn't go well, any bounced
message should go to your remote mailbox.
The sendmail -v flag requests verbose output,
so (we hope) you can see the SMTP transaction. Notice the envelope
sender and recipient addresses in the transaction.
After you send the message:
-
Use ls -l (or
ssh somehost ls -l) to confirm that your message arrived.
-
Read your spool
file (with a command like less
/var/spool/mail/myname)
and find the message you just sent.
It's probably at the end of the file.
-
Compare the original msg
file to the message you received. Note whether the MTA added
Date: and Message-ID: fields, look at the
Received: field(s), and so on.
The MTA may also have added an X-Authentication-Warning:
field; this tells the recipient that you used sendmail -f to alter the
envelope sender address.
If this all worked well, you should be ready to invoke an MTA directly
-- which you may want to do, for instance, from a
.procmailrc file or a script.
[To return to the place where you left the article, use your
browser's "back" button. You can also go to
the start
of the article.]