379 lines
15 KiB
TeX
379 lines
15 KiB
TeX
\chapter{Using SMTP}\label{cha:smtp}
|
|
%
|
|
\begin{description}
|
|
\item[Used files:] smtp.scm
|
|
\item[Name of the package:] smtp
|
|
\end{description}
|
|
%
|
|
|
|
\section{Philosophy}
|
|
SMTP protocol procedures tend to return two values:
|
|
\begin{description}
|
|
\item[\semvar{code}] The integer SMTP reply code returned by server for the transaction.
|
|
\item[\semvar{text}] A list of strings -- the text messages tagged by
|
|
the code.
|
|
\end{description}
|
|
|
|
The text strings have the initial code numerals and the terminating
|
|
\ex{CR}/\ex{LF}'s stripped. Codes in the range $[1,399]$ are sucess
|
|
codes; codes in the range $[400,599]$ are error codes; codes $>= 600$
|
|
are not part of the official SMTP spec. This module uses codes $>=
|
|
600$ to indicate extra-protocol errors. There are two of these:
|
|
|
|
\begin{description}
|
|
\item[600 Server reply could not be parsed.]
|
|
The server sent back some sort of incomprehensible garbage reply.
|
|
\item[621 Premature EOF while reading server reply.]
|
|
The server shut down in the middle of a reply.
|
|
\end{description}
|
|
|
|
A list of the official protocol return codes can be seen in table
|
|
\ref{smtp-reply-codes}.
|
|
|
|
\section{Procedures}
|
|
|
|
\begin{defundesc}{sendmail}{to-list body \ovar{host}}{code text-list}
|
|
Mail message \semvar{body} to recipients in list \semvar{to-list}.
|
|
Message handed off to server running on \semvar{host}; default is
|
|
the local host. Returns two values: \semvar{code} and
|
|
\semvar{text-list}, i.e. the code returned by the server and the
|
|
text-message, seperated by lines. However, if some recipients were
|
|
rejected, sendmail sends to the rest of the recipients, and the
|
|
partial-success return is [700 \semvar{loser-alist}] where
|
|
\semvar{loser-alist} is a list whose elements are of the form
|
|
\ex{(\semvar{loser-recipient} \semvar{code} . \semvar{text})} --
|
|
that is, for each recipient refused by the server, you get the error
|
|
data sent back for that guy. The success check is \ex{(< code 400)}.
|
|
\end{defundesc}
|
|
|
|
\begin{defundesc}{\%sendmail}{from local-host to dest-host
|
|
message}{code text} Mail \semvar{message} to recipient \semvar{to}
|
|
using \semvar{dest-host}, telling \semvar{from} as your mail-address
|
|
and \semvar{local-host} as your system-name.
|
|
\end{defundesc}
|
|
|
|
|
|
\defun{expn}{name host}{code text}
|
|
\defunx{vrfy}{name host}{code text}
|
|
\defunx{mail-help}{host \ovar{details}}{code text-list}
|
|
\begin{desc}
|
|
These three are simple queries of the server as stated in the
|
|
RFC~821: \ex{expn} asks the server to confirm that the argument
|
|
identifies a mailing list, and if so, to return the membership of
|
|
that list. The full name of the users (if known) and the fully
|
|
specified mailboxes are returned in a multiline reply. \ex{vrfy}
|
|
asks the receiver to confirm that the argument identifies a user.
|
|
If it is a user name, the full name of the user (if known) and the
|
|
fully specified mailbox are returned. \ex{mail-help} causes the
|
|
server to send helpful information. The command may take an argument
|
|
(\semvar{details}) (e.g., any command name) and return more specific
|
|
information as a response.
|
|
\end{desc}
|
|
|
|
|
|
\dfn{smtp-transactions}{socket ?transaction1 ...}{code
|
|
text-list}{syntax}
|
|
\dfnx{smtp-transactions/no-close}{socket ?transaction1 ...}{code
|
|
text-list}{syntax}
|
|
\begin{desc}
|
|
These macros make it easy to do simple sequences of SMTP commands.
|
|
|
|
Evaluate a series of expressions \semvar{?transaction1},
|
|
\semvar{?transaction2}, \ldots
|
|
\begin{itemize}
|
|
\item Each expression should perform an SMTP transaction, and return
|
|
two values: \semvar{code} (the integer reply code) and \semvar{text}
|
|
(list of strings that came with the reply).
|
|
\item If the transaction's reply code is 221 or 421 (meaning the
|
|
socket has been closed), then the transaction sequence is is
|
|
aborted, and the \ex{smtp\=trans\ob{}actions} form returns the
|
|
\semvar{code} and \semvar{text} values for the current transaction.
|
|
\item If the reply code is an error code (in the four- or five-hundred
|
|
range), the transaction sequence is aborted, and the fatal
|
|
transaction's \semvar{code} and \semvar{text} values are returned.
|
|
\ex{smtp\=trans\ob{}actions} will additionally close the socket for
|
|
you; \ex{smtp-trans\ob{}actions/\ob{}no\=close} will not.
|
|
\item If the transaction is the last in the transaction sequence, its
|
|
\semvar{code} and \semvar{text} values are returned.
|
|
\item Otherwise, we throw away the current \semvar{code} and
|
|
\semvar{text} values, and proceed to the next transaction.
|
|
\end{itemize}
|
|
|
|
Since \ex{smtp-trans\ob{}actions} closes the socket whenever it
|
|
aborts a sequence, an \ex{smtp-trans\ob{}actions} form terminated
|
|
with an \ex{(smtp/\ob{}quit socket)} transaction will always close
|
|
the socket.
|
|
|
|
If the socket should be kept open in the case of an abort, use
|
|
\ex{smtp-trans\ob{}actions/\ob{}no\=close}.
|
|
|
|
We abort sequences if a transaction results in a 400-class error code.
|
|
So, a sequence mailing a message to five people, with 5 RCPT's, would
|
|
abort if the mailing address for one of these people was wrong, rather
|
|
than proceeding to mail the other four. This may not be what you want;
|
|
if so, you'll have to roll your own.
|
|
\end{desc}
|
|
|
|
\defun{smtp/open}{host \ovar{maybe-port}}{socket}
|
|
\defunx{smtp/helo}{local-host-name}{code text-list}
|
|
\defunx{smtp/mail}{sender-address}{code text-list}
|
|
\defunx{smtp/rcpt}{destination-address}{code text-list}
|
|
\defunx{smtp/data}{socket message}{code text-list}
|
|
\defunx{smtp/send}{sender-address}{code text-list}
|
|
\defunx{smtp/soml}{sender-address}{code text-list}
|
|
\defunx{smtp/saml}{sender-address}{code text-list}
|
|
\defunx{smtp/rset}{}{code text-list}
|
|
\defunx{smtp/vrfy}{user}{code text-list}
|
|
\defunx{smtp/expn}{user}{code text-list}
|
|
\defunx{smtp/help}{details}{code text-list}
|
|
\defunx{smtp/noop}{}{code text-list}
|
|
\defunx{smtp/quit}{socket}{code text-list}
|
|
\defunx{smtp/turn}{}{code text-list}
|
|
\begin{desc}
|
|
These functions implement the basics of the protocol, i.e. they send
|
|
the corresponding command along with the argument(s), if any. A
|
|
short look to the code of \ex{\%sendmail} will give you the basics
|
|
on how to use the commands. You will obtain further informations in
|
|
the RFC~821. \semvar{host}, \semvar{local-host},
|
|
\semvar{sender-address}, \semvar{destination-address}, \semvar{user}
|
|
and \semvar{details} are strings, \semvar{message} may be a string
|
|
or an input-port. \semvar{socket} is a socket, mostly one returned
|
|
by \ex{smtp/\ob{}open}.
|
|
\end{desc}
|
|
|
|
\begin{defundesc}{handle-smtp-reply}{socket}{code text-list}
|
|
Read and handle the reply. Return an integer (the reply
|
|
\semvar{code}), and a list of the text lines (\semvar{text-list})
|
|
that came tagged by the reply code. The text lines have the
|
|
reply-code prefix (first 4 chars) and the terminating cr/lf's
|
|
stripped.
|
|
\end{defundesc}
|
|
|
|
\begin{defundesc}{read-smtp-reply}{port}{code text-list}
|
|
Read a reply from the SMTP server. Returns two values:
|
|
\begin{description}
|
|
\item[\semvar{code}] Integer. The reply code.
|
|
\item[\semvar{text}] String list. A list of the text lines comprising
|
|
the reply. Each line of text is stripped of the initial
|
|
reply-code numerals (e.g., the first four chars of the reply),
|
|
and the trailing cr/lf. We are in fact generous about what we
|
|
take to be a line -- the protocol requires cr/lf terminators, but
|
|
we'll accept just lf. This appears to true to the spirit of the
|
|
"be strict in what you send, and generous in what you accept"
|
|
Internet protocol philosphy.
|
|
\end{description}
|
|
\end{defundesc}
|
|
|
|
\begin{defundesc}{parse-smtp-reply}{line}{code rest more?}
|
|
Parse a line of SMTP reply. Return three values:
|
|
\begin{description}
|
|
\item[\semvar{code}] integer -- the reply code that prefixes the
|
|
string.
|
|
\item[\semvar{rest}] string -- the rest of the line.
|
|
\item[\semvar{more?}] boolean -- is there more reply to read (i.e.,
|
|
was the numeric reply code terminated by a ``\ex{-}'' character?)
|
|
\end{description}
|
|
\end{defundesc}
|
|
|
|
\begin{defundesc}{smtp-stuff}{text pchar}{stuffed-string last-char}
|
|
The message body of a piece of email is terminated by the sequence
|
|
\ex{<CRLF> <period> <CRLF>}, i.e. end-of-line, period,
|
|
end-of-line. If the message body contains this magic sequence, it
|
|
has to be escaped. We do this by mapping the sequence \ex{<LF>
|
|
<period>} to \ex{<lf> <period> <period>}; the SMTP receiver undoes
|
|
this mapping.
|
|
|
|
\semvar{text} is a string to stuff, \semvar{pchar} was the character
|
|
read just before \semvar{text} (which matters if it is a line-feed).
|
|
If \semvar{text} is the first chunk of the entire msg, then
|
|
\semvar{pchar} can be \sharpf. Return two values: the
|
|
\semvar{stuffed-string}, and the last char in \semvar{text} (or
|
|
\semvar{pchar} if \semvar{text} is empty). The last-char value
|
|
returned can be used as the \semvar{pchar} arg for the following
|
|
call to \ex{smtp\=stuff}.
|
|
\end{defundesc}
|
|
|
|
\section{Additional information about SMTP}
|
|
|
|
\section{Reply codes}
|
|
|
|
This material is taken from the RFC. The first digits encode categories
|
|
of responses:
|
|
\begin{description}
|
|
\item[1yz Positive Preliminary reply\,] The command has been
|
|
accepted, but the requested action is being held in abeyance,
|
|
pending confirmation of the information in this reply. The
|
|
sender-SMTP should send another command specifying whether to
|
|
continue or abort the action.
|
|
\begin{leftinset}
|
|
Note: SMTP does not have any commands that allow this type of reply,
|
|
and so does not have the continue or abort commands.
|
|
\end{leftinset}
|
|
\item[2yz Positive Completion reply\,] The requested action has
|
|
been successfully completed. A new request may be initiated.
|
|
\item[3yz Positive Intermediate reply\,] The command has been
|
|
accepted, but the requested action is being held in abeyance,
|
|
pending receipt of further information. The sender-SMTP should send
|
|
another command specifying this information. This reply is used in
|
|
command sequence groups.
|
|
\item[4yz Transient Negative Completion reply\,] The command was
|
|
not accepted and the requested action did not occur. However, the
|
|
error condition is temporary and the action may be requested again.
|
|
The sender should return to the beginning of the command sequence
|
|
(if any). It is difficult to assign a meaning to ``transient'' when
|
|
two different sites (receiver- and sender- SMTPs) must agree on the
|
|
interpretation. Each reply in this category might have a different
|
|
time value, but the sender-SMTP is encouraged to try again. A rule
|
|
of thumb to determine if a reply fits into the 4yz or the 5yz
|
|
category (see below) is that replies are 4yz if they can be repeated
|
|
without any change in command form or in properties of the sender or
|
|
receiver. (E.g., the command is repeated identically and the
|
|
receiver does not put up a new implementation.)
|
|
\item[5yz Permanent Negative Completion reply\,] The command was
|
|
not accepted and the requested action did not occur. The
|
|
sender-SMTP is discouraged from repeating the exact request (in the
|
|
same sequence). Even some ``permanent'' error conditions can be
|
|
corrected, so the human user may want to direct the sender-SMTP to
|
|
reinitiate the command sequence by direct action at some point in
|
|
the future (e.g., after the spelling has been changed, or the user
|
|
has altered the account status).
|
|
\end{description}
|
|
|
|
The second digit encodes responses in specific categories:
|
|
\begin{description}
|
|
\item[x0z Syntax\,] These replies refer to syntax errors,
|
|
syntactically correct commands that don't fit any functional
|
|
category, and unimplemented or superfluous commands.
|
|
\item[x1z Information\,] These are replies to requests for
|
|
information, such as status or help.
|
|
\item[x2z Connections\,] These are replies referring to the
|
|
transmission channel.
|
|
\item[x3z\,] Unspecified as yet.
|
|
\item[x4z\,] Unspecified as yet.
|
|
\item[x5z Mail system\,] These replies indicate the status of the
|
|
receiver mail system vis-a-vis the requested transfer or other mail
|
|
system action.
|
|
\end{description}
|
|
|
|
\begin{table}
|
|
\begin{center}
|
|
\label{smtp-reply-codes}
|
|
\begin{tabular}{|lp{10cm}|}
|
|
\hline
|
|
500 & Syntax error, command unrecognized \newline
|
|
[This may include errors such as ``command line too long''] \\
|
|
501 & Syntax error in parameters or arguments \\
|
|
502 & Command not implemented\\
|
|
503 & Bad sequence of commands\\
|
|
504 & Command parameter not implemented\\
|
|
\hline
|
|
211 & System status, or system help reply\\
|
|
214 & Help message \newline
|
|
[Information on how to use the receiver or the meaning of a
|
|
particular non-standard command; this reply is useful only
|
|
to the human user]\\
|
|
\hline
|
|
220 & \semvar{domain} Service ready \\
|
|
221 & \semvar{domain} Service closing transmission channel\\
|
|
421 & \semvar{domain} Service not available,
|
|
closing transmission channel\newline
|
|
[This may be a reply to any command if the service knows it
|
|
must shut down]\\
|
|
\hline
|
|
250 & Requested mail action okay, completed\\
|
|
251 & User not local; will forward to \semvar{forward-path}\\
|
|
450 & Requested mail action not taken: mailbox unavailable
|
|
[E.g., mailbox busy]\\
|
|
550 & Requested action not taken: mailbox unavailable
|
|
[E.g., mailbox not found, no access]\\
|
|
451 & Requested action aborted: error in processing\\
|
|
551 & User not local; please try \semvar{forward-path}\\
|
|
452 & Requested action not taken: insufficient system storage\\
|
|
552 & Requested mail action aborted: exceeded storage allocation\\
|
|
553 & Requested action not taken: mailbox name not allowed
|
|
[E.g., mailbox syntax incorrect]\\
|
|
354 & Start mail input; end with \ex{CRLF}.\ex{CRLF}\\
|
|
554 & Transaction failed\\
|
|
\hline
|
|
\end{tabular}
|
|
\caption{Complete list of SMTP reply-codes.}
|
|
\end{center}
|
|
\end{table}
|
|
|
|
\begin{table}
|
|
\begin{center}
|
|
\label{smtp-command-reply-codes}
|
|
\begin{tabular}{|l||l|l|l|l|}
|
|
\hline
|
|
\bf{What} & \bf{intermediate} & \bf{success} & \bf{failure} & \bf{error}\\
|
|
\hline
|
|
\hline
|
|
conn. establ. & &
|
|
220 &
|
|
421 &\\
|
|
HELO & &
|
|
250 & &
|
|
500, 501, 504, 421\\
|
|
MAIL & &
|
|
250 &
|
|
552, 451, 452 &
|
|
500, 501, 421\\
|
|
RCPT & &
|
|
250, 251 &
|
|
550, 551, 552, 553, 450, 451, 452 &
|
|
500, 501, 503, 421\\
|
|
DATA &
|
|
354 \verb|->| data &
|
|
250 &
|
|
552, 554, 451, 452 & \\ & otherwise & &
|
|
451, 554 &
|
|
500, 501, 503, 421\\
|
|
RSET & &
|
|
250 & &
|
|
500, 501, 504, 421\\
|
|
SEND & &
|
|
250 &
|
|
552, 451, 452 &
|
|
500, 501, 502, 421\\
|
|
SOML & &
|
|
250 &
|
|
552, 451, 452 &
|
|
500, 501, 502, 421\\
|
|
SAML & &
|
|
250 &
|
|
552, 451, 452 &
|
|
500, 501, 502, 421\\
|
|
VRFY & &
|
|
250, 251 &
|
|
550, 551, 553 &
|
|
500, 501, 502, 504, 421\\
|
|
EXPN & &
|
|
250 &
|
|
550 &
|
|
500, 501, 502, 504, 421\\
|
|
HELP & &
|
|
211, 214 & &
|
|
500, 501, 502, 504, 421\\
|
|
NOOP & &
|
|
250 & &
|
|
500, 421\\
|
|
QUIT & &
|
|
221 & &
|
|
500\\
|
|
TURN & &
|
|
250 &
|
|
502 &
|
|
500, 503\\
|
|
\hline
|
|
\end{tabular}
|
|
\caption{command--reply sequences.}
|
|
\end{center}
|
|
\end{table}
|
|
|
|
|
|
|
|
%%% Local Variables:
|
|
%%% mode: latex
|
|
%%% TeX-master: t
|
|
%%% End:
|