Author: noel
Date: Sat Jun 4 10:21:55 2005
New Revision: 180006
URL: http://svn.apache.org/viewcvs?rev=180006&view=rev
Log:
First attempt to leverage JavaMail 1.3.2 STMP reply code improvements to better
detect and handle transfer issues. Use <debug> true </debug> if you want to
diagnose what is happening.
Modified:
james/server/trunk/src/java/org/apache/james/transport/mailets/RemoteDelivery.java
Modified:
james/server/trunk/src/java/org/apache/james/transport/mailets/RemoteDelivery.java
URL:
http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/transport/mailets/RemoteDelivery.java?rev=180006&r1=180005&r2=180006&view=diff
==============================================================================
---
james/server/trunk/src/java/org/apache/james/transport/mailets/RemoteDelivery.java
(original)
+++
james/server/trunk/src/java/org/apache/james/transport/mailets/RemoteDelivery.java
Sat Jun 4 10:21:55 2005
@@ -46,6 +46,10 @@
import javax.mail.internet.MimeMessage;
import javax.mail.internet.ParseException;
+import com.sun.mail.smtp.SMTPSendFailedException;
+import com.sun.mail.smtp.SMTPAddressFailedException;
+import com.sun.mail.smtp.SMTPAddressSucceededException;
+
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
@@ -347,6 +351,46 @@
}
}
+ /*
+ * private method to log the extended SendFailedException introduced in
JavaMail 1.3.2.
+ */
+ private void logSendFailedException(SendFailedException sfe) {
+ if (isDebug) {
+ MessagingException me = (MessagingException)sfe;
+ if (me instanceof SMTPSendFailedException) {
+ SMTPSendFailedException ssfe = (SMTPSendFailedException)me;
+ log("SMTP SEND FAILED:");
+ log(ssfe.toString());
+ log(" Command: " + ssfe.getCommand());
+ log(" RetCode: " + ssfe.getReturnCode());
+ log(" Response: " + ssfe.getMessage());
+ } else {
+ log("Send failed: " + me.toString());
+ }
+ Exception ne;
+ while ((ne = me.getNextException()) != null && ne instanceof
MessagingException) {
+ me = (MessagingException)ne;
+ if (me instanceof SMTPAddressFailedException) {
+ SMTPAddressFailedException e =
(SMTPAddressFailedException)me;
+ log("ADDRESS FAILED:");
+ log(e.toString());
+ log(" Address: " + e.getAddress());
+ log(" Command: " + e.getCommand());
+ log(" RetCode: " + e.getReturnCode());
+ log(" Response: " + e.getMessage());
+ } else if (me instanceof SMTPAddressSucceededException) {
+ log("ADDRESS SUCCEEDED:");
+ SMTPAddressSucceededException e =
(SMTPAddressSucceededException)me;
+ log(e.toString());
+ log(" Address: " + e.getAddress());
+ log(" Command: " + e.getCommand());
+ log(" RetCode: " + e.getReturnCode());
+ log(" Response: " + e.getMessage());
+ }
+ }
+ }
+ }
+
/**
* We can assume that the recipients of this message are all going to the
same
* mail server. We will now rely on the DNS server to do DNS MX record
lookup
@@ -414,7 +458,7 @@
.append(outgoingMailServer.getHostName())
.append(" at ")
.append(outgoingMailServer.getHost())
- .append(" to addresses ")
+ .append(" for addresses ")
.append(Arrays.asList(addr));
log(logMessageBuffer.toString());
@@ -459,17 +503,41 @@
.append(") sent successfully to ")
.append(outgoingMailServer.getHostName())
.append(" at ")
- .append(outgoingMailServer.getHost());
+ .append(outgoingMailServer.getHost())
+ .append(" for ")
+ .append(mail.getRecipients());
log(logMessageBuffer.toString());
return true;
} catch (SendFailedException sfe) {
+ logSendFailedException(sfe);
+
+ if (sfe.getValidSentAddresses() != null) {
+ Address[] validSent = sfe.getValidSentAddresses();
+ if (validSent.length > 0) {
+ StringBuffer logMessageBuffer =
+ new StringBuffer(256)
+ .append("Mail (")
+ .append(mail.getName())
+ .append(") sent successfully for ")
+ .append(Arrays.asList(validSent));
+ log(logMessageBuffer.toString());
+ }
+ }
+
+ /* SMTPSendFailedException introduced in JavaMail 1.3.2,
and provides detailed protocol reply code for the operation */
+ if (sfe instanceof SMTPSendFailedException) {
+ SMTPSendFailedException ssfe =
(SMTPSendFailedException) sfe;
+ // if 5xx, terminate this delivery attempt by
re-throwing the exception.
+ if (ssfe.getReturnCode() >= 500 &&
ssfe.getReturnCode() <= 599) throw sfe;
+ }
+
if (sfe.getValidUnsentAddresses() != null
&& sfe.getValidUnsentAddresses().length > 0) {
if (isDebug) log("Send failed, " +
sfe.getValidUnsentAddresses().length + " valid addresses remain, continuing
with any other servers");
lastError = sfe;
continue;
} else {
- // There are no valid addresses left to send, so
rethrow
+ // There are no valid addresses left to send, so
rethrow
throw sfe;
}
} catch (MessagingException me) {
@@ -509,18 +577,14 @@
throw lastError;
}
} catch (SendFailedException sfe) {
- boolean deleteMessage = false;
+ logSendFailedException(sfe);
+
Collection recipients = mail.getRecipients();
- //Would like to log all the types of email addresses
- if (isDebug) log("Recipients: " + recipients);
+ boolean deleteMessage = false;
/*
- * The rest of the recipients failed for one reason or
- * another.
- *
- * SendFailedException actually handles this for us. For
- * example, if you send a message that has multiple invalid
+ * If you send a message that has multiple invalid
* addresses, you'll get a top-level SendFailedException
* that that has the valid, valid-unsent, and invalid
* address lists, with all of the server response messages
@@ -532,10 +596,34 @@
* sfe.getValidUnsentAddresses() should be considered temporary.
*
* JavaMail v1.3 properly populates those collections based
- * upon the 4xx and 5xx response codes.
+ * upon the 4xx and 5xx response codes to RCPT TO. Some
+ * servers, such as Yahoo! don't respond to the RCPT TO,
+ * and provide a 5xx reply after DATA. In that case, we
+ * will pick up the failure from SMTPSendFailedException.
*
*/
+ /* SMTPSendFailedException introduced in JavaMail 1.3.2, and
provides detailed protocol reply code for the operation */
+ if (sfe instanceof SMTPSendFailedException) {
+ // If we got an SMTPSendFailedException, use its RetCode to
determine default permanent/temporary failure
+ SMTPSendFailedException ssfe = (SMTPSendFailedException) sfe;
+ deleteMessage = (ssfe.getReturnCode() >= 500 &&
ssfe.getReturnCode() <= 599);
+ } else {
+ // Sometimes we'll get a normal SendFailedException with
nested SMTPAddressFailedException, so use the latter RetCode
+ MessagingException me = (MessagingException)sfe;
+ Exception ne;
+ while ((ne = me.getNextException()) != null && ne instanceof
MessagingException) {
+ me = (MessagingException)ne;
+ if (me instanceof SMTPAddressFailedException) {
+ SMTPAddressFailedException ssfe =
(SMTPAddressFailedException)me;
+ deleteMessage = (ssfe.getReturnCode() >= 500 &&
ssfe.getReturnCode() <= 599);
+ }
+ }
+ }
+
+ // log the original set of intended recipients
+ if (isDebug) log("Recipients: " + recipients);
+
if (sfe.getInvalidAddresses() != null) {
Address[] address = sfe.getInvalidAddresses();
if (address.length > 0) {
@@ -570,7 +658,12 @@
}
}
if (isDebug) log("Unsent recipients: " + recipients);
- deleteMessage = failMessage(mail, sfe, false);
+ if (sfe instanceof SMTPSendFailedException) {
+ SMTPSendFailedException ssfe =
(SMTPSendFailedException) sfe;
+ deleteMessage = failMessage(mail, sfe,
ssfe.getReturnCode() >= 500 && ssfe.getReturnCode() <= 599);
+ } else {
+ deleteMessage = failMessage(mail, sfe, false);
+ }
}
}
@@ -621,7 +714,7 @@
.append(mail.getName())
.append(": ");
out.print(logBuffer.toString());
- ex.printStackTrace(out);
+ if (isDebug) ex.printStackTrace(out);
log(sout.toString());
if (!permanent) {
if (!mail.getState().equals(Mail.ERROR)) {
@@ -717,7 +810,6 @@
}
}
out.println();
- out.println("The original message is attached.");
log("Sending failure message " + mail.getName());
try {
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]