\section{Using SMTP}\label{sec:smtp}
%
\begin{description}
\item[Used files:] smtp.scm
\item[Name of the package:] smtp 
\end{description}
%

\subsection{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}.

\subsection{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}

\subsection{Additional information about SMTP}

\subsubsection*{Reply codes}

This material is taken from the RFC. The first digits encode categories
of responses:
\begin{description}
\item{\bfseries 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{\bfseries 2yz  Positive Completion reply\,} The requested action has
  been successfully completed.  A new request may be initiated.
\item{\bfseries 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{\bfseries 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{\bfseries 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{\bfseries x0z  Syntax\,} These replies refer to syntax errors,
  syntactically correct commands that don't fit any functional
  category, and unimplemented or superfluous commands.
\item{\bfseries x1z  Information\,} These are replies to requests for
  information, such as status or help.
\item{\bfseries x2z  Connections\,} These are replies referring to the
  transmission channel.
\item{\bfseries x3z\,} Unspecified as yet.
\item{\bfseries x4z\,} Unspecified as yet.
\item{\bfseries 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: 
