## NAME

DwSmtpClient -- Class for handling the client side of an SMTP session

## SYNOPSIS

    class DW_EXPORT DwSmtpClient : public DwProtocolClient {

    public:

        enum {
            kCmdNoCommand=0,
            kCmdHelo,
            kCmdMail,
            kCmdRcpt,
            kCmdData,
            kCmdRset,
            kCmdSend,
            kCmdSoml,
            kCmdSaml,
            kCmdVrfy,
            kCmdExpn,
            kCmdHelp,
            kCmdNoop,
            kCmdQuit,
            kCmdTurn
        };

        DwSmtpClient();
        virtual ~DwSmtpClient();
        virtual int Open(const char* aServer, DwUint16 aPort=25);
        int ReplyCode() const;
        const DwString& Response() const;
        int Helo();
        int Mail(const char* aFrom);
        int Rcpt(const char* aTo);
        int Data();
        int Rset();
        int Send(const char* aFrom);
        int Soml(const char* aFrom);
        int Saml(const char* aFrom);
        int Vrfy(const char* aName);
        int Expn(const char* aName);
        int Help(const char* aArg=0);
        int Noop();
        int Quit();
        int Turn();
        int SendData(const DwString& aStr);
        int SendData(const char* aBuf, int aBufLen);
    };

## DESCRIPTION

`DwSmtpClient` is a class that handles the client side of an SMTP session. Specifically, `DwSmtpClient` provides facilities for opening a connection to an SMTP server, sending commands and data to the server, receiving responses from the server, and closing the connection. The protocol implemented is the Simple Mail Transport Protocol, as specified in RFC-821.

`DwSmtpClient` is derived from `DwProtocolClient`. For information about inherited member functions, especially member functions for detecting failures or errors, see the man page for `DwProtocolClient`.

In an SMTP session, the client sends commands to the server and receives responses from the server. A client command consists of a command word and possibly an argument. A server response consists of a three-digit numeric reply code followed by text. The reply code indicates a success or failure condition. `DwSmtpClient` provides facilities for you to send commands to the server and receive responses from the server.

`DwSmtpClient` has only a default constructor. On Win32 platforms, it is possible for the constructor to fail. (It calls WSAStartup().) You should verify that the constructor succeeded by calling the inherited member function `DwProtocolClient::LastError()` and checking for a zero return value.

To open a connection to the server, call the member function `Open()` with the name of the server as an argument. `Open()` accepts an optional argument that specifies the TCP port that the server listens to. The default port is the standard SMTP port (25). `Open()` may fail, so you should check the return value to verify that it succeeded. To close the connection, call the inherited member function `DwProtocolClient::Close()`. To check if a connection is open, call the inherited member function `DwProtocolClient::IsOpen()`. `IsOpen()` returns a boolean value that indicates whether or not a call to `Open()` was successful; it will not detect failure in the network or a close operation by the remote host.

For each SMTP command, `DwSmtpClient` has a member function that sends that command and receives the server's response. If the command takes an argument, then that argument is passed as a function argument to the command function. The command functions return the numeric value of the three-digit reply code returned by the server. Your program must check the reply code to determine whether or not the command was accepted and performed by the server. In some cases, because of a communications error or some other error, it is not possible for the command function to send the command or receive the response. When this happens, the command function will return 0. You can determine the precise error or failure by calling the inherited member functions `DwProtocolClient::LastError()` or `DwProtocolClient::LastFailure()`.

After each command is sent, `DwSmtpClient` receives the server's response and remembers it. The member function `ReplyCode()` returns the numberic value of the reply code received in response to the last command. `Response()` returns the entire response from the server, including the reply code. If no response is received, possibly because of a communications error or failure, `ReplyCode()` returns zero and `Response()` returns an empty string.

Following a successful response to the DATA command, an SMTP client sends multiple lines of text to the server. To perform this bulk data transfer, `DwSmtpClient` provides the member function `SendData()`. In the current implementation, `SendData()` does not convert end of line characters, so it is your responsibility to convert the end of line characters to CR LF, if necessary. (You may use the utility function `DwToCrLfEol()` to do the conversion.) `SendData()` will perform the character stuffing to protect '.' at the beginning of a line, and it will append the final [CR LF] '.' CR LF. It is possible to divide data and make multiple calls to `SendData()`; however, if you do so, please note the following paragraph.

