Sending Mail with SMTP
Table of Contents | Previous | Next | Index

Messaging Access SDK Guide
Part 1. Using the Messaging Access SDK


Chapter 2
Sending Mail with SMTP

This chapter is an overview of using SMTP (Simple Mail Transfer Protocol) to create and send email messages.

[Top]

The SMTP Protocol

SMTP (Simple Mail Transport Protocol) allows clients to deliver mail messages to SMTP servers. To retrieve these messages, the client uses the IMAP4 or POP3 protocol. Servers can use SMTP to move messages from one server to another before delivering them to a mailbox.

The SMTP client always starts the session, but either client or server can end it. The client starts the session by connecting to the server. The server acknowledges the message with a greeting. The client responds, and, in subsequent commands, specifies the message sender and recipients and sends the message.

SMTP commands are made up of a keyword, followed by any parameters the method has. Commands receive a three-digit response code, described in SMTP Response Codes. SMTP commands include only the U.S. ASCII character set, a subset of ASCII that includes the values 00h-7Fh (0d-127d).

The responses returned by SMTP commands are made up of a three-digit numeric code followed by descriptive text. The client application can detect and handle the response or display the message to the user for interpretation. For more information, see SMTP Response Codes.

If your server supports Extended SMTP (ESMTP), which is provided in an update to the existing SMTP specification, your mail application can take advantage of ESMTP elements, such as pipelining, the bdat command, data chunking, and DSN. For more information, see Determining ESMTP Support.

During a single SMTP session, the client can send multiple unrelated, independently addressed messages. Because of this, the SMTP client can increase efficiency by batching messages and sending them together using pipelining. For more information, see Pipelining Commands.

The SMTP server waits for SMTP messages on the "well-known" TCP port 25. Many mail applications allow the user to specify a different port.

For a table of SDK-supported SMTP protocol commands, see Supported SMTP Internet Protocol Commands. For detailed information about SMTP, consult one of the RFCs listed, with links, in SMTP RFCs.

[Top]

Steps in an SMTP Session

Generally, a messaging application follows these steps when using SMTP to send mail. These steps are listed below with links to more detailed descriptions.

Step Section with details

Initialize the response sink.

Creating a Response Sink

Initialize the client.

Creating a Client

Connect to the server.

Connecting to a Server

Determine Extended SMTP (ESMTP)
features supported by the server.

Determining ESMTP Support

Set the mailer.

Setting the Mailer

Set the recipients.

Setting the Recipient

Send the message.

Sending the Message

End the SMTP session.

Ending the Session

[Top]

SMTP Response Codes

When the client sends an SMTP command, the response that comes back contains a standard three-digit response code followed by descriptive text. This section is an overview of SMTP responses. For detailed information, see RFC 821.

The response contains the three digit code, a space, and one or more lines of text that describes the response. If the response is multi-line, each subsequent line also contains the three digit code, a hyphen, and text. The final line contains the code, a space, and text.

This table lists some of the most common SMTP reply codes. In general, response codes in the 100 to 300 range are considered successful; those in the 400 to 500 range are considered unsuccessful.

Table 2.1 SMTP Reply Codes

Code Text of Response

211

system status, or system help reply

214

help message

220

<domain> service ready

221

<domain> service closing transmission channel

250

request mail action okay, completed

251

user not local, will forward to <forward-path >

354

start mail input; and with <CRLF>.<CRLF>

421

<domain> servers not available, closing transmission channel

450

requested mail action not taken: mailbox unavailable

451

requested action aborted: local error in processing

452

requested action not taken: insufficient system storage

500

syntax error, command unrecognized

501

syntax error in parameters or arguments

502

command not implemented

503

bad sequence of commands

504

command parameter not implemented

550

requested action not taken: mailbox unavailable

551

user not local; please try <forward-path>

552

requested mail action aborted: exceeded storage allocation

553

requested action not taken: mailbox name not allowed

554

transaction failed

The first digit of the SMTP reply code basically tells whether the response is positive or negative.

Table 2.2 SMTP Reply Codes, Digit 1

Digit 1 Meaning
1yz

Positive Preliminary Reply

2yz

Positive Completion Reply

3yz

Positive Intermediate Reply

4yz

Transient Negative Completion Reply

5yz

Permanent Negative Completion Reply

The information described by the second and third digits is noted here. For the meanings of specific numbers, see RFC 821.

[Top]

SMTP in the Messaging Access SDK

The SMTP class hierarchy is made up of the following classes.

[Top]

SMTP Callback Mapping

Callbacks are associated with many SMTP methods. For general information about the response sink and callbacks, see "SDK Sink Classes for Java."

The ISMTPSink interface contains callbacks for each client call. The client's processResponses method invokes the interface method that corresponds to the client call. Methods with multi-line responses map to more than one callback. The second callback provides a notification that the operation is complete.

If a server error occurs, the error callback is invoked.

Table 2.3 shows which SMTP methods are mapped to callbacks in the ISMTPSink interface. Table 2.4 shows methods that do not map to callbacks.

Table 2.3 Methods with Callbacks

SMTPClient Methods Possible Callbacks on ISMTPSink
bdat
bdat, error 
connect 
connect, error 
data
data, error 
ehlo
ehlo, ehloComplete, error 
expand
expand, expandComplete, error 
help
help, helpComplete, error 
mailFrom
mailFrom, error
noop
noop, error
quit
quit, error 
rcptTo
rcptTo, error 
reset
reset, error 
send
send, error
sendCommand
sendCommand, sendCommandComplete, error
sendStream
send, error 
verify
verify, error
Table 2.4 Methods without Callbacks

Methods Without Callbacks
disconnect
setChunkSize
free
setPipelining
get_option
setResponseSink
initialize
setTimeout
processResponses
set_option
[Top] [SMTP Callback Mapping]


Creating a Response Sink

The first step in starting an SMTP session is to create the SMTP response sink, which is defined by the ISMTPSink interface. The response sink contains the callback methods for the SMTP client. For general information about the response sink, see "SDK Sink Classes for Java."

The ISMTPSink interface contains callbacks for each client call. You must implement this interface in order to use the SMTP client object. The constructor for the SMTPClient class takes an ISMTPSink object as a parameter.

To create your own response sink class, you can implement the ISMTPSink interface, using this syntax:

public class newSMTPSink extends Object 
   implements ISMTPSink
As a convenience, the Messaging SDK provides the SMTPSink class, which implements the ISMTPSink interface. SMTPSink implements all the interfaces in ISMTPSink. By default, the implementation does nothing, except provide the error callback, which throws an exception. You can save a step by extending this class, using this syntax:

public class newSMTPSink extends SMTPSink{
   }
The following section of code creates a response sink.

SMTPSink l_smtpSink; 
l_smtpSink = new SMTPSink();
After you create the response sink, the next step is Creating a Client.

[Top]

Creating a Client

The SMTP client uses an SMTPClient object to communicate with the server. To create the SMTPClient object and set the response sink for the client's use, call the SMTPClient.SMTPClient class constructor, which takes an existing response sink. Use this syntax:

public SMTPClient(ISMTPSink in_sink)
The following section of code creates a client.

/* Create sink first, as described in Creating a Response Sink */
SMTPClient l_client; 
SMTPSink l_smtpSink; 
l_client = new SMTPClient( l_smtpSink ); 
After you initialize the client, the next step is Connecting to a Server.

[Top]

Connecting to a Server

Before sending mail, the client must connect with the server through a service port. To connect to the server, call either of two SMTPClient.connect methods, depending on whether or not you want to specify the connection port. The SDK methods perform some error-checking.

To connect to the server using the default port for the SMTP protocol (port 25), use this form of connect and supply the identifier of the server:

public synchronized void connect(String in_server) throws IOException
To specify the server port to use for the server connection, use the other form of connect:

public synchronized void connect(String in_server,
                                 int in_port) throws IOException
On connecting, the server sends a greeting message to client. The client responds by identifying itself with the EHLO command.

NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
The following section of code connects the client to the server.

/* After Creating a Response Sink and Creating a Client */
l_client.connect( "smtpserver.com" ); 
l_client.processResponses(); 
During the connect process, you can enable pipelining if your server supports it. See Pipelining Commands. To find out which extensions are supported by the server, see Determining ESMTP Support. After connecting to the server, the next step is Setting the Mailer

To disconnect the client from the server, and close the socket connection, use this SMTPClient class method.

public synchronized void disconnect() throws IOException
You could use this function as part of a Cancel operation while retrieving a message. Remember that you do not call processResponses after disconnect. If an input or output error occurs, the method throws an IOException.

[Top]

Determining ESMTP Support

To retrieve a listing of extensions that are supported by the server, call the SMTPClient.ehlo method. This method returns a multiline message listing the Extended SMTP (ESMTP) features, such as pipelining or DSN, that the server supports. This is similar to the functionality of the IMAP4Client.capability command. Use this syntax:

public synchronized void ehlo(String in_domain) 
                              throws IOException
This method calls the EHLO SMTP protocol command, which can be issued in any session state, but is usually issued after connecting to the server.

In Messaging Server 3.5, the developer must determine ESMTP support; in Messaging Server 4.0, this is optional.

NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
The following section of code finds out which Extended SMTP (ESMTP) features the server supports.

/* After Connecting to a Server */
l_client.ehlo( "yourdomain.com" ); 
l_client.processResponses(); 
You can enable pipelining if your server supports this extension. See Pipelining Commands.

[Top]

Pipelining Commands

Pipelining allows you to group, or batch, methods for execution rather than sending each separately. If pipelining is enabled on your server, commands are stored internally in the client as they are issued. All commands begin to execute when triggered in one of three ways: if the SMTPClient.processResponses method is called, if the internal storage area is full, or if a method that cannot be pipelined is issued.

You can enable pipelining anywhere, but it may make sense to do this after invoking the SMTPClient.ehlo method. Pipelining may then be enabled if the server supports it. If not, the way the network works does not change. The ehlo callback indicates whether pipelining is supported.

Use this syntax to attempt to enable pipelining:

public synchronized void setPipelining(
                    boolean in_enablePipelining)
                    throws SMTPException
The in_enablePipelining parameter is a Boolean value that tells the server to attempt to enable pipelining. The method throws an SMTPException if PIPELINING is not supported by the server. This method sends the PIPELINING SMTP protocol command.

NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
Some methods continue to add to the pipelining list. These are SMTPClient.bdat, SMTPClient.mailFrom, SMTPClient.rcptTo, and SMTPClient.send. Calling any other method causes the methods on the pipelining list to begin executing.

For example, you could call mailFrom, followed by one or more calls to rcptTo. These methods are added to the pipelining list and are not executed. If you then call another method, such as noop, the commands are sent to the server.

For details about using pipelining, refer to RFC 1854,"SMTP Service Extension for Command Pipelining."

[Top]

Setting the Mailer

Setting the mailer starts the process of delivering a message. If your server supports Extended SMTP, you can implement ESMTP elements in the in_esmtpParams parameter. Use the SMTPClient.mailFrom method:

public synchronized void mailFrom(String in_reverseAddress,
                         String in_esmtpParams)
                         throws IOException
This method identifies the sender and provides the sender's fully qualified domain name in the in_reverseAddress parameter. It sends the MAIL FROM SMTP protocol command. If an I/O error occurs, the method throws an IOException.

NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
The following section of code sets the mailer.

/* After Connecting to a Server */
SMTPClient l_client; 
l_client.mailFrom( "sender@netscape.com", null ); 
l_client.processResponses();
After you set the mailer, the next step is Setting the Recipient.

[Top]

Setting the Recipient

After setting the mailer, the next step is to set the recipient. Use this SMTPClient class method:

public synchronized void rcptTo(String in_forwardAddress,
                               String in_esmtpParams)
                               throws IOException
This method sets a single recipient, so you must call it again for each recipient of a message. The in_forwardAddress parameter contains the recipient's address. If your server supports Extended SMTP, you can pass ESMTP elements in the in_esmtpParams parameter. If an input or output error occurs, the method throws an IOException.

SMTPClient.rcpTo sends the RCPT TO SMTP protocol command.

NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
The following section of code sets the recipient.

/* After Setting the Mailer */
l_client.rcptTo( "recipient@netscape.com", null ); 
l_client.processResponses(); 
After you set the recipient, the next step is Sending the Message.

[Top]

Sending the Message

After setting all of the message recipients, the client can send the message data. To send a message, use SMTPClient.data, followed by the SMTPClient.send method. First, use this method:

public synchronized void data() 
                     throws IOException
The server responds with a success or failure reply code. See SMTP Response Codes.

The SMTPClient.send method delivers data to the server. If you use this method, you must send data with the SMTPClient.data method and not with SMTPClient.bdat. The SMTPClient.bdat method, which can deliver binary data, is not supported on the Netscape Messaging Server and some other servers.

After the data method, call SMTPClient.send, which sends a message to the server:

public synchronized void send(
      InputStream in_inputStream) throws IOException
The input stream contains the data to send. When the server responds that it is ready, the client sends the RFC 822 message data line by line.

You can set data chunk size with SMTPClient.setChunkSize, or you can use the default (1 K). You can set this at any point before the SMTPClient.send method.

NOTE: For the callback mapping for these methods, see SMTP Callback Mapping. §
The following section of code uses SMPTClient.data and SMPTClient.send to send a message.

l_client.data(); 
l_client.processResponses(); 
l_client.send( new ByteArrayInputStream( "Hello World!!!" ) ); 
l_client.processResponses();
After you send the message and perform any other SMTP operations you need for the session, the next step is Ending the Session.

To use a more convenient, but less flexible, way to send messages, see Sending Messages with Convenience APIs.

[Top]

Sending Messages with Convenience APIs

The Messaging Access SDK provides two Convenience APIs that combine several message-handling operations in one step. The ImTransport.sendMessage and ImTransport.sendDocuments methods are for developers who want to mail-enable applications, such as spreadsheets and word processors, whose primary purpose is not messaging. Adding this mail functionality can allow the end user to mail documents or post them to a news group from within the application.

The ImTransport.sendMessage method is a convenience for sending messages. It lets the client use SMTP to send a message that is already in MIME format.

This method connects to the SMTP transport at the specified host, and submits a message created with the Netscape MIME API or in any other way. Use this syntax:

public String[] sendMessage(String host,
                            String sender,
                            String recipients[],
                            InputStream MIMEMessageStream)
                            throws IMException
You provide the names of the host and sender, and the email addresses of the recipients. The input stream contains the MIME message itself.

The Messaging Access SDK also provides an API for building and sending a message in a single step. For more information, see Sending Documents with the Convenience API.

[Top]

Ending the Session

When the client wants to end the session, the client should call SMTPClient.quit to notify the server. The server closes the TCP connection and returns a response code. You should always end a session with quit instead of just closing the connection. This method sends the QUIT SMTP protocol command:

public synchronized void quit() throws IOException
NOTE: For this method's callback mapping, see SMTP Callback Mapping. §
The following section of code notifies the server that the client is terminating the session.

l_client.quit(); 
l_client.processResponses(); 
[Top]


Table of Contents | Previous | Next | Index

Last Updated: June 3, 1998

Copyright © 1998 Netscape Communications Corporation