GoodServer

SMTP Server - Software Development Kit
~ README.html
~

SMTP-SSDK

1.0.6b


This document lists problems in the SMTP-SSDK that are known to GoodServer, both outstanding and repaired. To report a new bug or request a feature, send e-mail to support@goodserver.com .

1. Recent Closed Bugs

Version Bug Id Title
1.0.6 0343 Asterisk in socket binding not handled correctly
When an asterisk occurs as a value in an endpoint binding property, it does not result in the creation of a socket acceptor that listens on all ports. Instead, due to a logic error, it results in an invocation of the resolver library to enumerate addresses matching the host "localhost", and then the first returned address is used for the binding.

The logic error in question is in SocketAcceptorFactory, where the errant code:

if (strBinding != null || !"*".equals(strBinding))

should read:

if (strBinding != null && !"*".equals(strBinding))
1.0.6 0342 Local interface binding lookups should not require resolver
When a binding is specified for a network acceptor, the resolver library is invoked via InetAddress to lookup addresses for the host "localhost". This fails on some unix systems when no DNS server is present. JDK 1.4 introduced the NetworkInterface class to enumerate local interfaces and their addresses, which should now be used for this, removing the unnecessary external dependency and associated unnecessary external I/O.
1.0.6 0341 TelnetConnectionHandler ignores socket timeout property
The TelnetConnectionHandler class does not correctly load the socket timeout property.
1.0.5a 0336 No response sent after failure parsing MAIL FROM or RCPT TO args
The SmtpConnectionHandler.handleMail and handleRcpt command handlers correctly have ProtocolException catch blocks in the event that a failure occurs parsing the input stream for a reverse-path or forward-path. However, the catch blocks fail to send the response that they construct, leaving clients waiting upon a command response.
1.0.5a 0333 FlagsHelper returns null for "system user flag" instead of asterisk
The FlagsHelper.toString method maps JavaMail Flags.Flag objects to strings. This method incorrectly returns null for Flags.Flag.USER, instead of [backslash + asterisk], which would be the correct representation.
1.0.5a 0332 PropertiesPreferences.node() returns incorrect keys
When PropertiesPreferences is used to return a Preferences object for a child node, that node incorrectly returns invalid keys that contain delimiters and path prefixes.

Bug verified and fix validated with PreferencesHelperUT.testJob0332().
1.0.4d 0184 endpoint buffer.in and buffer.out properties inoperative
The endpoint properties buffer.in and buffer.out are not being read from the Preferences configuration. The values are defaulting to their hard-coded default size of 4k.

The ConnectionHandler interface has been modified to expose a connection handler's configuration as a 2nd argument to the init(...) method.

All ConnectionHandler implementations need to modify their init method signature.

The ConfProperties class has been deprecated, which contained a bug that was relevant to this issue. The PropertiesPreferences class was able to subsume all the necessary functionality that was provided by ConfProperties.

A buffer inputstream max line length property has been added so that servers may override the RFC recommended 8k max line length.
1.0.4b 0323 Cannot conveniently access returned SMTP capabilities
The SMTP client library should include a convenient accessor method for examining capabilities returned by the EHLO command.

The SmtpClient.sendEhlo() method returns a new SmtpEhloResponse class, providing convenient access to returned capabilities.
1.0.4a 0320 Cannot disable TLS manager
The framework advertises that it will not attempt to load a TLS manager when the tls.protocol property is blank or null. Instead, currently the TlsManagerImpl default implementation is being loaded, resulting in confusing logging in servers with no endpoints.

The way the tls.manager property was being read is also corrected, so that a blank value as well as a null value indicates that the default TLS manager should be used.
1.0.4a 0317 Excessive logging during network errors
When a network error occurs (IOException), the framework logs the exception and includes a stack trace. This is excessive, since the message of an IOException typically contains a fully descriptive summary of the problem, which is rarely if ever a programming error. Stack traces should be reserved for logging unhandled exceptions due to programming errors and the like.
1.0.4 0316 I/O performance suffers after STARTTLS
When a STARTTLS is performed, subsequent I/O operations over the secured channel occur in 17-byte blocks (a single byte payload plus the frame header). This can be seen by setting -Djavax.net.debug=all, and then performing an MUA session using the proxy sample server.

