//Create an array of the recipients as InternetAddress objects
Collection recipients = mail.getRecipients();
InternetAddress addr[] = new InternetAddress[recipients.size()];
int j = 0;
for (Iterator i = recipients.iterator(); i.hasNext(); j++) {
MailAddress rcpt = (MailAddress)i.next();
addr[j] = rcpt.toInternetAddress();
}
if (addr.length <= 0) {
log("No recipients specified... not sure how this could have happened.");
return true;
}
//Figure out which servers to try to send to. This collection
// will hold all the possible target servers
Collection targetServers = null;
if (gatewayServer == null) {
MailAddress rcpt = (MailAddress) recipients.iterator().next();
String host = rcpt.getHost();
//Lookup the possible targets
targetServers = getMailetContext().getMailServers(host);
if (targetServers.size() == 0) {
log("No mail server found for: " + host);
StringBuffer exceptionBuffer =
new StringBuffer(128)
.append("There are no DNS entries for the hostname ")
.append(host)
.append(". I cannot determine where to send this message.");
return failMessage(mail, new MessagingException(exceptionBuffer.toString()), false);
}
} else {
targetServers = new Vector();
targetServers.add(gatewayServer);
}
MessagingException lastError = null;
Iterator i = targetServers.iterator();
while ( i.hasNext()) {
try {
String outgoingMailServer = i.next().toString ();
StringBuffer logMessageBuffer =
new StringBuffer(256)
.append("Attempting delivery of ")
.append(mail.getName())
.append(" to host ")
.append(outgoingMailServer)
.append(" to addresses ")
.append(Arrays.asList(addr));
log(logMessageBuffer.toString());
URLName urlname = new URLName("smtp://" + outgoingMailServer);
Properties props = session.getProperties();
if (mail.getSender() == null) {
props.put("mail.smtp.from", "<>");
} else {
String sender = mail.getSender().toString();
props.put("mail.smtp.from", sender);
}
//Many of these properties are only in later JavaMail versions
//"mail.smtp.ehlo" //default true
//"mail.smtp.auth" //default false
//"mail.smtp.dsn.ret" //default to nothing... appended as RET= after MAIL FROM line.
//"mail.smtp.dsn.notify" //default to nothing...appended as NOTIFY= after RCPT TO line.
Transport transport = null;
try {
transport = session.getTransport(urlname);
try {
transport.connect();
} catch (MessagingException me) {
// Any error on connect should cause the mailet to attempt
// to connect to the next SMTP server associated with this MX record,
// assuming the number of retries hasn't been exceeded.
if (failMessage(mail, me, false)) {
return true;
} else {
continue;
}
}
transport.sendMessage(message, addr);
} finally {
if (transport != null) {
transport.close();
transport = null;
}
}
logMessageBuffer =
new StringBuffer(256)
.append("Mail (")
.append(mail.getName())
.append(") sent successfully to ")
.append(outgoingMailServer);
log(logMessageBuffer.toString());
return true;
} catch (MessagingException me) {
//MessagingException are horribly difficult to figure out what actually happened.
StringBuffer exceptionBuffer =
new StringBuffer(256)
.append("Exception delivering message (")
.append(mail.getName())
.append(") - ")
.append(me.getMessage());
log(exceptionBuffer.toString());
if ((me.getNextException() != null) &&
(me.getNextException() instanceof java.io.IOException)) {
//This is more than likely a temporary failure
// If it's an IO exception with no nested exception, it's probably
// some socket or weird I/O related problem.
lastError = me;
continue;
}
// This was not a connection or I/O error particular to one
// SMTP server of an MX set. Instead, it is almost certainly
// a protocol level error. In this case we assume that this
// is an error we'd encounter with any of the SMTP servers
// associated with this MX record, and we pass the exception
// to the code in the outer block that determines its severity.
throw me;
}
} // end while
//If we encountered an exception while looping through,
//throw the last MessagingException we caught. We only
//do this if we were unable to send the message to any
//server. If sending eventually succeeded, we exit
//deliver() though the return at the end of the try
//block.
if (lastError != null) {
throw lastError;
}
} catch (SendFailedException sfe) {
boolean deleteMessage = false;
Collection recipients = mail.getRecipients();
//Would like to log all the types of email addresses
if (isDebug) log("Recipients: " + recipients);
/*
if (sfe.getValidSentAddresses() != null) {
Address[] validSent = sfe.getValidSentAddresses();
Collection recipients = mail.getRecipients();
//Remove these addresses for the recipients
for (int i = 0; i < validSent.length; i++) {
try {
MailAddress addr = new MailAddress(validSent[i].toString());
recipients.remove(addr);
} catch (ParseException pe) {
//ignore once debugging done
pe.printStackTrace();
}
}
}
*/
/*
* 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
* 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
* will be contained within the nested exceptions. [Note:
* the content of the nested exceptions is implementation
* dependent.]
*
* sfe.getInvalidAddresses() should be considered permanent.
* sfe.getValidUnsentAddresses() should be considered temporary.
*
* JavaMail v1.3 properly populates those collections based
* upon the 4xx and 5xx response codes.
*
*/
if (sfe.getInvalidAddresses() != null) {
Address[] address = sfe.getInvalidAddresses();
if (address.length > 0) {
recipients.clear();
for (int i = 0; i < address.length; i++) {
try {
recipients.add(new MailAddress(address[i].toString()));
} catch (ParseException pe) {
// this should never happen ... we should have
// caught malformed addresses long before we
// got to this code.
log("Can't parse invalid address: " + pe.getMessage());
}
}
if (isDebug) log("Invalid recipients: " + recipients);
deleteMessage = failMessage(mail, sfe, true);
}
}
if (sfe.getValidUnsentAddresses() != null) {
Address[] address = sfe.getValidUnsentAddresses();
if (address.length > 0) {
recipients.clear();
for (int i = 0; i < address.length; i++) {
try {
recipients.add(new MailAddress(address[i].toString()));
} catch (ParseException pe) {
// this should never happen ... we should have
// caught malformed addresses long before we
// got to this code.
log("Can't parse unsent address: " + pe.getMessage());