You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2006/04/01 00:24:56 UTC
svn commit: r390524 [6/7] - in
/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail:
authentication/ store/nntp/ store/nntp/newsrc/ store/pop3/
store/pop3/message/ store/pop3/response/ transport/nntp/ transport/smtp/
util/
Modified: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java?rev=390524&r1=390523&r2=390524&view=diff
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java (original)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java Fri Mar 31 14:24:52 2006
@@ -49,32 +49,25 @@
import org.apache.geronimo.javamail.authentication.DigestMD5Authenticator;
import org.apache.geronimo.javamail.authentication.LoginAuthenticator;
import org.apache.geronimo.javamail.authentication.PlainAuthenticator;
-import org.apache.geronimo.javamail.authentication.PlainAuthenticator;
-import org.apache.geronimo.mail.util.Base64;
-import org.apache.geronimo.mail.util.XText;
-
import org.apache.geronimo.javamail.util.MIMEOutputStream;
import org.apache.geronimo.javamail.util.TraceInputStream;
import org.apache.geronimo.javamail.util.TraceOutputStream;
+import org.apache.geronimo.mail.util.Base64;
+import org.apache.geronimo.mail.util.XText;
/**
- * Simple implementation of SMTP transport. Just does plain RFC821-ish
- * delivery.
- * <p/>
- * Supported properties :
- * <p/>
+ * Simple implementation of SMTP transport. Just does plain RFC821-ish delivery.
+ * <p/> Supported properties : <p/>
* <ul>
- * <li> mail.host : to set the server to deliver to. Default = localhost</li>
- * <li> mail.smtp.port : to set the port. Default = 25</li>
+ * <li> mail.host : to set the server to deliver to. Default = localhost</li>
+ * <li> mail.smtp.port : to set the port. Default = 25</li>
* <li> mail.smtp.locahost : name to use for HELO/EHLO - default getHostName()</li>
* </ul>
- * <p/>
- * There is no way to indicate failure for a given recipient (it's possible to have a
- * recipient address rejected). The sun impl throws exceptions even if others successful),
- * but maybe we do a different way...
- * <p/>
- * TODO : lots. ESMTP, user/pass, indicate failure, etc...
- *
+ * <p/> There is no way to indicate failure for a given recipient (it's possible
+ * to have a recipient address rejected). The sun impl throws exceptions even if
+ * others successful), but maybe we do a different way... <p/> TODO : lots.
+ * ESMTP, user/pass, indicate failure, etc...
+ *
* @version $Rev$ $Date$
*/
public class SMTPTransport extends Transport {
@@ -83,97 +76,148 @@
* constants for EOL termination
*/
protected static final char CR = '\r';
+
protected static final char LF = '\n';
/**
* property keys for top level session properties.
*/
protected static final String MAIL_LOCALHOST = "mail.localhost";
- protected static final String MAIL_SSLFACTORY_CLASS = "mail.SSLSocketFactory.class";
+ protected static final String MAIL_SSLFACTORY_CLASS = "mail.SSLSocketFactory.class";
/**
- * property keys for protocol properties. The actual property name will
- * be appended with "mail." + protocol + ".", where the protocol is either
+ * property keys for protocol properties. The actual property name will be
+ * appended with "mail." + protocol + ".", where the protocol is either
* "smtp" or "smtps".
*/
protected static final String MAIL_SMTP_AUTH = "auth";
+
protected static final String MAIL_SMTP_PORT = "port";
+
protected static final String MAIL_SMTP_LOCALHOST = "localhost";
+
protected static final String MAIL_SMTP_TIMEOUT = "timeout";
+
protected static final String MAIL_SMTP_SASL_REALM = "sasl.realm";
+
protected static final String MAIL_SMTP_TLS = "starttls.enable";
+
protected static final String MAIL_SMTP_FACTORY_CLASS = "socketFactory.class";
+
protected static final String MAIL_SMTP_FACTORY_FALLBACK = "socketFactory.fallback";
+
protected static final String MAIL_SMTP_FACTORY_PORT = "socketFactory.port";
+
protected static final String MAIL_SMTP_REPORT_SUCCESS = "reportsuccess";
+
protected static final String MAIL_SMTP_STARTTLS_ENABLE = "starttls.enable";
+
protected static final String MAIL_SMTP_DSN_NOTIFY = "dsn.notify";
+
protected static final String MAIL_SMTP_SENDPARTIAL = "sendpartial";
+
protected static final String MAIL_SMTP_LOCALADDRESS = "localaddress";
+
protected static final String MAIL_SMTP_LOCALPORT = "localport";
+
protected static final String MAIL_SMTP_QUITWAIT = "quitwait";
+
protected static final String MAIL_SMTP_FROM = "from";
+
protected static final String MAIL_SMTP_DSN_RET = "dsn.ret";
+
protected static final String MAIL_SMTP_SUBMITTER = "submitter";
+
protected static final String MAIL_SMTP_EXTENSION = "mailextension";
+
protected static final String MAIL_SMTP_EHLO = "ehlo";
- protected static final String MAIL_SMTP_ENCODE_TRACE = "encodetrace";
+ protected static final String MAIL_SMTP_ENCODE_TRACE = "encodetrace";
protected static final int MIN_MILLIS = 1000 * 60;
+
protected static final int TIMEOUT = MIN_MILLIS * 5;
+
protected static final String DEFAULT_MAIL_HOST = "localhost";
+
protected static final int DEFAULT_MAIL_SMTP_PORT = 25;
+
protected static final int DEFAULT_MAIL_SMTPS_PORT = 465;
// SMTP reply codes
protected static final int SERVICE_READY = 220;
+
protected static final int SERVICE_CLOSING = 221;
+
protected static final int AUTHENTICATION_COMPLETE = 235;
+
protected static final int COMMAND_ACCEPTED = 250;
+
protected static final int ADDRESS_NOT_LOCAL = 251;
protected static final int AUTHENTICATION_CHALLENGE = 334;
+
protected static final int START_MAIL_INPUT = 354;
protected static final int SERVICE_NOT_AVAILABLE = 421;
+
protected static final int MAILBOX_BUSY = 450;
+
protected static final int PROCESSING_ERROR = 451;
+
protected static final int INSUFFICIENT_STORAGE = 452;
protected static final int COMMAND_SYNTAX_ERROR = 500;
+
protected static final int PARAMETER_SYNTAX_ERROR = 501;
+
protected static final int COMMAND_NOT_IMPLEMENTED = 502;
+
protected static final int INVALID_COMMAND_SEQUENCE = 503;
+
protected static final int COMMAND_PARAMETER_NOT_IMPLEMENTED = 504;
+
protected static final int MAILBOX_NOT_FOUND = 550;
+
protected static final int USER_NOT_LOCAL = 551;
+
protected static final int MAILBOX_FULL = 552;
+
protected static final int INVALID_MAILBOX = 553;
+
protected static final int TRANSACTION_FAILED = 553;
protected static final String AUTHENTICATION_PLAIN = "PLAIN";
+
protected static final String AUTHENTICATION_LOGIN = "LOGIN";
+
protected static final String AUTHENTICATION_CRAMMD5 = "CRAM-MD5";
+
protected static final String AUTHENTICATION_DIGESTMD5 = "DIGEST-MD5";
- // the protocol we're working with. This will be either "smtp" or "smtps".
+ // the protocol we're working with. This will be either "smtp" or "smtps".
protected String protocol;
+
// the target host
protected String host;
- // the default port to use for this protocol (differs between "smtp" and "smtps").
+
+ // the default port to use for this protocol (differs between "smtp" and
+ // "smtps").
protected int defaultPort;
+
// the target server port.
protected int port;
- // the connection socket...can be a plain socket or SSLSocket, if TLS is being used.
+ // the connection socket...can be a plain socket or SSLSocket, if TLS is
+ // being used.
protected Socket socket;
// our local host name
protected String localHost;
- // input stream used to read data. If Sasl is in use, this might be other than the
+ // input stream used to read data. If Sasl is in use, this might be other
+ // than the
// direct access to the socket input stream.
protected InputStream inputStream;
@@ -182,24 +226,30 @@
// list of authentication mechanisms supported by the server
protected HashMap serverAuthenticationMechanisms;
+
// map of server extension arguments
protected HashMap serverExtensionArgs;
// do we report success after completion of each mail send.
protected boolean reportSuccess;
+
// does the server support transport level security?
protected boolean serverTLS = false;
+
// is TLS enabled on our part?
protected boolean useTLS = false;
+
// do we use SSL for our initial connection?
protected boolean sslConnection = false;
-
// the username we connect with
protected String username;
+
// the authentication password.
protected String password;
- // the target SASL realm (normally null unless explicitly set or we have an authentication mechanism that
+
+ // the target SASL realm (normally null unless explicitly set or we have an
+ // authentication mechanism that
// requires it.
protected String realm;
@@ -209,38 +259,40 @@
// our session provided debug output stream.
protected PrintStream debugStream;
-
/**
- * Normal constructor for an SMTPTransport() object. This
- * constructor is used to build a transport instance for the
- * "smtp" protocol.
- *
- * @param session The attached session.
- * @param name An optional URLName object containing target information.
+ * Normal constructor for an SMTPTransport() object. This constructor is
+ * used to build a transport instance for the "smtp" protocol.
+ *
+ * @param session
+ * The attached session.
+ * @param name
+ * An optional URLName object containing target information.
*/
public SMTPTransport(Session session, URLName name) {
this(session, name, "smtp", DEFAULT_MAIL_SMTP_PORT, false);
}
/**
- * Common constructor used by the SMTPTransport and SMTPSTransport
- * classes to do common initialization of defaults.
- *
- * @param session The host session instance.
- * @param name The URLName of the target.
- * @param protocol The protocol type (either "smtp" or "smtps". This helps us
- * in retrieving protocol-specific session properties.
+ * Common constructor used by the SMTPTransport and SMTPSTransport classes
+ * to do common initialization of defaults.
+ *
+ * @param session
+ * The host session instance.
+ * @param name
+ * The URLName of the target.
+ * @param protocol
+ * The protocol type (either "smtp" or "smtps". This helps us in
+ * retrieving protocol-specific session properties.
* @param defaultPort
- * The default port used by this protocol. For "smtp", this
- * will be 25. The default for "smtps" is 465.
+ * The default port used by this protocol. For "smtp", this will
+ * be 25. The default for "smtps" is 465.
* @param sslConnection
- * Indicates whether an SSL connection should be used to initial
- * contact the server. This is different from the STARTTLS
- * support, which switches the connection to SSL after the
- * initial startup.
+ * Indicates whether an SSL connection should be used to initial
+ * contact the server. This is different from the STARTTLS
+ * support, which switches the connection to SSL after the
+ * initial startup.
*/
- protected SMTPTransport(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection)
- {
+ protected SMTPTransport(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
super(session, name);
this.protocol = protocol;
@@ -258,13 +310,12 @@
System.out.println("Debug value in transport = " + debug);
}
-
/**
- * Connect to a server using an already created socket. This
- * connection is just like any other connection, except we will
- * not create a new socket.
- *
- * @param socket The socket connection to use.
+ * Connect to a server using an already created socket. This connection is
+ * just like any other connection, except we will not create a new socket.
+ *
+ * @param socket
+ * The socket connection to use.
*/
public void connect(Socket socket) throws MessagingException {
this.socket = socket;
@@ -272,39 +323,47 @@
}
/**
- * Do the protocol connection for an SMTP transport. This
- * handles server authentication, if possible. Returns false if
- * unable to connect to the server.
- *
- * @param host The target host name.
- * @param port The server port number.
- * @param user The authentication user (if any).
- * @param password The server password. Might not be sent directly if more
- * sophisticated authentication is used.
- *
- * @return true if we were able to connect to the server properly, false
- * for any failures.
+ * Do the protocol connection for an SMTP transport. This handles server
+ * authentication, if possible. Returns false if unable to connect to the
+ * server.
+ *
+ * @param host
+ * The target host name.
+ * @param port
+ * The server port number.
+ * @param user
+ * The authentication user (if any).
+ * @param password
+ * The server password. Might not be sent directly if more
+ * sophisticated authentication is used.
+ *
+ * @return true if we were able to connect to the server properly, false for
+ * any failures.
* @exception MessagingException
*/
- protected boolean protocolConnect(String host, int port, String username, String password) throws MessagingException
- {
+ protected boolean protocolConnect(String host, int port, String username, String password)
+ throws MessagingException {
if (debug) {
debugOut("Connecting to server " + host + ":" + port + " for user " + username);
}
- // first check to see if we need to authenticate. If we need this, then we must have a username and
- // password specified. Failing this may result in a user prompt to collect the information.
+ // first check to see if we need to authenticate. If we need this, then
+ // we must have a username and
+ // password specified. Failing this may result in a user prompt to
+ // collect the information.
boolean mustAuthenticate = isProtocolPropertyTrue(MAIL_SMTP_AUTH);
- // if we need to authenticate, and we don't have both a userid and password, then we fail this
- // immediately. The Service.connect() method will try to obtain the user information and retry the
+ // if we need to authenticate, and we don't have both a userid and
+ // password, then we fail this
+ // immediately. The Service.connect() method will try to obtain the user
+ // information and retry the
// connection one time.
if (mustAuthenticate && (username == null || password == null)) {
return false;
}
-
- // if the port is defaulted, then see if we have something configured in the session.
+ // if the port is defaulted, then see if we have something configured in
+ // the session.
// if not configured, we just use the default default.
if (port == -1) {
// take the default first.
@@ -315,7 +374,6 @@
}
}
-
try {
// create socket and connect to server.
@@ -349,10 +407,12 @@
/**
* Send a message to multiple addressees.
- *
- * @param message The message we're sending.
- * @param addresses An array of addresses to send to.
- *
+ *
+ * @param message
+ * The message we're sending.
+ * @param addresses
+ * An array of addresses to send to.
+ *
* @exception MessagingException
*/
public void sendMessage(Message message, Address[] addresses) throws MessagingException {
@@ -364,7 +424,8 @@
throw new MessagingException("Null message");
}
- // SMTP only handles instances of MimeMessage, not the more general message case.
+ // SMTP only handles instances of MimeMessage, not the more general
+ // message case.
if (!(message instanceof MimeMessage)) {
throw new MessagingException("SMTP can only send MimeMessages");
}
@@ -376,26 +437,26 @@
boolean haveGroup = false;
- // enforce the requirement that all of the targets are InternetAddress instances.
+ // enforce the requirement that all of the targets are InternetAddress
+ // instances.
for (int i = 0; i < addresses.length; i++) {
if (addresses[i] instanceof InternetAddress) {
- // and while we're here, see if we have a groups in the address list. If we do, then
+ // and while we're here, see if we have a groups in the address
+ // list. If we do, then
// we're going to need to expand these before sending.
- if (((InternetAddress)addresses[i]).isGroup()) {
+ if (((InternetAddress) addresses[i]).isGroup()) {
haveGroup = true;
}
- }
- else {
+ } else {
throw new MessagingException("Illegal InternetAddress " + addresses[i]);
}
}
- // did we find a group? Time to expand this into our full target list.
+ // did we find a group? Time to expand this into our full target list.
if (haveGroup) {
addresses = expandGroups(addresses);
}
-
SendStatus[] stats = new SendStatus[addresses.length];
// create our lists for notification and exception reporting.
@@ -404,10 +465,10 @@
Address[] invalid = null;
try {
- // send sender first. If this failed, send a failure notice of the event, using the full list of
+ // send sender first. If this failed, send a failure notice of the
+ // event, using the full list of
// addresses as the unsent, and nothing for the rest.
- if (!sendMailFrom(message))
- {
+ if (!sendMailFrom(message)) {
unsent = addresses;
sent = new Address[0];
invalid = new Address[0];
@@ -417,58 +478,61 @@
// include the reponse information here.
SMTPReply last = lastServerResponse;
// now send an "uber-exception" to indicate the failure.
- throw new SMTPSendFailedException("MAIL FROM", last.getCode(), last.getMessage(), null, sent, unsent, invalid);
+ throw new SMTPSendFailedException("MAIL FROM", last.getCode(), last.getMessage(), null, sent, unsent,
+ invalid);
}
String dsn = null;
- // there's an optional notification argument that can be added to MAIL TO. See if we've been
+ // there's an optional notification argument that can be added to
+ // MAIL TO. See if we've been
// provided with one.
// an SMTPMessage object is the first source
if (message instanceof SMTPMessage) {
// get the notification options
- int options = ((SMTPMessage)message).getNotifyOptions();
+ int options = ((SMTPMessage) message).getNotifyOptions();
switch (options) {
- // a zero value indicates nothing is set.
- case 0:
- break;
-
- case SMTPMessage.NOTIFY_NEVER:
- dsn = "NEVER";
- break;
-
- case SMTPMessage.NOTIFY_SUCCESS:
- dsn = "SUCCESS";
- break;
-
- case SMTPMessage.NOTIFY_FAILURE:
- dsn = "FAILURE";
- break;
-
- case SMTPMessage.NOTIFY_DELAY:
- dsn = "DELAY";
- break;
-
- // now for combinations...there are few enough combinations here
- // that we can just handle this in the switch statement rather than have to
- // concatentate everything together.
- case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE):
- dsn = "SUCCESS,FAILURE";
- break;
-
- case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_DELAY):
- dsn = "SUCCESS,DELAY";
- break;
-
- case (SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
- dsn = "FAILURE,DELAY";
- break;
-
- case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
- dsn = "SUCCESS,FAILURE,DELAY";
- break;
+ // a zero value indicates nothing is set.
+ case 0:
+ break;
+
+ case SMTPMessage.NOTIFY_NEVER:
+ dsn = "NEVER";
+ break;
+
+ case SMTPMessage.NOTIFY_SUCCESS:
+ dsn = "SUCCESS";
+ break;
+
+ case SMTPMessage.NOTIFY_FAILURE:
+ dsn = "FAILURE";
+ break;
+
+ case SMTPMessage.NOTIFY_DELAY:
+ dsn = "DELAY";
+ break;
+
+ // now for combinations...there are few enough combinations here
+ // that we can just handle this in the switch statement rather
+ // than have to
+ // concatentate everything together.
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE):
+ dsn = "SUCCESS,FAILURE";
+ break;
+
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_DELAY):
+ dsn = "SUCCESS,DELAY";
+ break;
+
+ case (SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
+ dsn = "FAILURE,DELAY";
+ break;
+
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
+ dsn = "SUCCESS,FAILURE,DELAY";
+ break;
}
}
@@ -477,51 +541,58 @@
dsn = getProtocolProperty(MAIL_SMTP_DSN_NOTIFY);
}
- // we need to know about any failures once we've gone through the complete list, so keep a
+ // we need to know about any failures once we've gone through the
+ // complete list, so keep a
// failure flag.
boolean sendFailure = false;
- // event notifcation requires we send lists of successes and failures broken down by category.
+ // event notifcation requires we send lists of successes and
+ // failures broken down by category.
// The categories are:
//
// 1) addresses successfully processed.
- // 2) addresses deemed valid, but had a processing failure that prevented sending.
- // 3) addressed deemed invalid (basically all other processing failures).
+ // 2) addresses deemed valid, but had a processing failure that
+ // prevented sending.
+ // 3) addressed deemed invalid (basically all other processing
+ // failures).
ArrayList sentAddresses = new ArrayList();
ArrayList unsentAddresses = new ArrayList();
ArrayList invalidAddresses = new ArrayList();
- // Now we add a MAIL TO record for each recipient. At this point, we just collect
+ // Now we add a MAIL TO record for each recipient. At this point, we
+ // just collect
for (int i = 0; i < addresses.length; i++) {
- InternetAddress target = (InternetAddress)addresses[i];
+ InternetAddress target = (InternetAddress) addresses[i];
// write out the record now.
SendStatus status = sendRcptTo(target, dsn);
stats[i] = status;
switch (status.getStatus()) {
- // successfully sent
- case SendStatus.SUCCESS:
- sentAddresses.add(target);
- break;
-
- // we have an invalid address of some sort, or a general sending error (which we'll
- // interpret as due to an invalid address.
- case SendStatus.INVALID_ADDRESS:
- case SendStatus.GENERAL_ERROR:
- sendFailure = true;
- invalidAddresses.add(target);
- break;
-
- // good address, but this was a send failure.
- case SendStatus.SEND_FAILURE:
- sendFailure = true;
- unsentAddresses.add(target);
- break;
+ // successfully sent
+ case SendStatus.SUCCESS:
+ sentAddresses.add(target);
+ break;
+
+ // we have an invalid address of some sort, or a general sending
+ // error (which we'll
+ // interpret as due to an invalid address.
+ case SendStatus.INVALID_ADDRESS:
+ case SendStatus.GENERAL_ERROR:
+ sendFailure = true;
+ invalidAddresses.add(target);
+ break;
+
+ // good address, but this was a send failure.
+ case SendStatus.SEND_FAILURE:
+ sendFailure = true;
+ unsentAddresses.add(target);
+ break;
}
}
- // if we had a send failure, then we need to check if we allow partial sends. If not allowed,
+ // if we had a send failure, then we need to check if we allow
+ // partial sends. If not allowed,
// we abort the send operation now.
if (sendFailure) {
// now see how we're configured for this send operation.
@@ -529,30 +600,34 @@
// this can be attached directly to the message.
if (message instanceof SMTPMessage) {
- partialSends = ((SMTPMessage)message).getSendPartial();
+ partialSends = ((SMTPMessage) message).getSendPartial();
}
- // if still false on the message object, check for a property version also
+ // if still false on the message object, check for a property
+ // version also
if (!partialSends) {
partialSends = isProtocolPropertyTrue(MAIL_SMTP_SENDPARTIAL);
}
-
- // if we're not allowing partial successes or we've failed on all of the addresses, it's
+ // if we're not allowing partial successes or we've failed on
+ // all of the addresses, it's
// time to abort.
if (!partialSends || sentAddresses.isEmpty()) {
- // we send along the valid and invalid address lists on the notifications and
+ // we send along the valid and invalid address lists on the
+ // notifications and
// exceptions.
- // however, since we're aborting the entire send, the successes need to become
+ // however, since we're aborting the entire send, the
+ // successes need to become
// members of the failure list.
unsentAddresses.addAll(sentAddresses);
// this one is empty.
sent = new Address[0];
- unsent = (Address[])unsentAddresses.toArray(new Address[0]);
- invalid = (Address[])invalidAddresses.toArray(new Address[0]);
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
- // go reset our connection so we can process additional sends.
+ // go reset our connection so we can process additional
+ // sends.
resetConnection();
// get a list of chained exceptions for all of the failures.
@@ -563,43 +638,47 @@
}
}
-
try {
// try to send the data
sendData(message);
} catch (MessagingException e) {
- // If there's an error at this point, this is a complete delivery failure.
- // we send along the valid and invalid address lists on the notifications and
+ // If there's an error at this point, this is a complete
+ // delivery failure.
+ // we send along the valid and invalid address lists on the
+ // notifications and
// exceptions.
- // however, since we're aborting the entire send, the successes need to become
+ // however, since we're aborting the entire send, the successes
+ // need to become
// members of the failure list.
unsentAddresses.addAll(sentAddresses);
// this one is empty.
sent = new Address[0];
- unsent = (Address[])unsentAddresses.toArray(new Address[0]);
- invalid = (Address[])invalidAddresses.toArray(new Address[0]);
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
// notify of the error.
notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent, invalid, message);
// send a send failure exception.
throw new SMTPSendFailedException("DATA", 0, "Send failure", e, sent, unsent, invalid);
}
-
- // create our lists for notification and exception reporting from this point on.
- sent = (Address[])sentAddresses.toArray(new Address[0]);
- unsent = (Address[])unsentAddresses.toArray(new Address[0]);
- invalid = (Address[])invalidAddresses.toArray(new Address[0]);
-
-
- // if sendFailure is true, we had an error during the address phase, but we had permission to
- // process this as a partial send operation. Now that the data has been sent ok, it's time to
+ // create our lists for notification and exception reporting from
+ // this point on.
+ sent = (Address[]) sentAddresses.toArray(new Address[0]);
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
+
+ // if sendFailure is true, we had an error during the address phase,
+ // but we had permission to
+ // process this as a partial send operation. Now that the data has
+ // been sent ok, it's time to
// report the partial failure.
if (sendFailure) {
// notify our listeners of the partial delivery.
notifyTransportListeners(TransportEvent.MESSAGE_PARTIALLY_DELIVERED, sent, unsent, invalid, message);
- // get a list of chained exceptions for all of the failures (and the successes, if reportSuccess has been
+ // get a list of chained exceptions for all of the failures (and
+ // the successes, if reportSuccess has been
// turned on).
MessagingException failures = generateExceptionChain(stats, getReportSuccess());
@@ -610,17 +689,20 @@
// notify our listeners of successful delivery.
notifyTransportListeners(TransportEvent.MESSAGE_DELIVERED, sent, unsent, invalid, message);
- // we've not had any failures, but we've been asked to report success as an exception. Do
+ // we've not had any failures, but we've been asked to report
+ // success as an exception. Do
// this now.
if (reportSuccess) {
- // generate the chain of success exceptions (we already know there are no failure ones to report).
+ // generate the chain of success exceptions (we already know
+ // there are no failure ones to report).
MessagingException successes = generateExceptionChain(stats, reportSuccess);
if (successes != null) {
throw successes;
}
}
} catch (SMTPSendFailedException e) {
- // if this is a send failure, we've already handled notifications....just rethrow it.
+ // if this is a send failure, we've already handled
+ // notifications....just rethrow it.
throw e;
} catch (MessagingException e) {
// notify of the error.
@@ -629,11 +711,10 @@
}
}
-
/**
- * Close the connection. On completion, we'll be disconnected from
- * the server and unable to send more data.
- *
+ * Close the connection. On completion, we'll be disconnected from the
+ * server and unable to send more data.
+ *
* @exception MessagingException
*/
public void close() throws MessagingException {
@@ -645,21 +726,22 @@
// say goodbye
sendQuit();
} finally {
- // and close up the connection. We do this in a finally block to make sure the connection
+ // and close up the connection. We do this in a finally block to
+ // make sure the connection
// is shut down even if quit gets an error.
closeServerConnection();
}
}
-
/**
- * Turn a series of send status items into a chain of exceptions
- * indicating the state of each send operation.
- *
- * @param stats The list of SendStatus items.
+ * Turn a series of send status items into a chain of exceptions indicating
+ * the state of each send operation.
+ *
+ * @param stats
+ * The list of SendStatus items.
* @param reportSuccess
- * Indicates whether we should include the report success items.
- *
+ * Indicates whether we should include the report success items.
+ *
* @return The head of a chained list of MessagingExceptions.
*/
protected MessagingException generateExceptionChain(SendStatus[] stats, boolean reportSuccess) {
@@ -670,12 +752,12 @@
if (status != null) {
MessagingException nextException = stats[i].getException(reportSuccess);
- // if there's an exception associated with this status, chain it up with the rest.
+ // if there's an exception associated with this status, chain it
+ // up with the rest.
if (nextException != null) {
if (current == null) {
current = nextException;
- }
- else {
+ } else {
current.setNextException(nextException);
current = nextException;
}
@@ -685,14 +767,14 @@
return current;
}
-
/**
* Reset the server connection after an error.
- *
+ *
* @exception MessagingException
*/
protected void resetConnection() throws MessagingException {
- // we want the caller to retrieve the last response responsbile for requiring the reset, so save and
+ // we want the caller to retrieve the last response responsbile for
+ // requiring the reset, so save and
// restore that info around the reset.
SMTPReply last = lastServerResponse;
@@ -707,28 +789,29 @@
lastServerResponse = last;
}
-
/**
- * Expand the address list by converting any group addresses
- * into single address targets.
- *
- * @param addresses The input array of addresses.
- *
+ * Expand the address list by converting any group addresses into single
+ * address targets.
+ *
+ * @param addresses
+ * The input array of addresses.
+ *
* @return The expanded array of addresses.
* @exception MessagingException
*/
protected Address[] expandGroups(Address[] addresses) throws MessagingException {
ArrayList expandedAddresses = new ArrayList();
- // run the list looking for group addresses, and add the full group list to our targets.
+ // run the list looking for group addresses, and add the full group list
+ // to our targets.
for (int i = 0; i < addresses.length; i++) {
- InternetAddress address = (InternetAddress)addresses[i];
- // not a group? Just copy over to the other list.
+ InternetAddress address = (InternetAddress) addresses[i];
+ // not a group? Just copy over to the other list.
if (!address.isGroup()) {
expandedAddresses.add(address);
- }
- else {
- // get the group address and copy each member of the group into the expanded list.
+ } else {
+ // get the group address and copy each member of the group into
+ // the expanded list.
InternetAddress[] groupAddresses = address.getGroup(true);
for (int j = 1; j < groupAddresses.length; j++) {
expandedAddresses.add(groupAddresses[j]);
@@ -737,21 +820,20 @@
}
// convert back into an array.
- return (Address [])expandedAddresses.toArray(new Address[0]);
+ return (Address[]) expandedAddresses.toArray(new Address[0]);
}
-
/**
- * Create a transport connection object and connect it to the
- * target server.
- *
- * @param host The target server host.
- * @param port The connection port.
- *
+ * Create a transport connection object and connect it to the target server.
+ *
+ * @param host
+ * The target server host.
+ * @param port
+ * The connection port.
+ *
* @exception MessagingException
*/
- protected void getConnection(String host, int port, String username, String password) throws IOException
- {
+ protected void getConnection(String host, int port, String username, String password) throws IOException {
this.host = host;
this.port = port;
this.username = username;
@@ -759,36 +841,42 @@
// and see if STARTTLS is enabled.
useTLS = isProtocolPropertyTrue(MAIL_SMTP_TLS);
serverAuthenticationMechanisms = new HashMap();
- // We might have been passed a socket to connect with...if not, we need to create one of the correct type.
+ // We might have been passed a socket to connect with...if not, we need
+ // to create one of the correct type.
if (socket == null) {
// if this is the "smtps" protocol, we start with an SSLSocket
if (sslConnection) {
getConnectedSSLSocket();
- }
- else
- {
+ } else {
getConnectedSocket();
}
}
- // if we already have a socket, get some information from it and override what we've been passed.
+ // if we already have a socket, get some information from it and
+ // override what we've been passed.
else {
port = socket.getPort();
host = socket.getInetAddress().getHostName();
}
// now set up the input/output streams.
- inputStream = new TraceInputStream(socket.getInputStream(), debugStream, debug, isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE)); ;
- outputStream = new TraceOutputStream(socket.getOutputStream(), debugStream, debug, isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
+ inputStream = new TraceInputStream(socket.getInputStream(), debugStream, debug,
+ isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
+ ;
+ outputStream = new TraceOutputStream(socket.getOutputStream(), debugStream, debug,
+ isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
}
/**
* Get a property associated with this mail protocol.
- *
- * @param name The name of the property.
- *
- * @return The property value (returns null if the property has not been set).
+ *
+ * @param name
+ * The name of the property.
+ *
+ * @return The property value (returns null if the property has not been
+ * set).
*/
protected String getProtocolProperty(String name) {
- // the name we're given is the least qualified part of the name. We construct the full property name
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
// using the protocol (either "smtp" or "smtps").
String fullName = "mail." + protocol + "." + name;
return getSessionProperty(fullName);
@@ -796,24 +884,28 @@
/**
* Get a property associated with this mail session.
- *
- * @param name The name of the property.
- *
- * @return The property value (returns null if the property has not been set).
+ *
+ * @param name
+ * The name of the property.
+ *
+ * @return The property value (returns null if the property has not been
+ * set).
*/
protected String getSessionProperty(String name) {
return session.getProperty(name);
}
/**
- * Get a property associated with this mail session. Returns
- * the provided default if it doesn't exist.
- *
- * @param name The name of the property.
+ * Get a property associated with this mail session. Returns the provided
+ * default if it doesn't exist.
+ *
+ * @param name
+ * The name of the property.
* @param defaultValue
- * The default value to return if the property doesn't exist.
- *
- * @return The property value (returns defaultValue if the property has not been set).
+ * The default value to return if the property doesn't exist.
+ *
+ * @return The property value (returns defaultValue if the property has not
+ * been set).
*/
protected String getSessionProperty(String name, String defaultValue) {
String result = session.getProperty(name);
@@ -824,30 +916,35 @@
}
/**
- * Get a property associated with this mail session. Returns
- * the provided default if it doesn't exist.
- *
- * @param name The name of the property.
+ * Get a property associated with this mail session. Returns the provided
+ * default if it doesn't exist.
+ *
+ * @param name
+ * The name of the property.
* @param defaultValue
- * The default value to return if the property doesn't exist.
- *
- * @return The property value (returns defaultValue if the property has not been set).
+ * The default value to return if the property doesn't exist.
+ *
+ * @return The property value (returns defaultValue if the property has not
+ * been set).
*/
protected String getProtocolProperty(String name, String defaultValue) {
- // the name we're given is the least qualified part of the name. We construct the full property name
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
// using the protocol (either "smtp" or "smtps").
String fullName = "mail." + protocol + "." + name;
return getSessionProperty(fullName, defaultValue);
}
/**
- * Get a property associated with this mail session as an integer value. Returns
- * the default value if the property doesn't exist or it doesn't have a valid int value.
- *
- * @param name The name of the property.
+ * Get a property associated with this mail session as an integer value.
+ * Returns the default value if the property doesn't exist or it doesn't
+ * have a valid int value.
+ *
+ * @param name
+ * The name of the property.
* @param defaultValue
- * The default value to return if the property doesn't exist.
- *
+ * The default value to return if the property doesn't exist.
+ *
* @return The property value converted to an int.
*/
protected int getIntSessionProperty(String name, int defaultValue) {
@@ -864,43 +961,46 @@
}
/**
- * Get a property associated with this mail session as an integer value. Returns
- * the default value if the property doesn't exist or it doesn't have a valid int value.
- *
- * @param name The name of the property.
+ * Get a property associated with this mail session as an integer value.
+ * Returns the default value if the property doesn't exist or it doesn't
+ * have a valid int value.
+ *
+ * @param name
+ * The name of the property.
* @param defaultValue
- * The default value to return if the property doesn't exist.
- *
+ * The default value to return if the property doesn't exist.
+ *
* @return The property value converted to an int.
*/
protected int getIntProtocolProperty(String name, int defaultValue) {
- // the name we're given is the least qualified part of the name. We construct the full property name
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
// using the protocol (either "smtp" or "smtps").
String fullName = "mail." + protocol + "." + name;
return getIntSessionProperty(fullName, defaultValue);
}
-
/**
- * Process a session property as a boolean value, returning
- * either true or false.
- *
- * @return True if the property value is "true". Returns false for any
- * other value (including null).
+ * Process a session property as a boolean value, returning either true or
+ * false.
+ *
+ * @return True if the property value is "true". Returns false for any other
+ * value (including null).
*/
protected boolean isProtocolPropertyTrue(String name) {
- // the name we're given is the least qualified part of the name. We construct the full property name
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
// using the protocol (either "smtp" or "smtps").
String fullName = "mail." + protocol + "." + name;
return isSessionPropertyTrue(fullName);
}
/**
- * Process a session property as a boolean value, returning
- * either true or false.
- *
- * @return True if the property value is "true". Returns false for any
- * other value (including null).
+ * Process a session property as a boolean value, returning either true or
+ * false.
+ *
+ * @return True if the property value is "true". Returns false for any other
+ * value (including null).
*/
protected boolean isSessionPropertyTrue(String name) {
String property = session.getProperty(name);
@@ -911,11 +1011,11 @@
}
/**
- * Process a session property as a boolean value, returning
- * either true or false.
- *
- * @return True if the property value is "false". Returns false for
- * other value (including null).
+ * Process a session property as a boolean value, returning either true or
+ * false.
+ *
+ * @return True if the property value is "false". Returns false for other
+ * value (including null).
*/
protected boolean isSessionPropertyFalse(String name) {
String property = session.getProperty(name);
@@ -926,25 +1026,24 @@
}
/**
- * Process a session property as a boolean value, returning
- * either true or false.
- *
- * @return True if the property value is "false". Returns false for
- * other value (including null).
+ * Process a session property as a boolean value, returning either true or
+ * false.
+ *
+ * @return True if the property value is "false". Returns false for other
+ * value (including null).
*/
protected boolean isProtocolPropertyFalse(String name) {
- // the name we're given is the least qualified part of the name. We construct the full property name
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
// using the protocol (either "smtp" or "smtps").
String fullName = "mail." + protocol + "." + name;
return isSessionPropertyTrue(fullName);
}
-
/**
* Close the server connection at termination.
*/
- protected void closeServerConnection()
- {
+ protected void closeServerConnection() {
try {
socket.close();
} catch (IOException ignored) {
@@ -955,10 +1054,9 @@
outputStream = null;
}
-
/**
* Creates a connected socket
- *
+ *
* @exception MessagingException
*/
protected void getConnectedSocket() throws IOException {
@@ -966,12 +1064,13 @@
debugOut("Attempting plain socket connection to server " + host + ":" + port);
}
-
- // the socket factory can be specified via a session property. By default, we just directly
+ // the socket factory can be specified via a session property. By
+ // default, we just directly
// instantiate a socket without using a factor.
String socketFactory = getProtocolProperty(MAIL_SMTP_FACTORY_CLASS);
- // there are several protocol properties that can be set to tune the created socket. We need to
+ // there are several protocol properties that can be set to tune the
+ // created socket. We need to
// retrieve those bits before creating the socket.
int timeout = getIntProtocolProperty(MAIL_SMTP_TIMEOUT, -1);
InetAddress localAddress = null;
@@ -986,7 +1085,8 @@
socket = null;
- // if there is no socket factory defined (normal), we just create a socket directly.
+ // if there is no socket factory defined (normal), we just create a
+ // socket directly.
if (socketFactory == null) {
socket = new Socket(host, port, localAddress, localPort);
}
@@ -1002,32 +1102,35 @@
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class factoryClass = loader.loadClass(socketFactory);
- // done indirectly, we need to invoke the method using reflection.
+ // done indirectly, we need to invoke the method using
+ // reflection.
// This retrieves a factory instance.
Method getDefault = factoryClass.getMethod("getDefault", new Class[0]);
Object defFactory = getDefault.invoke(new Object(), new Object[0]);
- // now that we have the factory, there are two different createSocket() calls we use,
+ // now that we have the factory, there are two different
+ // createSocket() calls we use,
// depending on whether we have a localAddress override.
if (localAddress != null) {
- // retrieve the createSocket(String, int, InetAddress, int) method.
+ // retrieve the createSocket(String, int, InetAddress, int)
+ // method.
Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class, Integer.TYPE };
Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
Object[] createSocketArgs = new Object[] { host, portArg, localAddress, new Integer(localPort) };
- socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
- }
- else {
+ socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
+ } else {
// retrieve the createSocket(String, int) method.
Class[] createSocketSig = new Class[] { String.class, Integer.TYPE };
Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
Object[] createSocketArgs = new Object[] { host, portArg };
- socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+ socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
}
} catch (Throwable e) {
- // if a socket factor is specified, then we may need to fall back to a default. This behavior
+ // if a socket factor is specified, then we may need to fall
+ // back to a default. This behavior
// is controlled by (surprise) more session properties.
if (isProtocolPropertyTrue(MAIL_SMTP_FACTORY_FALLBACK)) {
if (debug) {
@@ -1035,19 +1138,22 @@
}
socket = new Socket(host, port, localAddress, localPort);
}
- // we have an exception. We're going to throw an IOException, which may require unwrapping
+ // we have an exception. We're going to throw an IOException,
+ // which may require unwrapping
// or rewrapping the exception.
else {
- // we have an exception from the reflection, so unwrap the base exception
+ // we have an exception from the reflection, so unwrap the
+ // base exception
if (e instanceof InvocationTargetException) {
- e = ((InvocationTargetException)e).getTargetException();
+ e = ((InvocationTargetException) e).getTargetException();
}
if (debug) {
debugOut("Plain socket creation failure", e);
}
- // throw this as an IOException, with the original exception attached.
+ // throw this as an IOException, with the original exception
+ // attached.
IOException ioe = new IOException("Error connecting to " + host + ", " + port);
ioe.initCause(e);
throw ioe;
@@ -1060,21 +1166,24 @@
}
}
-
/**
* Creates a connected SSL socket for an initial SSL connection.
- *
+ *
* @exception MessagingException
*/
protected void getConnectedSSLSocket() throws IOException {
if (debug) {
debugOut("Attempting SSL socket connection to server " + host + ":" + port);
}
- // the socket factory can be specified via a protocol property, a session property, and if all else
- // fails (which it usually does), we fall back to the standard factory class.
- String socketFactory = getProtocolProperty(MAIL_SMTP_FACTORY_CLASS, getSessionProperty(MAIL_SSLFACTORY_CLASS, "javax.net.ssl.SSLSocketFactory"));
+ // the socket factory can be specified via a protocol property, a
+ // session property, and if all else
+ // fails (which it usually does), we fall back to the standard factory
+ // class.
+ String socketFactory = getProtocolProperty(MAIL_SMTP_FACTORY_CLASS, getSessionProperty(MAIL_SSLFACTORY_CLASS,
+ "javax.net.ssl.SSLSocketFactory"));
- // there are several protocol properties that can be set to tune the created socket. We need to
+ // there are several protocol properties that can be set to tune the
+ // created socket. We need to
// retrieve those bits before creating the socket.
int timeout = getIntProtocolProperty(MAIL_SMTP_TIMEOUT, -1);
InetAddress localAddress = null;
@@ -1089,13 +1198,15 @@
socket = null;
- // if there is no socket factory defined (normal), we just create a socket directly.
+ // if there is no socket factory defined (normal), we just create a
+ // socket directly.
if (socketFactory == null) {
socket = new Socket(host, port, localAddress, localPort);
}
else {
- // we'll try this with potentially two different factories if we're allowed to fall back.
+ // we'll try this with potentially two different factories if we're
+ // allowed to fall back.
boolean fallback = isProtocolPropertyTrue(MAIL_SMTP_FACTORY_FALLBACK);
while (true) {
@@ -1113,32 +1224,36 @@
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class factoryClass = loader.loadClass(socketFactory);
- // done indirectly, we need to invoke the method using reflection.
+ // done indirectly, we need to invoke the method using
+ // reflection.
// This retrieves a factory instance.
Method getDefault = factoryClass.getMethod("getDefault", new Class[0]);
Object defFactory = getDefault.invoke(new Object(), new Object[0]);
- // now that we have the factory, there are two different createSocket() calls we use,
+ // now that we have the factory, there are two different
+ // createSocket() calls we use,
// depending on whether we have a localAddress override.
if (localAddress != null) {
- // retrieve the createSocket(String, int, InetAddress, int) method.
- Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class, Integer.TYPE };
+ // retrieve the createSocket(String, int, InetAddress,
+ // int) method.
+ Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class,
+ Integer.TYPE };
Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
Object[] createSocketArgs = new Object[] { host, portArg, localAddress, new Integer(localPort) };
- socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
- }
- else {
+ socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
+ } else {
// retrieve the createSocket(String, int) method.
Class[] createSocketSig = new Class[] { String.class, Integer.TYPE };
Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
Object[] createSocketArgs = new Object[] { host, portArg };
- socket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+ socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
}
} catch (Throwable e) {
- // if we're allowed to fallback, then use the default factory and try this again. We only
+ // if we're allowed to fallback, then use the default
+ // factory and try this again. We only
// allow this to happen once.
if (fallback) {
if (debug) {
@@ -1148,19 +1263,22 @@
fallback = false;
continue;
}
- // we have an exception. We're going to throw an IOException, which may require unwrapping
+ // we have an exception. We're going to throw an
+ // IOException, which may require unwrapping
// or rewrapping the exception.
else {
- // we have an exception from the reflection, so unwrap the base exception
+ // we have an exception from the reflection, so unwrap
+ // the base exception
if (e instanceof InvocationTargetException) {
- e = ((InvocationTargetException)e).getTargetException();
+ e = ((InvocationTargetException) e).getTargetException();
}
if (debug) {
debugOut("Failure creating SSL socket", e);
}
- // throw this as an IOException, with the original exception attached.
+ // throw this as an IOException, with the original
+ // exception attached.
IOException ioe = new IOException("Error connecting to " + host + ", " + port);
ioe.initCause(e);
throw ioe;
@@ -1174,10 +1292,9 @@
}
}
-
/**
- * Switch the connection to using TLS level security,
- * switching to an SSL socket.
+ * Switch the connection to using TLS level security, switching to an SSL
+ * socket.
*/
protected void getConnectedTLSSocket() throws MessagingException {
if (debug) {
@@ -1192,14 +1309,15 @@
}
throw new MessagingException("Unable to make TLS server connection");
}
- // it worked, now switch the socket into TLS mode
- try {
+ // it worked, now switch the socket into TLS mode
+ try {
// we use the same target and port as the current connection.
String host = socket.getInetAddress().getHostName();
int port = socket.getPort();
- // the socket factory can be specified via a session property. By default, we use
+ // the socket factory can be specified via a session property. By
+ // default, we use
// the native SSL factory.
String socketFactory = getProtocolProperty(MAIL_SMTP_FACTORY_CLASS, "javax.net.ssl.SSLSocketFactory");
@@ -1219,32 +1337,36 @@
Object[] createSocketArgs = new Object[] { socket, host, new Integer(port), Boolean.TRUE };
// and finally create the socket
- Socket sslSocket = (Socket)createSocket.invoke(defFactory, createSocketArgs);
+ Socket sslSocket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
- // if this is an instance of SSLSocket (very common), try setting the protocol to be
- // "TLSv1". If this is some other class because of a factory override, we'll just have to
+ // if this is an instance of SSLSocket (very common), try setting
+ // the protocol to be
+ // "TLSv1". If this is some other class because of a factory
+ // override, we'll just have to
// accept that things will work.
if (sslSocket instanceof SSLSocket) {
- ((SSLSocket)sslSocket).setEnabledProtocols(new String[] {"TLSv1"} );
- ((SSLSocket)sslSocket).setUseClientMode(true);
- ((SSLSocket)sslSocket).startHandshake();
+ ((SSLSocket) sslSocket).setEnabledProtocols(new String[] { "TLSv1" });
+ ((SSLSocket) sslSocket).setUseClientMode(true);
+ ((SSLSocket) sslSocket).startHandshake();
}
-
- // and finally, as a last step, replace our input streams with the secure ones.
+ // and finally, as a last step, replace our input streams with the
+ // secure ones.
// now set up the input/output streams.
- inputStream = new TraceInputStream(sslSocket.getInputStream(), debugStream, debug, isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE)); ;
- outputStream = new TraceOutputStream(sslSocket.getOutputStream(), debugStream, debug, isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
+ inputStream = new TraceInputStream(sslSocket.getInputStream(), debugStream, debug,
+ isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
+ ;
+ outputStream = new TraceOutputStream(sslSocket.getOutputStream(), debugStream, debug,
+ isProtocolPropertyTrue(MAIL_SMTP_ENCODE_TRACE));
// this is our active socket now
socket = sslSocket;
- }
- catch (Exception e) {
+ } catch (Exception e) {
if (debug) {
debugOut("Failure attempting to convert connection to TLS", e);
}
- throw new MessagingException("Unable to convert connection to SSL", e);
- }
+ throw new MessagingException("Unable to convert connection to SSL", e);
+ }
}
/**
@@ -1256,9 +1378,9 @@
}
/**
- * Sends the data in the message down the socket. This presumes the
- * server is in the right place and ready for getting the DATA message
- * and the data right place in the sequence
+ * Sends the data in the message down the socket. This presumes the server
+ * is in the right place and ready for getting the DATA message and the data
+ * right place in the sequence
*/
protected void sendData(Message msg) throws MessagingException {
@@ -1269,16 +1391,21 @@
throw new MessagingException("Error issuing SMTP 'DATA' command: " + line);
}
- // now the data... I could look at the type, but
+ // now the data... I could look at the type, but
try {
- // the data content has two requirements we need to meet by filtering the
- // output stream. Requirement 1 is to conicalize any line breaks. All line
+ // the data content has two requirements we need to meet by
+ // filtering the
+ // output stream. Requirement 1 is to conicalize any line breaks.
+ // All line
// breaks will be transformed into properly formed CRLF sequences.
//
- // Requirement 2 is to perform byte-stuff for any line that begins with a "."
- // so that data is not confused with the end-of-data marker (a "\r\n.\r\n" sequence.
+ // Requirement 2 is to perform byte-stuff for any line that begins
+ // with a "."
+ // so that data is not confused with the end-of-data marker (a
+ // "\r\n.\r\n" sequence.
//
- // The MIME output stream performs those two functions on behalf of the content
+ // The MIME output stream performs those two functions on behalf of
+ // the content
// writer.
OutputStream mimeOut = new MIMEOutputStream(outputStream);
@@ -1294,14 +1421,15 @@
sendLine("");
sendLine(".");
- // use a longer time out here to give the server time to process the data.
+ // use a longer time out here to give the server time to process the
+ // data.
try {
- line = new SMTPReply(receiveLine(TIMEOUT * 2));
- } catch (MalformedSMTPReplyException e) {
+ line = new SMTPReply(receiveLine(TIMEOUT * 2));
+ } catch (MalformedSMTPReplyException e) {
throw new MessagingException(e.toString());
- } catch (MessagingException e) {
+ } catch (MessagingException e) {
throw new MessagingException(e.toString());
- }
+ }
if (line.isError()) {
throw new MessagingException("Error issuing SMTP 'DATA' command: " + line);
@@ -1312,12 +1440,13 @@
* Sends the QUIT message and receieves the response
*/
protected void sendQuit() throws MessagingException {
- // there's yet another property that controls whether we should wait for a
- // reply for a QUIT command. If on, just send the command and get outta here.
+ // there's yet another property that controls whether we should wait for
+ // a
+ // reply for a QUIT command. If on, just send the command and get outta
+ // here.
if (isProtocolPropertyTrue(MAIL_SMTP_QUITWAIT)) {
sendLine("QUIT");
- }
- else {
+ } else {
// handle as a real command...we're going to ignore the response.
sendCommand("QUIT");
}
@@ -1325,15 +1454,18 @@
/**
* Sets a receiver address for the current message
- *
- * @param addr The target address.
- * @param dsn An optional notification address appended to the MAIL command.
- *
+ *
+ * @param addr
+ * The target address.
+ * @param dsn
+ * An optional notification address appended to the MAIL command.
+ *
* @return The status for this particular send operation.
* @exception MessagingException
*/
protected SendStatus sendRcptTo(InternetAddress addr, String dsn) throws MessagingException {
- // compose the command using the fixed up email address. Normally, this involves adding
+ // compose the command using the fixed up email address. Normally, this
+ // involves adding
// "<" and ">" around the address.
StringBuffer command = new StringBuffer();
@@ -1354,42 +1486,43 @@
SMTPReply line = sendCommand(commandString);
switch (line.getCode()) {
- // these two are both successful transmissions
- case COMMAND_ACCEPTED:
- case ADDRESS_NOT_LOCAL:
- // we get out of here with the status information.
- return new SendStatus(SendStatus.SUCCESS, addr, commandString, line);
-
- // these are considered invalid address errors
- case PARAMETER_SYNTAX_ERROR:
- case INVALID_COMMAND_SEQUENCE:
- case MAILBOX_NOT_FOUND:
- case INVALID_MAILBOX:
- case USER_NOT_LOCAL:
- // we get out of here with the status information.
- return new SendStatus(SendStatus.INVALID_ADDRESS, addr, commandString, line);
-
- // the command was valid, but something went wrong in the server.
- case SERVICE_NOT_AVAILABLE:
- case MAILBOX_BUSY:
- case PROCESSING_ERROR:
- case INSUFFICIENT_STORAGE:
- case MAILBOX_FULL:
- // we get out of here with the status information.
- return new SendStatus(SendStatus.SEND_FAILURE, addr, commandString, line);
-
- // everything else is considered really bad...
- default:
- // we get out of here with the status information.
- return new SendStatus(SendStatus.GENERAL_ERROR, addr, commandString, line);
+ // these two are both successful transmissions
+ case COMMAND_ACCEPTED:
+ case ADDRESS_NOT_LOCAL:
+ // we get out of here with the status information.
+ return new SendStatus(SendStatus.SUCCESS, addr, commandString, line);
+
+ // these are considered invalid address errors
+ case PARAMETER_SYNTAX_ERROR:
+ case INVALID_COMMAND_SEQUENCE:
+ case MAILBOX_NOT_FOUND:
+ case INVALID_MAILBOX:
+ case USER_NOT_LOCAL:
+ // we get out of here with the status information.
+ return new SendStatus(SendStatus.INVALID_ADDRESS, addr, commandString, line);
+
+ // the command was valid, but something went wrong in the server.
+ case SERVICE_NOT_AVAILABLE:
+ case MAILBOX_BUSY:
+ case PROCESSING_ERROR:
+ case INSUFFICIENT_STORAGE:
+ case MAILBOX_FULL:
+ // we get out of here with the status information.
+ return new SendStatus(SendStatus.SEND_FAILURE, addr, commandString, line);
+
+ // everything else is considered really bad...
+ default:
+ // we get out of here with the status information.
+ return new SendStatus(SendStatus.GENERAL_ERROR, addr, commandString, line);
}
}
/**
* Set the sender for this mail.
- *
- * @param message The message we're sending.
- *
+ *
+ * @param message
+ * The message we're sending.
+ *
* @exception MessagingException
*/
protected boolean sendMailFrom(Message message) throws MessagingException {
@@ -1397,9 +1530,10 @@
// need to sort the from value out from a variety of sources.
String from = null;
- // first potential source is from the message itself, if it's an instance of SMTPMessage.
+ // first potential source is from the message itself, if it's an
+ // instance of SMTPMessage.
if (message instanceof SMTPMessage) {
- from = ((SMTPMessage)message).getEnvelopeFrom();
+ from = ((SMTPMessage) message).getEnvelopeFrom();
}
// if not available from the message, check the protocol property next
@@ -1408,22 +1542,22 @@
from = getProtocolProperty(MAIL_SMTP_FROM);
}
-
// if not there, see if we have something in the message header.
if (from == null || from.length() == 0) {
Address[] fromAddresses = message.getFrom();
- // if we have some addresses in the header, then take the first one as our From: address
+ // if we have some addresses in the header, then take the first one
+ // as our From: address
if (fromAddresses != null && fromAddresses.length > 0) {
- from = ((InternetAddress)fromAddresses[0]).getAddress();
+ from = ((InternetAddress) fromAddresses[0]).getAddress();
}
- // get what the InternetAddress class believes to be the local address.
+ // get what the InternetAddress class believes to be the local
+ // address.
else {
from = InternetAddress.getLocalAddress(session).getAddress();
}
}
-
if (from == null || from.length() == 0) {
throw new MessagingException("no FROM address");
}
@@ -1434,38 +1568,43 @@
command.append("MAIL FROM: ");
command.append(fixEmailAddress(from));
- // does this server support Delivery Status Notification? Then we may need to add some extra to the command.
+ // does this server support Delivery Status Notification? Then we may
+ // need to add some extra to the command.
if (supportsExtension("DSN")) {
String returnNotification = null;
- // the return notification stuff might be set as value on the message object itself.
+ // the return notification stuff might be set as value on the
+ // message object itself.
if (message instanceof SMTPMessage) {
// we need to convert the option into a string value.
- switch (((SMTPMessage)message).getReturnOption()) {
- case SMTPMessage.RETURN_FULL:
- returnNotification = "FULL";
- break;
+ switch (((SMTPMessage) message).getReturnOption()) {
+ case SMTPMessage.RETURN_FULL:
+ returnNotification = "FULL";
+ break;
- case SMTPMessage.RETURN_HDRS:
- returnNotification = "HDRS";
- break;
+ case SMTPMessage.RETURN_HDRS:
+ returnNotification = "HDRS";
+ break;
}
}
- // if not obtained from the message object, it can also be set as a property.
+ // if not obtained from the message object, it can also be set as a
+ // property.
if (returnNotification == null) {
// the DSN value is set by yet another property.
returnNotification = getProtocolProperty(MAIL_SMTP_DSN_RET);
}
- // if we have a target, add the notification stuff to our FROM command.
+ // if we have a target, add the notification stuff to our FROM
+ // command.
if (returnNotification != null) {
command.append(" RET=");
command.append(returnNotification);
}
}
- // if this server supports AUTH and we have submitter information, then we also add the
+ // if this server supports AUTH and we have submitter information, then
+ // we also add the
// "AUTH=" keyword to the MAIL FROM command (see RFC 2554).
if (supportsExtension("AUTH")) {
@@ -1473,14 +1612,15 @@
// another option that can be specified on the message object.
if (message instanceof SMTPMessage) {
- submitter = ((SMTPMessage)message).getSubmitter();
+ submitter = ((SMTPMessage) message).getSubmitter();
}
// if not part of the object, try for a propery version.
if (submitter == null) {
// we only send the extra keyword is a submitter is specified.
submitter = getProtocolProperty(MAIL_SMTP_SUBMITTER);
}
- // we have one...add the keyword, plus the submitter info in xtext format (defined by RFC 1891).
+ // we have one...add the keyword, plus the submitter info in xtext
+ // format (defined by RFC 1891).
if (submitter != null) {
command.append(" AUTH=");
try {
@@ -1494,10 +1634,11 @@
String extension = null;
- // now see if we need to add any additional extension info to this command. The extension is not
- // checked for validity. That's the reponsibility of the caller.
+ // now see if we need to add any additional extension info to this
+ // command. The extension is not
+ // checked for validity. That's the reponsibility of the caller.
if (message instanceof SMTPMessage) {
- extension = ((SMTPMessage)message).getMailExtension();
+ extension = ((SMTPMessage) message).getMailExtension();
}
// this can come either from the object or from a set property.
if (extension == null) {
@@ -1511,7 +1652,6 @@
command.append(extension);
}
-
// and finally send the command
SMTPReply line = sendCommand(command.toString());
@@ -1520,11 +1660,12 @@
}
/**
- * Send a command to the server, returning the first response line
- * back as a reply.
- *
- * @param data The data to send.
- *
+ * Send a command to the server, returning the first response line back as a
+ * reply.
+ *
+ * @param data
+ * The data to send.
+ *
* @return A reply object with the reply line.
* @exception MessagingException
*/
@@ -1533,10 +1674,8 @@
return getReply();
}
-
/**
- * Sends a message down the socket and terminates with the
- * appropriate CRLF
+ * Sends a message down the socket and terminates with the appropriate CRLF
*/
protected void sendLine(String data) throws MessagingException {
if (socket == null || !socket.isConnected()) {
@@ -1553,9 +1692,9 @@
}
/**
- * Receives one line from the server. A line is a sequence of bytes
+ * Receives one line from the server. A line is a sequence of bytes
* terminated by a CRLF
- *
+ *
* @return the line from the server as String
*/
protected String receiveLine() throws MessagingException {
@@ -1564,25 +1703,25 @@
/**
* Get a reply line for an SMTP command.
- *
+ *
* @return An SMTP reply object from the stream.
*/
protected SMTPReply getReply() throws MessagingException {
try {
- lastServerResponse = new SMTPReply(receiveLine());
- } catch (MalformedSMTPReplyException e) {
- throw new MessagingException(e.toString());
- } catch (MessagingException e) {
- throw e;
- }
+ lastServerResponse = new SMTPReply(receiveLine());
+ } catch (MalformedSMTPReplyException e) {
+ throw new MessagingException(e.toString());
+ } catch (MessagingException e) {
+ throw e;
+ }
return lastServerResponse;
}
/**
* Retrieve the last response received from the SMTP server.
- *
- * @return The raw response string (including the error code) returned
- * from the SMTP server.
+ *
+ * @return The raw response string (including the error code) returned from
+ * the SMTP server.
*/
public String getLastServerResponse() {
if (lastServerResponse == null) {
@@ -1591,12 +1730,10 @@
return lastServerResponse.getReply();
}
-
-
/**
- * Receives one line from the server. A line is a sequence of bytes
+ * Receives one line from the server. A line is a sequence of bytes
* terminated by a CRLF
- *
+ *
* @return the line from the server as String
*/
protected String receiveLine(int delayMillis) throws MessagingException {
@@ -1617,17 +1754,15 @@
int c;
boolean crFound = false, lfFound = false;
-
while ((c = inputStream.read()) != -1 && crFound == false && lfFound == false) {
- // we're looking for a CRLF sequence, so mark each one as seen. Any other
+ // we're looking for a CRLF sequence, so mark each one as seen.
+ // Any other
// character gets appended to the end of the buffer.
if (c == CR) {
crFound = true;
- }
- else if (c == LF) {
+ } else if (c == LF) {
lfFound = true;
- }
- else {
+ } else {
buff.append((char) c);
}
}
@@ -1649,14 +1784,14 @@
}
/**
- * Convert an InternetAddress into a form sendable on an SMTP
- * mail command. InternetAddress.getAddress() generally returns
- * just the address portion of the full address, minus route address
- * markers. We need to ensure we have an address with '<' and '>'
- * delimiters.
- *
- * @param mail The mail address returned from InternetAddress.getAddress().
- *
+ * Convert an InternetAddress into a form sendable on an SMTP mail command.
+ * InternetAddress.getAddress() generally returns just the address portion
+ * of the full address, minus route address markers. We need to ensure we
+ * have an address with '<' and '>' delimiters.
+ *
+ * @param mail
+ * The mail address returned from InternetAddress.getAddress().
+ *
* @return A string formatted for sending.
*/
protected String fixEmailAddress(String mail) {
@@ -1667,27 +1802,28 @@
}
/**
- * Start the handshake process with the server, including setting up and TLS-level work. At the
- * completion of this task, we should be ready to authenticate with the server, if needed.
+ * Start the handshake process with the server, including setting up and
+ * TLS-level work. At the completion of this task, we should be ready to
+ * authenticate with the server, if needed.
*/
protected boolean sendHandshake() throws MessagingException {
// check to see what sort of initial handshake we need to make.
boolean useEhlo = !isProtocolPropertyFalse(MAIL_SMTP_EHLO);
- // if we're to use Ehlo, send it and then fall back to just a HELO message if it fails.
+ // if we're to use Ehlo, send it and then fall back to just a HELO
+ // message if it fails.
if (useEhlo) {
if (!sendEhlo()) {
sendHelo();
}
- }
- else {
+ } else {
// send the initial hello response.
sendHelo();
}
-
if (useTLS) {
- // if we've been told to use TLS, and this server doesn't support it, then this is a failure
+ // if we've been told to use TLS, and this server doesn't support
+ // it, then this is a failure
if (!serverTLS) {
throw new MessagingException("Server doesn't support required transport level security");
}
@@ -1695,8 +1831,10 @@
// on our connection.
getConnectedTLSSocket();
- // some servers (gmail is one that I know of) only send a STARTTLS extension message on the
- // first EHLO command. Now that we have the TLS handshaking established, we need to send a
+ // some servers (gmail is one that I know of) only send a STARTTLS
+ // extension message on the
+ // first EHLO command. Now that we have the TLS handshaking
+ // established, we need to send a
// second EHLO message to retrieve the AUTH records from the server.
serverAuthenticationMechanisms.clear();
if (!sendEhlo()) {
@@ -1708,10 +1846,9 @@
return true;
}
-
/**
* Send the EHLO command to the SMTP server.
- *
+ *
* @return True if the command was accepted ok, false for any errors.
* @exception SMTPTransportException
* @exception MalformedSMTPReplyException
@@ -1722,8 +1859,10 @@
SMTPReply line = getReply();
- // we get a 250 code back. The first line is just a greeting, and extensions are identifed on
- // continuations. If this fails, then we'll try once more with HELO to establish bona fides.
+ // we get a 250 code back. The first line is just a greeting, and
+ // extensions are identifed on
+ // continuations. If this fails, then we'll try once more with HELO to
+ // establish bona fides.
if (line.getCode() != COMMAND_ACCEPTED) {
return false;
}
@@ -1745,10 +1884,9 @@
return true;
}
-
/**
* Send the HELO command to the SMTP server.
- *
+ *
* @exception MessagingException
*/
protected void sendHelo() throws MessagingException {
@@ -1756,17 +1894,18 @@
SMTPReply line = getReply();
- // we get a 250 code back. The first line is just a greeting, and extensions are identifed on
- // continuations. If this fails, then we'll try once more with HELO to establish bona fides.
+ // we get a 250 code back. The first line is just a greeting, and
+ // extensions are identifed on
+ // continuations. If this fails, then we'll try once more with HELO to
+ // establish bona fides.
if (line.getCode() != COMMAND_ACCEPTED) {
throw new MessagingException("Failure sending HELO command to SMTP server");
}
}
-
/**
* Retrieve the local client host name.
- *
+ *
* @return The string version of the local host name.
* @exception SMTPTransportException
*/
@@ -1788,60 +1927,57 @@
}
if (localHost == null) {
[... 474 lines stripped ...]