Two classes contribute to this problem. Both CounterOutputStream and RedirectingFilterOutputStream fail to extend the write(byte[]) and write(byte[], int, int) methods per J2SE recommendation. This causes the default implementations of those methods in FilterOutputStream to execute, which unwinds the buffer operations into a loop of single-byte write operations, instead of passing the block operation along to the underlying output stream.
1.0.3g 0314 Proxy sample server's ANT script requires classpathref to ssdklib
When an evaluation distribution is used, the Java/src/sample/proxy sample server makes use of the Java/lib/smtp-ssdk.jar library for necessary classes. The build.xml build script is missing a classpathref to this library, and so "ant clean" followed by "ant" results in compilation errors.

Commercial distributions do not have this problem, since classes are resolved from the Java/classes directory, where they are placed by compilation of sources that are available.
1.0.3f 0313 Evaluation distribution missing mailservant packages; sample server won't run
The evaluation distribution does not contain the necessary classes to run the proxy sample server. Performing "ant run" in the Java/src/sample/proxy folder results in a NoClassDefFoundError attempting to locate AuthenticateCapable.

The com.goodserver.mailservant.smtp package name was being obfuscated.
1.0.3e 0311 Connection handler threads need more specific names
Threads created by ConnectionHandlerPool are assigned generic sequential names. They should be given more specific names, like other GoodServer SDK's which incorporate the service short name in the thread prefix, to assist in debugging within a runtime container.
1.0.3e 0310 Acceptor thread doesn't survive OutOfMemoryError
Under low memory conditions, a service's AcceptorThread falls out of its run loop due to an uncaught Error. This results in the termination of network services. This should be enhanced so that recovery from a low memory event is possible, and new connections can be handled.
1.0.3e 0309 TelnetInputStream skipToEOL() fails at start of stream
If TelnetInputStream.skipToEOL() is performed on a newly opened stream, it fails to skip any bytes from the input stream. This is due to a faulty initialization state.
1.0.3e 0259 Network framework consumes 100% cpu
Under certain conditions, the network framework consumes 100% cpu. This has been traced to TelnetInputStream's skipToEOL() method, which reads characters from the input stream until a LF occurs, regardless of whether an end-of-stream occurs in the meanwhile, such as when a client disconnects.

Re-opened due to bug regression. Apparently this bug was never fixed because of a faulty unit test. The unit test TelnetInputStreamUT.testJob0259() method which was used to validate this bug, and to verify its fix, uses skipToEOL() at the beginning of a stream to determine whether that method will hang indefinitely. Bug 0309 has identified a different fault within that method whereby it fails to skip any bytes if it is invoked at the beginning of the stream. The unit test happened to be satisfying that condition, so the test was passing because no attempt was being made to read from the stream at all, since the stream's faulty initialization had it in an end-of-line state.

Re-closed in 1.2.3b.
1.0.3d 0307 STARTTLS handshake error due to socket in client mode
The STARTTLS implementation in the proxy sample server fails when MUA's attempt to handshake. This has been traced to TlsManagerImpl, which creates a layered socket but fails to set it in server mode. The J2SE SSLSocketFactory creates layered sockets that are in client mode by default.
1.0.3c 0298 Buffer overflow exceptions caused by rewind buffer
The new mark/reset capability offered by TelnetInputStream causes buffer overflow exceptions when large content is retrieved through the input stream after a mark is performed.