Note: Because of a feature (some might say bug) in the current implementation, `SendData()` will not detect a '.' at the beginning of a line if the CR LF '.' sequence is split between two calls to `SendData()`. This problem will probably be resolved in a future version, but be aware that such a change will require a change in `DwSmtpClient`'s interface.

## Public Member Functions

DwSmtpClient()

Initializes the `DwSmtpClient` object. It is possible for the constructor to fail. To verify that the constructor succeeded, call the member function `LastError()` and check that it returns zero. (In the Win32 implementation, the constructor calls the Winsock function `WSAStartup()`, which may fail.)

virtual int Open(const char* aServer, DwUint16 aPort=25)

Opens a TCP connection to the server `aServer` at port `aPort`. `aServer` may be either a host name, such as "smtp.acme.com" or an IP number in dotted decimal format, such as "147.81.64.60". The default value for `aPort` is 25, the well-known port for SMTP assigned by the Internet Assigned Numbers Authority (IANA).

If the connection attempt succeeds, the server sends a response. `Open()` returns the server's numeric reply code. The full response from the server can be retrieved by calling `Response()`.

If the connection attempt fails, `Open()` returns 0. To determine what error occurred when a connection attempt fails, call the inherited member function `DwProtocolClient::LastError()`. To determine if a failure also occurred, call the inherited member function `DwProtocolClient::LastFailure()`.

int ReplyCode() const

Returns the numeric value of the three-digit reply code received from the server in response to the last client command. If no response was received, perhaps because of a communications failure, `ReplyCode()` returns zero.

const DwString& Response() const

Returns the entire response last received from the server. If no response was received, perhaps because of a communications failure, `Response()` returns an empty string.

int Helo()

Sends the SMTP HELO command and returns the reply code received from the server. If no response is received the function returns zero.

int Mail(const char* aFrom)

Sends the SMTP MAIL command with `aFrom` as the sender and returns the reply code received from the server. If no response is received, the function returns zero.

int Rcpt(const char* aTo)

Sends the SMTP RCPT command with `aTo` as the recipient and returns the reply code received from the server. If no response is received, the function returns zero.

int Data()

Sends the SMTP DATA command and returns the reply code received from the server. If no response is received, the function returns zero.

int Rset()

Sends the SMTP RSET command and returns the reply code received from the server. If no response is received, the function returns zero.

int Send(const char* aFrom)

Sends the SMTP SEND command with `aFrom` as the sender and returns the reply code received from the server. If no response is received, the function returns zero.

int Soml(const char* aFrom)

Sends the SMTP SOML command with `aFrom` as the sender and returns the reply code received from the server. If no response is received, the function returns zero.

int Saml(const char* aFrom)

Sends the SMTP SAML command with `aFrom` as the sender and returns the reply code received from the server. If no response is received, the function returns zero.

int Vrfy(const char* aName)

Sends the SMTP VRFY command with `aName` as the argument and returns the reply code received from the server. If no response is received, the function returns zero.

int Expn(const char* aName)

Sends the SMTP EXPN command with `aName` as the argument and returns the reply code received from the server. If no response is received, the function returns zero.

int Help(const char* aArg=0)

Sends the SMTP HELP command with `aArg` as the argument and returns the reply code received from the server. If no response is received, the function returns zero.

int Noop()

Sends the SMTP NOOP command and returns the reply code received from the server. If no response is received, the function returns zero.

int Quit()

Sends the SMTP QUIT command and returns the reply code received from the server. If no response is received, the function returns zero.

int Turn()

Sends the SMTP TURN command and returns the reply code received from the server. If no response is received, the function returns zero.

int SendData(const DwString& aStr)
int SendData(const char* aBuf, int aBufLen)

Sends bulk data to the server and returns the reply code received. A bulk data transfer follows a DATA command and is used to send a complete message to the server.

In the current implementation, `SendData()` does not convert end of line characters, so it is your responsibility to convert the end of line characters to CR LF, if necessary. (You may use the utility function `DwToCrLfEol()` to do the conversion.) `SendData()` will perform the character stuffing to protect '.' at the beginning of a line, and it will append the final [CR LF] '.' CR LF. It is possible to divide the data and make multiple calls to `SendData()`; however, this may cause problems in the current implementation if a CR LF '.' sequence is split between calls.