diff --git a/WHATSNEW b/WHATSNEW index c7ae71988..e93979dfe 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -425,6 +425,10 @@ Other changes: used by MailLogger. Bugzilla Report 27211. + * a new attribute of allows the task to succeed if it can + reach at least one given recipient. + Bugzilla Report 36446. + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= diff --git a/docs/manual/CoreTasks/mail.html b/docs/manual/CoreTasks/mail.html index 408190429..c119cd24c 100644 --- a/docs/manual/CoreTasks/mail.html +++ b/docs/manual/CoreTasks/mail.html @@ -172,6 +172,13 @@ Email subject line. No + + ignoreInvalidRecipients + Boolean. Whether the task should try to send + the message to as many recipients as possible and should only + fail if neither is reachable. Since Ant 1.8.0. + No, default is false +

Note regarding the attributes containing email addresses

diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java index ef6962aa7..6360f0562 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java @@ -103,6 +103,9 @@ public class EmailTask extends Task { /** indicate if the user wishes SSL-TLS */ private boolean ssl = false; + /** ignore invalid recipients? */ + private boolean ignoreInvalidRecipients = false; + /** * Set the user for SMTP auth; this requires JavaMail. * @param user the String username. @@ -402,6 +405,19 @@ public class EmailTask extends Task { return includeFileNames; } + /** + * Whether invalid recipients should be ignored (but a warning + * will be logged) instead of making the task fail. + * + *

Even with this property set to true the task will still fail + * if the mail couldn't be sent to any recipient at all.

+ * + * @since Ant 1.8.0 + */ + public void setIgnoreInvalidRecipients(boolean b) { + ignoreInvalidRecipients = b; + } + /** * Send an email. */ @@ -532,6 +548,7 @@ public class EmailTask extends Task { mailer.setTask(this); mailer.setIncludeFileNames(includeFileNames); mailer.setHeaders(headers); + mailer.setIgnoreInvalidRecipients(ignoreInvalidRecipients); // send the email mailer.send(); diff --git a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java index b9a645648..bb9cf7e2d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java @@ -48,6 +48,7 @@ public abstract class Mailer { protected boolean includeFileNames = false; protected Vector headers = null; // CheckStyle:VisibilityModifier ON + private boolean ignoreInvalidRecipients = false; /** * Set the mail server. @@ -205,6 +206,28 @@ public abstract class Mailer { public abstract void send() throws BuildException; + /** + * Whether invalid recipients should be ignored (but a warning + * will be logged) instead of making the task fail. + * + *

Even with this property set to true the task will still fail + * if the mail couldn't be sent to any recipient at all.

+ * + * @since Ant 1.8.0 + */ + public void setIgnoreInvalidRecipients(boolean b) { + ignoreInvalidRecipients = b; + } + + /** + * Whether invalid recipients should be ignored. + * + * @since Ant 1.8.0 + */ + protected boolean shouldIgnoreInvalidRecipients() { + return ignoreInvalidRecipients; + } + /** * Return the current Date in a format suitable for a SMTP date * header. diff --git a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java index dac8d41f0..4a295d3e6 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java @@ -38,19 +38,22 @@ import java.security.Security; import javax.activation.DataHandler; import javax.activation.FileDataSource; -import javax.mail.Message; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.Authenticator; +import javax.mail.Address; +import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; -import javax.mail.internet.MimeMessage; +import javax.mail.SendFailedException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.AddressException; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; /** * Uses the JavaMail classes to send Mime format email. @@ -60,6 +63,9 @@ import org.apache.tools.ant.BuildException; public class MimeMailer extends Mailer { private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + private static final String GENERIC_ERROR = + "Problem while sending mime mail:"; + /** Default character set */ private static final String DEFAULT_CHARSET = System.getProperty("file.encoding"); @@ -237,11 +243,36 @@ public class MimeMailer extends Mailer { attachments.addBodyPart(body); } msg.setContent(attachments); - Transport.send(msg); + try { + Transport.send(msg); + } catch (SendFailedException sfe) { + if (!shouldIgnoreInvalidRecipients()) { + throw new BuildException(GENERIC_ERROR, sfe); + } else if (sfe.getValidSentAddresses() == null + || sfe.getValidSentAddresses().length == 0) { + throw new BuildException("Couldn't reach any recipient", + sfe); + } else { + Address[] invalid = sfe.getInvalidAddresses(); + if (invalid == null) { + invalid = new Address[0]; + } + for (int i = 0; i < invalid.length; i++) { + didntReach(invalid[i], "invalid", sfe); + } + Address[] validUnsent = sfe.getValidUnsentAddresses(); + if (validUnsent == null) { + validUnsent = new Address[0]; + } + for (int i = 0; i < validUnsent.length; i++) { + didntReach(validUnsent[i], "valid", sfe); + } + } + } } catch (MessagingException e) { - throw new BuildException("Problem while sending mime mail:", e); + throw new BuildException(GENERIC_ERROR, e); } catch (IOException e) { - throw new BuildException("Problem while sending mime mail:", e); + throw new BuildException(GENERIC_ERROR, e); } } @@ -274,6 +305,17 @@ public class MimeMailer extends Mailer { return token.nextToken(); } + private void didntReach(Address addr, String category, + MessagingException ex) { + String msg = "Failed to send mail to " + category + " address " + + addr + " because of " + ex.getMessage(); + if (task != null) { + task.log(msg, Project.MSG_WARN); + } else { + System.err.println(msg); + } + } + static class SimpleAuthenticator extends Authenticator { private String user = null; private String password = null; diff --git a/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java index 113cb3a37..3c5212b17 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.PrintStream; import java.util.Enumeration; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; import org.apache.tools.mail.MailMessage; /** @@ -44,6 +45,7 @@ class PlainMailer extends Mailer { mailMessage.from(from.toString()); Enumeration e; + boolean atLeastOneRcptReached = false; e = replyToList.elements(); while (e.hasMoreElements()) { @@ -51,15 +53,36 @@ class PlainMailer extends Mailer { } e = toList.elements(); while (e.hasMoreElements()) { - mailMessage.to(e.nextElement().toString()); + String to = e.nextElement().toString(); + try { + mailMessage.to(to); + atLeastOneRcptReached = true; + } catch (IOException ex) { + badRecipient(to, ex); + } } e = ccList.elements(); while (e.hasMoreElements()) { - mailMessage.cc(e.nextElement().toString()); + String to = e.nextElement().toString(); + try { + mailMessage.cc(to); + atLeastOneRcptReached = true; + } catch (IOException ex) { + badRecipient(to, ex); + } } e = bccList.elements(); while (e.hasMoreElements()) { - mailMessage.bcc(e.nextElement().toString()); + String to = e.nextElement().toString(); + try { + mailMessage.bcc(to); + atLeastOneRcptReached = true; + } catch (IOException ex) { + badRecipient(to, ex); + } + } + if (!atLeastOneRcptReached) { + throw new BuildException("Couldn't reach any recipient"); } if (subject != null) { mailMessage.setSubject(subject); @@ -135,5 +158,19 @@ class PlainMailer extends Mailer { finstr.close(); } } + + private void badRecipient(String rcpt, IOException reason) { + String msg = "Failed to send mail to " + rcpt; + if (shouldIgnoreInvalidRecipients()) { + msg += " because of :" + reason.getMessage(); + if (task != null) { + task.log(msg, Project.MSG_WARN); + } else { + System.err.println(msg); + } + } else { + throw new BuildException(msg, reason); + } + } }