things.data.transport.smtp
Class FancySMTPClient

java.lang.Object
  extended by things.data.transport.smtp.FancySMTPClient
All Implemented Interfaces:
Debuggable, StringPoster, SMTPClient

public class FancySMTPClient
extends java.lang.Object
implements SMTPClient, Debuggable

This is a fancy SMTP client. It expected the server to supposed extensions

The client will propagate any InterruptedExceptions like a good THINGs citizen, though it will then mark the client as BAD and it will no longer work--through exceptions for any call thereafter.

Version:
1.0

Version History

EPG - Added by request - 1 JUNV 09
 
Author:
Erich P. Gatejen

Field Summary
static int CONNECTION_RETRIES
           
static int CONNECTION_TIMEOUT
           
static java.lang.String EXTENSION_DSN
          Extension names.
 
Fields inherited from interface things.data.transport.smtp.SMTPClient
ACTION_ABORTED, ACTION_NOT_TAKEN, ACTION_OK, BAD_COMMAND_SEQUENCE, CODE_211, CODE_214, CODE_215, CODE_220, CODE_221, CODE_250, CODE_251, CODE_354, CODE_421, CODE_450, CODE_451, CODE_452, CODE_500, CODE_501, CODE_502, CODE_503, CODE_504, CODE_550, CODE_551, CODE_552, CODE_553, CODE_554, CODE_FAIL_THRESHOLD, COMMAND_NOT_IMPLEMENTED, COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER, HELP_MESSAGE, INSUFFICIENT_STORAGE, MAILBOX_NAME_NOT_ALLOWED, MAILBOX_UNAVAILABLE, SERVICE_CLOSING_TRANSMISSION_CHANNEL, SERVICE_NOT_AVAILABLE, SERVICE_READY, START_MAIL_INPUT, STORAGE_ALLOCATION_EXCEEDED, SYNTAX_ERROR_IN_ARGUMENTS, SYSTEM_STATUS, TRANSACTION_FAILED, UNRECOGNIZED_COMMAND, USER_NOT_LOCAL, USER_NOT_LOCAL_WILL_FORWARD
 
Constructor Summary
FancySMTPClient(Logger theLogger)
          Create a new client.
FancySMTPClient(Logger theLogger, java.lang.String name)
          Create a new client with an imposed name.
 
Method Summary
 Reply connect(java.lang.String connectAddress, int connectPort)
          Start a connection.
 void debuggingOff()
          Turn debugging off.
 void debuggingOn()
          Turn debugging on.
 boolean debuggingState()
          Get the current debugging SMTPSMTPState.
 Reply disconnect()
          Start a connection.
 Reply done()
          Quit the client.
 boolean extensionPresent(java.lang.String extensionName)
          Is a named extension present?
 void flush()
          Try to flush.
 java.lang.String getName()
          Get client name.
 SMTPState getState()
          Get the SMTPState.
 Reply login(java.lang.String hostname)
          HELO with the hostname--no authentication.
 void post(java.lang.String message)
          Post as a message.
 void postit(java.lang.String message)
          Post as a message.
 Reply recipient(java.lang.String recipientText)
          Set the recipient using RCPT TO.
 Reply recipient(java.lang.String recipientText, DSN dsn)
          Set the recipient using RCPT TO.
 Reply reset()
          RESET the connection.
 Reply sendData(java.io.InputStream... ios)
          Send DATA.
 Reply sender(java.lang.String senderText)
          Set the sender using MAIL FROM.
 Reply sender(java.lang.String senderText, DSN dsn)
          Set the sender using MAIL FROM.
 void setSocketRetries(int retries)
          Number of times a socket read will be retried after a timeout before completely giving up.
The default value is CONNECTION_RETRIES.
 void setTimeout(int timeout)
          Set the socket timeout for each connection.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CONNECTION_TIMEOUT

public static final int CONNECTION_TIMEOUT
See Also:
Constant Field Values

CONNECTION_RETRIES

public static final int CONNECTION_RETRIES
See Also:
Constant Field Values

EXTENSION_DSN

public static final java.lang.String EXTENSION_DSN
Extension names.

See Also:
Constant Field Values
Constructor Detail

FancySMTPClient

public FancySMTPClient(Logger theLogger,
                       java.lang.String name)
Create a new client with an imposed name. This will not connect.

Parameters:
theLogger - the logger to use. It will be quiet unless you start debugging.
name - the client's name. It will be slightly altered for uniqueness.

FancySMTPClient

public FancySMTPClient(Logger theLogger)
Create a new client. This will not connect.

Parameters:
theLogger - the logger to use. It will be quiet unless you start debugging.
Method Detail

getName

public java.lang.String getName()
Get client name.

Specified by:
getName in interface SMTPClient
Returns:
the clients name.

getState

public SMTPState getState()
Get the SMTPState.

Specified by:
getState in interface SMTPClient
Returns:
State

setTimeout

public void setTimeout(int timeout)
Set the socket timeout for each connection. A timeout may be retried, depending on the value set with setSocketRetries(int).
The default value is CONNECTION_TIMEOUT.

It will take effect whenever a new connection is established.

Specified by:
setTimeout in interface SMTPClient
Parameters:
timeout - the timeout in milliseconds.

setSocketRetries

public void setSocketRetries(int retries)
Number of times a socket read will be retried after a timeout before completely giving up.
The default value is CONNECTION_RETRIES.