The rewind buffer should be discarded once it fills up, since it will no longer be able to perform a reset().
1.0.2g 0284 Responses contain extraneous CRLF
Responses to all commands sent by the framework contain a redundant CRLF.
1.0.2g 0283 HELO/EHLO command causes stack overflow
When the framework receives an EHLO or HELO command, the response generation causes a stack overflow due to recursive logic in the SmtpHelloResponseImpl class's write(Writer) method.
1.0.2f 0280 SMTP server response sent incorrectly when no message is set
When a SMTP server or proxy sends a command response in which the message is unset, the response code is not transmitted, resulting in a malformed response.
1.0.2e 0269 SMTP client library fails sending HELO/EHLO argument
The SmtpClient.sendEhlo(String) and sendHelo(String) methods are ignoring the String argument. A code review indicates that this bug was introduced in version 1.0.2b, when the request factory was created as a constructor for requests, including HelloRequest.
1.0.2c 0263 SMTP client library requires ability to set AUTH initial response
The SMTP client library request factory requires the ability to assign a value for the initial response during an AUTH exchange. This accessibility is required when subclassing the SmtpClient class.
1.0.2 0224 SMTP Client Library requires AUTH support
The SmtpClient client library is missing a method to send an AUTH command to the target server, and to then perform the subsequent authenticate handshake.

AUTH support has been implemented in the client library. Two convenience classes are included (AuthenticateLoginClientHandshakeImpl and AuthenticatePlainClientHandshakeImpl), which hide the handshake while offering a convenient constructor that takes (user, pass) arguments. The proxy sample server now implements the AuthenticateCapable interface, and proxies AUTH requests to a target server.
1.0.1c 0221 HELP argument inoperable
The HELP command should support an optional argument, which it does not.

The help command now supports an optional argument, encapsulated by the HelpRequest class.

The SmtpClient client library now supports sendHelp() and sendHelp(String) methods.

The proxy sample server now implements the HelpCapable interface, and delegates HELP commands to target servers.
1.0.1c 0179 PropertiesPreferences fails returning intermediate nodes
The PropertiesPreferences class fails enumerating all nodes for a given dotted property set. The property set ("a", "a.b.c") fails to return a Properties node for the intermediary "a.b" node. A workaround is to create a dummy property "a.b = hack" so that the missing node is created.
1.0.1b 0254 SmtpRecipientRequestImpl loses empty forward path of "<>"
The SmtpRecipientRequestImpl class encapsulates the RCPT TO forward-path argument as a string, but only provides access to this data member with the getAddress() method, which attempts to encapsulate the forward path as a JavaMail InternetAddress. This causes a loss of accessibility to the data when the forward-path is specified as "<>".

The getAddress() method in AddressRequest has been modified to return a String instead of an InternetAddress. SmtpClient has been updated to support String arguments to the sendExpn, sendRcptTo, and sendVrfy methods.
1.0.1 0246 TelnetInputStream should throw DisconnectException instead of returning null
When TelnetInputStream detects a disconnect, it should throw a DisconnectException instead of returning null.
1.0.0h 0244 Server fails to detect client disconnect
Servers and proxies build with the framework fail to detect a client disconnect event. This occurs in the SmtpConnectionHandler.handleCommand() method, when the TelnetInputStream.readLine() method returns null to signal an EOS.
1.0.0g 0241 Session throws NullPointerException during invalidate()
When the Session.invalidate() method is invoked for a session containing no session attributes, a NullPointerException is thrown.

The exception is caused because this class uses lazy allocation of the attribute map, while the invalidate() method assumes that the attribute map is always allocated.
1.0.0e 0229 AUTH type argument parse error; whitespace not ignored
When an AUTH command is received, the auth-type parse fails because the parser does not skip the white space between the command and the first argument. This causes a ProtocolException, which also fails to be sent to the client.
1.0.0e 0228 Input buffer contains CRLF in DATA command handler
When an SMTP connection handler receives a message in the doData command handler, it will typically construct an SMTPInputStream using getInputStream() as the filter stream argument. This input stream contains CRLF as the first two characters in the stream, before the message content. These CRLF characters are the line delimiters for the "DATA" command that has been received.

The framework now performs skipToEOL() on the input stream before any command handlers are invoked that involve continuation.
1.0.0d 0226 AUTH arguments not separated correctly
When an AUTH command is received containing both auth-type and initial-response arguments, these two arguments are not parsed correctly. Instead, they are both assigned as the auth-type argument, while the initial-response argument remains null.

The SmtpSyntaxParser class now contains an authType() parser for RFC 2554 "auth_type" strings.
1.0.0d 0220 MAIL and RCPT optional parameters inoperable
The optional ESMTP parameters to the MAIL FROM: and RCPT TO: commands are currently inoperable, due to a recent command parsing overhaul.
1.0.0d 0016 MAIL command "RET" param not supported
"RET" parameter of the ESMTP MAIL command is not supported yet (RFC 1891).
1.0.0c 0223 SmtpConnectionHandler.getCapabilities() not called by framework
The SmtpConnectionHandler getCapabilities() method is not being called by the framework. This method should be deprecated, since it is no longer in use. In its place, the SmtpMailServant doEhlo and doHelo methods should define a new SmtpHelloResponse response class interface, which provides assignment and accessor methods for an encapsulated list of server capabilities.
1.0.0c 0222 SmtpReply class returns numeric response code
The SmtpReply class currently uses a numeric response code. This should be changed to use a class of type ResponseCode, which can also encapsulate an EnhancedStatusCode.
1.0.0a 0185 Master build script missing from distribution
The master build script (build.xml) is missing from the src/ folder in the distribution zip file.
1.0.0a 0180 Network listener shutdown synchronization errors
Successive rapid init() and destroy() operations for a service with a socket listener and connected clients results in a NullPointerExceptions being throw from TelnetConnectionHandler's shutdown routines. It appears that AcceptorThread is failing to shutdown the connection handler pool, which would provide the necessary shutdown synchronization.
1.0.0 0154 InternetRecipient returns null address
RCPT TO arguments are encapsulated in an InternetRecipient object, which extends the JavaMail InternetAddress class and adds encapsulation for optional RCPT TO arguments. Calling the base class getAddress() method returns null, instead of the RCPT TO internet address argument.

2. Recent New Features

Version Bug Id Title
1.0.6b 0348 Added FlagsHelper.equals convenience method
The FlagsHelper class has been enhanced with a static equals() convenience method capable of comparing two Flags references.
1.0.6b 0347 Added FolderHelper.equals convenience method
The FolderHelper class has been enhanced with a static equals() convenience method capable of comparing two javax.mail.Folder references.
1.0.6b 0346 Added InternetAddressHelper.equals convenience method
The InternetAddressHelper class has been enhanced with a static equals() convenience method capable of comparing two InternetAddress references.
1.0.6b 0344 Added remaining() convenience method to PathIterator
The PathIterator class provides a convenient way to break a folder path into composite parts.

A remaining() method is now available, simplifying access to the remaining portion of the path that has not yet been tokenized. For the path "a/b/c/d", the first call to pathIterator.next() returns "a", and a subsequent call to pathIterator.remaining() returns "b/c/d".
1.0.5a 0337 JAR now includes manifest
The smtp-ssdk.jar distribution now contains a manifest file, and version information.
1.0.5 0331 Internal representation overhaul in preparation for 8-bit support
Merge of IMAP4 Server SDK 1.2.5.

All classes encapsulating elements of the protocol exchange have been overhauled to prepare the framework for international 8bit string support. 152 files have been touched.

1. Many data elements previously represented as a String are now represented as byte[].
2. All write(Writer) methods have been replaced with write(OutputStream).
3. Parsers return byte[] instead of String.
4. Parsers and streams now operate internally using int's instead of chars or bytes.
5. Many instances of StringHelper.equalsIgnoreCase replaced with ByteArrayHelper.equalsIgnoreCase.
6. Conversion of ASCII String to byte[] is performed by a new ByteArrayHelper.toAsciiString function.
1.0.4c 0327 Merge IMAP4 Server SDK 1.2.4
Maintenance release incorporating shared library changes in the IMAP4 Server SDK version 1.2.4.
1.0.4a 0318 Default TLS manager requires more flexibility with custom KeyManagerFactory
The current TlsManagerImpl TLS manager currently contains logic that is specific to the J2SE's default KeyManagerFactory. Specifically, the current logic does not support cases where one may wish to specify a provider, without having the framework load the keystore.
1.0.3b 0297 Merge IMAP4 Server SDK 1.2.2d
Maintenance release incorporating shared library changes in the IMAP4 Server SDK version 1.2.2d.

1. TelnetInputStream mark()/reset() implementation.
1.0.3a 0291 Proxy sample server now implements STARTTLS
The proxy sample server now supports the STARTTLS command. It configures the SMTP client library to perform the STARTTLS command with disregard to local keystores (a "trust all certificates" mode), which satisfies the purposes of a sample server and prevents pre-configuration.
1.0.3a 0289 TLS manager enhancements
The default TLS manager implementation (TlsManagerImpl) has been enhanced with the following new features:

1. The default keystore is now supported, and is used when the ServicePropertyNames.TLS_KEYSTORE_LOCATION property is left null.

2. A new property ServicePropertyNames.TLS_TRUST_ALL_CERTS, when set to "true", indicates to the SSL socket factory that during a server-initiated certificate handshake, it should accept any and all certificates. This property causes local keystores to be ignored.
1.0.3 0288 STARTTLS support in SMTP client library
Support for STARTTLS has been added to the SmtpClient client library. Invoking startTls() sends a STARTTLS request. If the server responds with a positive response, then the TLS handshake is performed, and all further communications are secured.
1.0.3 0285 Support for pluggable TLS manager
Server implementations may now use custom TLS manager classes, to govern keystore and STARTTLS operations in a custom way.

1. The TlsManager class is now an interface, and a default TlsManagerImpl implementation is provided.

2. A specific TLS manager class may be used in a service startup (Service.init(Preferences)) by setting the ServicePropertyNames.TLS_MANAGER property with the class name.
1.0.2d 0265 SMTP client library requires support for Rcpt-parameters during RCPT command
The SmtpClient client library requires the ability to specify Rcpt-parameters (RFC2821) to the sendRcptTo() method.
1.0.2d 0264 SMTP client library requires support for Mail-parameters during MAIL command
The SmtpClient client library requires the ability to specify Mail-parameters (RFC2821) to the sendMailFrom() method.
1.0.2b 0262 New SMTP client library request factory
A new request factory class has been added to the SMTP client library, so that inheritance-based customizations may be performed.
1.0.2a 0258 The SmtpClient SocketClient member variable should be protected
The SmtpClient client library's aClient member variable (SocketClient) should be protected instead of private, for extensibility purposes.
1.0.1a 0251 Performance enhancement for block network operations
TelnetInputStream has improved performance during block network read operations. Data read from the network is now transferred directly into a final buffer, instead of an intermediate buffer followed by a copy.
1.0.1 0248 SmtpRequest now provides access to socket info
The SmtpRequest interface has been updated to specify the SocketRequest interface. The SMTP container (@link com.goodserver.server.smtp) has been updated, and implements accessors for the data elements specified by the SocketRequest interface.
1.0.0g 0240 SMTP ResponseCode requires constant for 535 (RFC2554)
RFC 2554 defines an error code 535 for use when a server rejects authentication data. The ResponseCode class should define a constant for this value.
1.0.0f 0233 Added SMTP STARTTLS support
The framework now supports the STARTTLS extension command. Connection handler classes that implement the new StartTlsCapable interface will have that command handler invoked when the STARTTLS command is received.
1.0.0b 0204 SMTP client library update
The SmtpClient client library has been updated to be syntactically compatible with the IMAP client library in the IMAP4 Server SDK 1.1.9.

