diff --git a/doc/latex/smtp.tex b/doc/latex/smtp.tex index 0246352..a5639ab 100644 --- a/doc/latex/smtp.tex +++ b/doc/latex/smtp.tex @@ -1,374 +1,114 @@ -\chapter{Using SMTP}\label{cha:smtp} -% -\begin{description} -\item[Used files:] smtp.scm -\item[Name of the package:] smtp -\end{description} +\chapter{SMTP Client}\label{cha:smtp} % +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} -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 procedures described here usually return an SMTP reply code. For +details, see RFC~821. -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: +\defun{smtp-send-mail}{from to-list headers body [host]}{code list} +\begin{desc} + This emails message \var{body} with hedaers \var{headers} to + recipients in list \var{to-list}, using a sender address \var{from}. + 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. + + This returns two values: \var{code} and \var{list}, the code + returned by the server and the text message, represented as a list + lines. If some recipients were rejected, \ex{smtp-send-mail} sends + to the rest of the recipients, and returns code 700 and an + association list whose elements are of the form + \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} -\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 [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} +\defun{smtp-expand}{name host}{code text} +\defunx{smtp-verify}{name host}{code text} +\defunx{smtp-get-help}{host [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. + RFC~821: \ex{smtp-expann} 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{Smtp-verify} 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{Smtp-get-help} causes the server to send helpful information. + The command may take an argument (\var{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} +\defun{smtp-connect}{host [port]}{smtp-connection} \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. + \ex{Smtp-connect} returns an SMTP connection value that represents + a connection to the SMTP server. \end{desc} -\defun{smtp/open}{host [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} +\defun{smtp-transactions}{smtp-connection transaction1 ...}{code text-list} +\defunx{smtp-transactions/no-close}{smtp-connection transaction1 ...}{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} + 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. -\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{ }, 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{ - } to \ex{ }; the SMTP receiver undoes - this mapping. + For each transaction, + \begin{itemize} + \item If the transaction's reply code is 221 or 421 (meaning the socket has + been closed), then the transaction sequence is aborted, and + \ex{smtp-transactions}/\ex{smtp-transactions/no-close} return the + reply code and text from that 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 code + and text values are returned. \ex{Smtp-transactions} will additionally + close the socket for you; \ex{smtp-transactions/no-close} will not. + \item If the transaction is the last in the transaction sequence, + its reply code and text are returned. + \item Otherwise, we throw away the current reply code and text, and + proceed to the next transaction. + \end{itemize} + % + \ex{Smtp-transactions} closes the socket after the transaction. (The + \ex{smtp-quit} transaction, when executed, also closes the transaction.) - \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} + If the socket should be kept open in the case of an abort, use + \ex{Smtp-transactions/no-close}. +\end{desc} -\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} +\defunx{smtp-helo}{local-host-name}{smtp-transaction} +\defunx{smtp-mail}{sender-address}{smtp-transaction} +\defunx{smtp-rcpt}{destination-address}{smtp-transaction} +\defunx{smtp-data}{socket message}{smtp-transaction} +\defunx{smtp-send}{sender-address}{smtp-transaction} +\defunx{smtp-soml}{sender-address}{smtp-transaction} +\defunx{smtp-saml}{sender-address}{smtp-transaction} +\defvarx{smtp-rset}{smtp-transaction} +\defunx{smtp-vrfy}{user}{smtp-transaction} +\defunx{smtp-expn}{user}{smtp-transaction} +\defunx{smtp-help}{details}{smtp-transaction} +\defvarx{smtp-noop}{smtp-transaction} +\defvarx{smtp-quit}{smtp-transaction} +\defvarx{smtp-turn}{smtp-transaction} +\begin{desc} + These transactions represent the commands of the SMTP protocol for + use in \ex{smtp-transactions} and \ex{smtp-transactions/no-close}, + i.e.\ they send the corresponding command along with the argument(s), + if any. For details, consult RFC~821. + + The \ex{smtp-quit} transaction, in addition to sending a \ex{QUIT} + command to the SMTP server, also closes the socket of its SMTP + connection. +\end{desc} %%% Local Variables: