Reasonably complete and up-to-date documentation.

This commit is contained in:
sperber 2003-01-21 15:54:02 +00:00
parent b60335d2cd
commit b2c4e59cb8
1 changed files with 96 additions and 356 deletions

View File

@ -1,375 +1,115 @@
\chapter{Using SMTP}\label{cha:smtp} \chapter{SMTP Client}\label{cha:smtp}
%
\begin{description}
\item[Used files:] smtp.scm
\item[Name of the package:] smtp
\end{description}
% %
The \ex{smtp} structure provides an client library for the Simple Mail
Transfer Protocol, commonly used for sending email on the Internet.
This library provides a simple wrapper for sending complete emails as
well as procedures for composing custom SMTP transactions.
\section{Philosophy} The procedures described here usually return an SMTP reply code. For
SMTP protocol procedures tend to return two values: details, see RFC~821.
\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 \defun{smtp-send-mail}{from to-list headers body [host]}{code list}
\ex{CR}/\ex{LF}'s stripped. Codes in the range $[1,399]$ are sucess \begin{desc}
codes; codes in the range $[400,599]$ are error codes; codes $>= 600$ This emails message \var{body} with hedaers \var{headers} to
are not part of the official SMTP spec. This module uses codes $>= recipients in list \var{to-list}, using a sender address \var{from}.
600$ to indicate extra-protocol errors. There are two of these: The email is handed off to the SMTP server running on \var{host};
default is the local host. \var{Body} is either a list of strings
representing the lines of the message body or an input port which is
exhausted to determine the message body. \var{Headers} is an
association lists, mapping symbols representing RFC~822 field names
to strings representing field bodies.
\begin{description} This returns two values: \var{code} and \var{list}, the code
\item[600 Server reply could not be parsed.] returned by the server and the text message, represented as a list
The server sent back some sort of incomprehensible garbage reply. lines. If some recipients were rejected, \ex{smtp-send-mail} sends
\item[621 Premature EOF while reading server reply.] to the rest of the recipients, and returns code 700 and an
The server shut down in the middle of a reply. association list whose elements are of the form
\end{description} \ex{(\var{loser-recipient} \var{code} . \var{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{desc}
A list of the official protocol return codes can be seen in table \defun{smtp-expand}{name host}{code text}
\ref{smtp-reply-codes}. \defunx{smtp-verify}{name host}{code text}
\defunx{smtp-get-help}{host [details]}{code text-list}
\section{Procedures}
\begin{defundesc}{sendmail}{to-list body [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 [details]}{code text-list}
\begin{desc} \begin{desc}
These three are simple queries of the server as stated in the These three are simple queries of the server as stated in the
RFC~821: \ex{expn} asks the server to confirm that the argument RFC~821: \ex{smtp-expann} asks the server to confirm that the
identifies a mailing list, and if so, to return the membership of argument identifies a mailing list, and if so, to return the
that list. The full name of the users (if known) and the fully membership of that list. The full name of the users (if known) and
specified mailboxes are returned in a multiline reply. \ex{vrfy} the fully specified mailboxes are returned in a multiline reply.
asks the receiver to confirm that the argument identifies a user. \ex{Smtp-verify} asks the receiver to confirm that the argument
If it is a user name, the full name of the user (if known) and the identifies a user. If it is a user name, the full name of the user
fully specified mailbox are returned. \ex{mail-help} causes the (if known) and the fully specified mailbox are returned.
server to send helpful information. The command may take an argument \ex{Smtp-get-help} causes the server to send helpful information.
(\semvar{details}) (e.g., any command name) and return more specific The command may take an argument (\var{details}) (e.g., any command
information as a response. name) and return more specific information as a response.
\end{desc} \end{desc}
\defun{smtp-connect}{host [port]}{smtp-connection}
\dfn{smtp-transactions}{socket ?transaction1 ...}{code
text-list}{syntax}
\dfnx{smtp-transactions/no-close}{socket ?transaction1 ...}{code
text-list}{syntax}
\begin{desc} \begin{desc}
These macros make it easy to do simple sequences of SMTP commands. \ex{Smtp-connect} returns an SMTP connection value that represents
a connection to the SMTP server.
\end{desc}
Evaluate a series of expressions \semvar{?transaction1}, \defun{smtp-transactions}{smtp-connection transaction1 ...}{code text-list}
\semvar{?transaction2}, \ldots \defunx{smtp-transactions/no-close}{smtp-connection transaction1 ...}{code text-list}
\begin{desc}
These procedures make it easy to do simple sequences of SMTP
commands. \var{Smtp-connection} must be an SMTP connection as
returned by \ex{smtp-connect}. The \var{transaction} arguments must
be transactions as returned by the procedures below.
\ex{Smtp-transactions} and \ex{smtp-transactions/no-close} execute
the transactions specified by the arguments.
For each transaction,
\begin{itemize} \begin{itemize}
\item Each expression should perform an SMTP transaction, and return \item If the transaction's reply code is 221 or 421 (meaning the socket has
two values: \semvar{code} (the integer reply code) and \semvar{text} been closed), then the transaction sequence is aborted, and
(list of strings that came with the reply). \ex{smtp-transactions}/\ex{smtp-transactions/no-close} return the
\item If the transaction's reply code is 221 or 421 (meaning the reply code and text from that transaction.
socket has been closed), then the transaction sequence is is \item If the reply code is an error code (in the four- or five-hundred range),
aborted, and the \ex{smtp\=trans\ob{}actions} form returns the the transaction sequence is aborted, and the fatal transaction's code
\semvar{code} and \semvar{text} values for the current transaction. and text values are returned. \ex{Smtp-transactions} will additionally
\item If the reply code is an error code (in the four- or five-hundred close the socket for you; \ex{smtp-transactions/no-close} will not.
range), the transaction sequence is aborted, and the fatal \item If the transaction is the last in the transaction sequence,
transaction's \semvar{code} and \semvar{text} values are returned. its reply code and text are returned.
\ex{smtp\=trans\ob{}actions} will additionally close the socket for \item Otherwise, we throw away the current reply code and text, and
you; \ex{smtp-trans\ob{}actions/\ob{}no\=close} will not. proceed to the next transaction.
\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} \end{itemize}
%
Since \ex{smtp-trans\ob{}actions} closes the socket whenever it \ex{Smtp-transactions} closes the socket after the transaction. (The
aborts a sequence, an \ex{smtp-trans\ob{}actions} form terminated \ex{smtp-quit} transaction, when executed, also closes the transaction.)
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 If the socket should be kept open in the case of an abort, use
\ex{smtp-trans\ob{}actions/\ob{}no\=close}. \ex{Smtp-transactions/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} \end{desc}
\defun{smtp/open}{host [port]}{socket} \defunx{smtp-helo}{local-host-name}{smtp-transaction}
\defunx{smtp/helo}{local-host-name}{code text-list} \defunx{smtp-mail}{sender-address}{smtp-transaction}
\defunx{smtp/mail}{sender-address}{code text-list} \defunx{smtp-rcpt}{destination-address}{smtp-transaction}
\defunx{smtp/rcpt}{destination-address}{code text-list} \defunx{smtp-data}{socket message}{smtp-transaction}
\defunx{smtp/data}{socket message}{code text-list} \defunx{smtp-send}{sender-address}{smtp-transaction}
\defunx{smtp/send}{sender-address}{code text-list} \defunx{smtp-soml}{sender-address}{smtp-transaction}
\defunx{smtp/soml}{sender-address}{code text-list} \defunx{smtp-saml}{sender-address}{smtp-transaction}
\defunx{smtp/saml}{sender-address}{code text-list} \defvarx{smtp-rset}{smtp-transaction}
\defunx{smtp/rset}{}{code text-list} \defunx{smtp-vrfy}{user}{smtp-transaction}
\defunx{smtp/vrfy}{user}{code text-list} \defunx{smtp-expn}{user}{smtp-transaction}
\defunx{smtp/expn}{user}{code text-list} \defunx{smtp-help}{details}{smtp-transaction}
\defunx{smtp/help}{details}{code text-list} \defvarx{smtp-noop}{smtp-transaction}
\defunx{smtp/noop}{}{code text-list} \defvarx{smtp-quit}{smtp-transaction}
\defunx{smtp/quit}{socket}{code text-list} \defvarx{smtp-turn}{smtp-transaction}
\defunx{smtp/turn}{}{code text-list}
\begin{desc} \begin{desc}
These functions implement the basics of the protocol, i.e. they send These transactions represent the commands of the SMTP protocol for
the corresponding command along with the argument(s), if any. A use in \ex{smtp-transactions} and \ex{smtp-transactions/no-close},
short look to the code of \ex{\%sendmail} will give you the basics i.e.\ they send the corresponding command along with the argument(s),
on how to use the commands. You will obtain further informations in if any. For details, consult RFC~821.
the RFC~821. \semvar{host}, \semvar{local-host},
\semvar{sender-address}, \semvar{destination-address}, \semvar{user} The \ex{smtp-quit} transaction, in addition to sending a \ex{QUIT}
and \semvar{details} are strings, \semvar{message} may be a string command to the SMTP server, also closes the socket of its SMTP
or an input-port. \semvar{socket} is a socket, mostly one returned connection.
by \ex{smtp/\ob{}open}.
\end{desc} \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: %%% Local Variables:
%%% mode: latex %%% mode: latex