A new isConnected() method returns the state of the underlying socket client. Two new parsers are available: AbnfParser and SmtpParser.
1.0.0a 0181 Configuration files accessed via ConfFile now allow macros
The ConfFile class now supports ANT-style macros in property values. The property "name=${java.home}" now assigns a property with "name" as the key, and the value of the "java.home" system property as the value.
1.0.0a 0164 Added JMX support and JBoss runtime container
The GoodServer network service class ServiceBase now publishes its management interface via JMX. A JBoss runtime container is also provided (JBossService). ServiceBase implementations can now be deployed to JBoss using the provided runtime container.
1.0.0a 0160 Incorporate JavaMail 1.3.1 library
The frameworks now incorporate and redistribute JavaMail 1.3.1.
1.0.0a 0159 Incorporate JAF 1.0.2 library
The frameworks now incorporate and redistribute Java Activation Framework (JAF) 1.0.2.
1.0.0 0156 New network service property format
The default network service container (ServiceBase) has been overhauled to read endpoints from the service configuration. Prior to this version, endpoints were initialized programmatically using the ServiceBase.initAcceptorThread() method.

Configuration files for the sample servers have been updated to reflect the change. A new "handler" property now defines the ConnectionHandler class instance to instantiate for the given endpoint.
1.0.0 0153 Version 1.0 Release
Version 1.0 released. The 0.9 branch (Beta) is now closed.

This is an official version 1.0 release, even though there are several production implementations out there based on the 0.9 (Beta) branch.

This release incorporates the following features from the mainline code branch:
o Libraries are now based on J2SE 1.4.
o Logging is now J2SE based. IBM JLog has been deprecated. The old logging channels ("serverlog", "protocollog", etc) are deprecated, and components now log to their class name. No logging setup is performed by the containers, so configuration is now completely manageable by a customer and their special container requirements.
o Configuration is now based on Preferences instead of Properties, so subcomponents are able to listen for configuration changes and reconfigure themselves. This was an important prerequisite for adding future JMX support.
o The stateful SMTP connection handler functionality has been removed. The framework is now strictly abstract, allowing any "flavor" of SMTP server or proxy to be created.
o The smtp package has been introduced, which defines (in a completely abstract form) the SMTP protocol exchange. The smtp package is now called a "container", and is considered a default container implementation.

3. Known Problems (Open Bugs)

Bug Id Title

4. Needed Features (Open Features)

Bug Id Title
0122 Exceeding concurrent sessions should be more user-friendly
When connecting to a server where the number of concurrent sessions is at the maximum, the client receives no greeting response. The OS connects the client through the TCP/IP backlog feature, but it is not assigned to a socket (session) until a session frees up. The client should see a greeting response, possibily informing them that the server is currently too busy to handle their connection.
0123 Rfc822DateHelper should handle missing time
Rfc822DateHelper should be able to parse dates that are missing the time part.

5. All Bugs

See separate Bug List document.

6. Supported Standards

Document

Since

Description

Comments

RFC 1651

1.0.0

SMTP Service Extensions

Specifies the method for servers to declare what service extensions they support.

RFC 1845

1.0.0

CHECKPOINT Extension

Specifies a mechanism for restarting previously failed partial deliveries.

RFC 1870

1.0.0

Message Size Declaration Extension

Specifies a mechanism whereby SMTP senders can declare the size of a message before transmittal, enabling early refusal.

RFC 1891

1.0.0

Delivery Status Notification Extension

Specifies DSN mechanism.

RFC 1893

1.0.0

Enhanced Status Codes

Enhanced status codes defined.

RFC 2034

1.0.0

Returning Enhanced Error Codes

Enhanced status (error) codes defined during the SMTP protocol exchange.

RFC 2197

1.0.0

Command Pipelining Extension

Specifies command pipelining support.

RFC 2554

1.0.0

Authentication Extension

Specifies how authentication extension mechanisms are to function.

RFC 2821

1.0.0

SMTP

April 2001 update to the RFC 821 specification.

7. Redistributed Code

The following packages have been redistributed in accordance with their respective license agreements.

8. Contacting GoodServer

Send e-mail to support@goodserver.com with your feedback, suggestions, or coding issues.