It will take effect whenever a new operation is started.

Specified by:
setSocketRetries in interface SMTPClient
Parameters:
retries - Number of retries. Zero or a negative number is the same as no retries.

connect

public Reply connect(java.lang.String connectAddress,
                     int connectPort)
              throws ThingsException,
                     java.lang.InterruptedException
Start a connection. Return a code. It will throw an ERROR is already connect, but will leave the connection intact.

Specified by:
connect in interface SMTPClient
Parameters:
connectAddress -
connectPort -
Returns:
ACTION_OK if it was ok.
Throws:
ThingsException - will always be fatal at this point.
java.lang.InterruptedException

disconnect

public Reply disconnect()
                 throws ThingsException,
                        java.lang.InterruptedException
Start a connection. Return a code.

Specified by:
disconnect in interface SMTPClient
Returns:
The reply.
Throws:
ThingsException - which will never happen, since we'll just abandon the bad connection.
java.lang.InterruptedException

login

public Reply login(java.lang.String hostname)
            throws ThingsException,
                   java.lang.InterruptedException
HELO with the hostname--no authentication. A state problem will cause a FAULT. A transmission problem is just an ERROR. It will transition to LOGIN_COMPLETE only of the reply is an ACTION_OK.

Specified by:
login in interface SMTPClient
Parameters:
hostname -
Returns:
the reply.
Throws:
ThingsException
java.lang.InterruptedException

sender

public Reply sender(java.lang.String senderText)
             throws ThingsException,
                    java.lang.InterruptedException
Set the sender using MAIL FROM. It must be at LOGIN_COMPLETE.

Specified by:
sender in interface SMTPClient
Parameters:
senderText - as a valid SMTP address.
Returns:
A reply.
Throws:
ThingsException - if not ready for MAIL FROM or actual transmission problem.
java.lang.InterruptedException

sender

public Reply sender(java.lang.String senderText,
                    DSN dsn)
             throws ThingsException,
                    java.lang.InterruptedException
Set the sender using MAIL FROM. It must be at LOGIN_COMPLETE.

Specified by:
sender in interface SMTPClient
Parameters:
senderText - as a valid SMTP address.
dsn - command. If null, it will be ignored.
Returns:
A reply.
Throws:
ThingsException - if not ready for MAIL FROM or actual transmission problem.
java.lang.InterruptedException

recipient

public Reply recipient(java.lang.String recipientText)
                throws ThingsException,
                       java.lang.InterruptedException
Set the recipient using RCPT TO. It must be at MAILFROM_DONE.

Specified by:
recipient in interface SMTPClient
Parameters:
recipientText - as a valid SMTP address.
Returns:
A reply.
Throws:
ThingsException - if not ready for RCPT TO or actual transmission problem.
java.lang.InterruptedException

recipient

public Reply recipient(java.lang.String recipientText,
                       DSN dsn)
                throws ThingsException,
                       java.lang.InterruptedException
Set the recipient using RCPT TO. It must be at MAILFROM_DONE.

Specified by:
recipient in interface SMTPClient
Parameters:
recipientText - as a valid SMTP address.
dsn - command. If null, it will be ignored.
Returns:
A reply.
Throws:
ThingsException - if not ready for RCPT TO or actual transmission problem.
java.lang.InterruptedException

reset

public Reply reset()
            throws ThingsException,
                   java.lang.InterruptedException
RESET the connection. This will return the state to LOGIN_COMPLETE, as long as it has already been logged in.

Specified by:
reset in interface SMTPClient
Returns:
the reply.
Throws:
ThingsException - if the connection is made and logged in.
java.lang.InterruptedException

sendData

public Reply sendData(java.io.InputStream... ios)
               throws ThingsException,
                      java.lang.InterruptedException
Send DATA. It must be at RCPTTO_DONE. It will do the appropriate dot doubling and CRLF management.

Specified by:
sendData in interface SMTPClient
Parameters:
ios - Stream to send. You handle any buffering. Null entries are allowed and ignored.
Returns:
the reply
Throws:
ThingsException
java.lang.InterruptedException

done

public Reply done()
           throws ThingsException,
                  java.lang.InterruptedException
Quit the client. This will return it to FRESH. It will never throw an exception, but may return a bad reply.

Specified by:
done in interface SMTPClient
Returns:
a reply
Throws:
ThingsException
java.lang.InterruptedException

extensionPresent

public boolean extensionPresent(java.lang.String extensionName)
Is a named extension present?

Parameters:
extensionName -
Returns:
true if the named extension is present.

debuggingOn

public void debuggingOn()
Turn debugging on. Logs with debug level priority will be passed.

Specified by:
debuggingOn in interface Debuggable

debuggingOff

public void debuggingOff()
Turn debugging off. Logs with debug level priority will not be passed.

Specified by:
debuggingOff in interface Debuggable

debuggingState

public boolean debuggingState()
Get the current debugging SMTPSMTPState.

Specified by:
debuggingState in interface Debuggable
Returns:
debugging state

post

public void post(java.lang.String message)
          throws ThingsException
Post as a message.

Specified by:
post in interface StringPoster
Parameters:
message - String to post
Throws:
ThingsException

postit

public void postit(java.lang.String message)
Post as a message. Best effort. Ignore errors.

Specified by:
postit in interface StringPoster
Parameters:
message - String to post

flush

public void flush()
Try to flush. Never error no matter what.

Specified by:
flush in interface StringPoster


Things.