Save This Page
Home » apache-ant-1.8.1 » org.apache.tools » ant » taskdefs » email » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    *
   17    */
   18   package org.apache.tools.ant.taskdefs.email;
   19   
   20   import java.io.File;
   21   import java.util.Iterator;
   22   import java.util.StringTokenizer;
   23   import java.util.Vector;
   24   
   25   import org.apache.tools.ant.BuildException;
   26   import org.apache.tools.ant.Project;
   27   import org.apache.tools.ant.Task;
   28   import org.apache.tools.ant.types.EnumeratedAttribute;
   29   import org.apache.tools.ant.types.FileSet;
   30   import org.apache.tools.ant.types.Path;
   31   import org.apache.tools.ant.types.Resource;
   32   import org.apache.tools.ant.types.resources.FileProvider;
   33   import org.apache.tools.ant.types.resources.FileResource;
   34   import org.apache.tools.ant.util.ClasspathUtils;
   35   
   36   /**
   37    * A task to send SMTP email. This is a refactoring of the SendMail and
   38    * MimeMail tasks such that both are within a single task.
   39    *
   40    * @since Ant 1.5
   41    * @ant.task name="mail" category="network"
   42    */
   43   public class EmailTask extends Task {
   44       private static final int SMTP_PORT = 25;
   45   
   46       /** Constant to show that the best available mailer should be used.  */
   47       public static final String AUTO = "auto";
   48       /** Constant to allow the Mime mailer to be requested  */
   49       public static final String MIME = "mime";
   50       /** Constant to allow the UU mailer to be requested  */
   51       public static final String UU = "uu";
   52       /** Constant to allow the plaintext mailer to be requested  */
   53       public static final String PLAIN = "plain";
   54   
   55       /**
   56        * Enumerates the encoding constants.
   57        */
   58       public static class Encoding extends EnumeratedAttribute {
   59           /**
   60            * finds the valid encoding values
   61            *
   62            * @return a list of valid entries
   63            */
   64           public String[] getValues() {
   65               return new String[] {AUTO, MIME, UU, PLAIN};
   66           }
   67       }
   68   
   69       private String encoding = AUTO;
   70       /** host running SMTP  */
   71       private String host = "localhost";
   72       private int port = SMTP_PORT;
   73       /** subject field  */
   74       private String subject = null;
   75       /** any text  */
   76       private Message message = null;
   77       /** failure flag */
   78       private boolean failOnError = true;
   79       private boolean includeFileNames = false;
   80       private String messageMimeType = null;
   81       /* special headers */
   82       /** sender  */
   83       private EmailAddress from = null;
   84       /** replyto */
   85       private Vector replyToList = new Vector();
   86       /** TO recipients  */
   87       private Vector toList = new Vector();
   88       /** CC (Carbon Copy) recipients  */
   89       private Vector ccList = new Vector();
   90       /** BCC (Blind Carbon Copy) recipients  */
   91       private Vector bccList = new Vector();
   92   
   93       /** generic headers */
   94       private Vector headers = new Vector();
   95   
   96       /** file list  */
   97       private Path attachments = null;
   98       /** Character set for MimeMailer*/
   99       private String charset = null;
  100       /** User for SMTP auth */
  101       private String user = null;
  102       /** Password for SMTP auth */
  103       private String password = null;
  104       /** indicate if the user wishes SSL-TLS */
  105       private boolean ssl = false;
  106       /** indicate if the user wishes support for STARTTLS */
  107       private boolean starttls = false;
  108   
  109       /** ignore invalid recipients? */
  110       private boolean ignoreInvalidRecipients = false;
  111   
  112       /**
  113        * Set the user for SMTP auth; this requires JavaMail.
  114        * @param user the String username.
  115        * @since Ant 1.6
  116        */
  117       public void setUser(String user) {
  118           this.user = user;
  119       }
  120   
  121       /**
  122        * Set the password for SMTP auth; this requires JavaMail.
  123        * @param password the String password.
  124        * @since Ant 1.6
  125        */
  126       public void setPassword(String password) {
  127           this.password = password;
  128       }
  129   
  130       /**
  131        * Set whether to send data over SSL.
  132        * @param ssl boolean; if true SSL will be used.
  133        * @since Ant 1.6
  134        */
  135       public void setSSL(boolean ssl) {
  136           this.ssl = ssl;
  137       }
  138   
  139       /**
  140        * Set whether to allow authentication to switch to a TLS
  141        * connection via STARTTLS.
  142        * @param b boolean; if true STARTTLS will be supported.
  143        * @since Ant 1.8.0
  144        */
  145       public void setEnableStartTLS(boolean b) {
  146           this.starttls = b;
  147       }
  148   
  149       /**
  150        * Set the preferred encoding method.
  151        *
  152        * @param encoding The encoding (one of AUTO, MIME, UU, PLAIN).
  153        */
  154       public void setEncoding(Encoding encoding) {
  155           this.encoding = encoding.getValue();
  156       }
  157   
  158       /**
  159        * Set the mail server port.
  160        *
  161        * @param port The port to use.
  162        */
  163       public void setMailport(int port) {
  164           this.port = port;
  165       }
  166   
  167       /**
  168        * Set the host.
  169        *
  170        * @param host The host to connect to.
  171        */
  172       public void setMailhost(String host) {
  173           this.host = host;
  174       }
  175   
  176       /**
  177        * Set the subject line of the email.
  178        *
  179        * @param subject Subject of this email.
  180        */
  181       public void setSubject(String subject) {
  182           this.subject = subject;
  183       }
  184   
  185       /**
  186        * Shorthand method to set the message.
  187        *
  188        * @param message Message body of this email.
  189        */
  190       public void setMessage(String message) {
  191           if (this.message != null) {
  192               throw new BuildException("Only one message can be sent in an "
  193                    + "email");
  194           }
  195           this.message = new Message(message);
  196           this.message.setProject(getProject());
  197       }
  198   
  199       /**
  200        * Shorthand method to set the message from a file.
  201        *
  202        * @param file The file from which to take the message.
  203        */
  204       public void setMessageFile(File file) {
  205           if (this.message != null) {
  206               throw new BuildException("Only one message can be sent in an "
  207                    + "email");
  208           }
  209           this.message = new Message(file);
  210           this.message.setProject(getProject());
  211       }
  212   
  213       /**
  214        * Shorthand method to set type of the text message, text/plain by default
  215        * but text/html or text/xml is quite feasible.
  216        *
  217        * @param type The new MessageMimeType value.
  218        */
  219       public void setMessageMimeType(String type) {
  220           this.messageMimeType = type;
  221       }
  222   
  223       /**
  224        * Add a message element.
  225        *
  226        * @param message The message object.
  227        * @throws BuildException if a message has already been added.
  228        */
  229       public void addMessage(Message message) throws BuildException {
  230           if (this.message != null) {
  231               throw new BuildException(
  232                   "Only one message can be sent in an email");
  233           }
  234           this.message = message;
  235       }
  236   
  237       /**
  238        * Add a from address element.
  239        *
  240        * @param address The address to send from.
  241        */
  242       public void addFrom(EmailAddress address) {
  243           if (this.from != null) {
  244               throw new BuildException("Emails can only be from one address");
  245           }
  246           this.from = address;
  247       }
  248   
  249       /**
  250        * Shorthand to set the from address element.
  251        *
  252        * @param address The address to send mail from.
  253        */
  254       public void setFrom(String address) {
  255           if (this.from != null) {
  256               throw new BuildException("Emails can only be from one address");
  257           }
  258           this.from = new EmailAddress(address);
  259       }
  260   
  261       /**
  262        * Add a replyto address element.
  263        *
  264        * @param address The address to reply to.
  265        * @since Ant 1.6
  266        */
  267       public void addReplyTo(EmailAddress address) {
  268           this.replyToList.add(address);
  269       }
  270   
  271       /**
  272        * Shorthand to set the replyto address element.
  273        *
  274        * @param address The address to which replies should be directed.
  275        * @since Ant 1.6
  276        */
  277       public void setReplyTo(String address) {
  278           this.replyToList.add(new EmailAddress(address));
  279       }
  280   
  281       /**
  282        * Add a to address element.
  283        *
  284        * @param address An email address.
  285        */
  286       public void addTo(EmailAddress address) {
  287           toList.addElement(address);
  288       }
  289   
  290       /**
  291        * Shorthand to set the "to" address element.
  292        *
  293        * @param list Comma-separated list of addresses.
  294        */
  295       public void setToList(String list) {
  296           StringTokenizer tokens = new StringTokenizer(list, ",");
  297   
  298           while (tokens.hasMoreTokens()) {
  299               toList.addElement(new EmailAddress(tokens.nextToken()));
  300           }
  301       }
  302   
  303       /**
  304        * Add a "cc" address element.
  305        *
  306        * @param address The email address.
  307        */
  308       public void addCc(EmailAddress address) {
  309           ccList.addElement(address);
  310       }
  311   
  312       /**
  313        * Shorthand to set the "cc" address element.
  314        *
  315        * @param list Comma separated list of addresses.
  316        */
  317       public void setCcList(String list) {
  318           StringTokenizer tokens = new StringTokenizer(list, ",");
  319   
  320           while (tokens.hasMoreTokens()) {
  321               ccList.addElement(new EmailAddress(tokens.nextToken()));
  322           }
  323       }
  324   
  325       /**
  326        * Add a "bcc" address element.
  327        *
  328        * @param address The email address.
  329        */
  330       public void addBcc(EmailAddress address) {
  331           bccList.addElement(address);
  332       }
  333   
  334       /**
  335        * Shorthand to set the "bcc" address element.
  336        *
  337        * @param list comma separated list of addresses.
  338        */
  339       public void setBccList(String list) {
  340           StringTokenizer tokens = new StringTokenizer(list, ",");
  341   
  342           while (tokens.hasMoreTokens()) {
  343               bccList.addElement(new EmailAddress(tokens.nextToken()));
  344           }
  345       }
  346   
  347       /**
  348        * Set whether BuildExceptions should be passed back to the core.
  349        *
  350        * @param failOnError The new FailOnError value.
  351        */
  352       public void setFailOnError(boolean failOnError) {
  353           this.failOnError = failOnError;
  354       }
  355   
  356       /**
  357        * Set the list of files to be attached.
  358        *
  359        * @param filenames Comma-separated list of files.
  360        */
  361       public void setFiles(String filenames) {
  362           StringTokenizer t = new StringTokenizer(filenames, ", ");
  363   
  364           while (t.hasMoreTokens()) {
  365               createAttachments()
  366                   .add(new FileResource(getProject().resolveFile(t.nextToken())));
  367           }
  368       }
  369   
  370       /**
  371        * Add a set of files (nested fileset attribute).
  372        *
  373        * @param fs The fileset.
  374        */
  375       public void addFileset(FileSet fs) {
  376           createAttachments().add(fs);
  377       }
  378   
  379       /**
  380        * Creates a Path as container for attachments.  Supports any
  381        * filesystem resource-collections that way.
  382        * @return the path to be configured.
  383        * @since Ant 1.7
  384        */
  385       public Path createAttachments() {
  386           if (attachments == null) {
  387               attachments = new Path(getProject());
  388           }
  389           return attachments.createPath();
  390       }
  391   
  392       /**
  393        * Create a nested header element.
  394        * @return a Header instance.
  395        */
  396       public Header createHeader() {
  397           Header h = new Header();
  398           headers.add(h);
  399           return h;
  400       }
  401   
  402       /**
  403        * Set whether to include filenames.
  404        *
  405        * @param includeFileNames Whether to include filenames in the text of the
  406        *      message.
  407        */
  408       public void setIncludefilenames(boolean includeFileNames) {
  409           this.includeFileNames = includeFileNames;
  410       }
  411   
  412       /**
  413        * Get whether file names should be included.
  414        *
  415        * @return Identifies whether file names should be included.
  416        */
  417       public boolean getIncludeFileNames() {
  418           return includeFileNames;
  419       }
  420   
  421       /**
  422        * Whether invalid recipients should be ignored (but a warning
  423        * will be logged) instead of making the task fail.
  424        *
  425        * <p>Even with this property set to true the task will still fail
  426        * if the mail couldn't be sent to any recipient at all.</p>
  427        *
  428        * @since Ant 1.8.0
  429        */
  430       public void setIgnoreInvalidRecipients(boolean b) {
  431           ignoreInvalidRecipients = b;
  432       }
  433   
  434       /**
  435        * Send an email.
  436        */
  437       public void execute() {
  438           Message savedMessage = message;
  439   
  440           try {
  441               Mailer mailer = null;
  442   
  443               // prepare for the auto select mechanism
  444               boolean autoFound = false;
  445               // try MIME format
  446               if (encoding.equals(MIME)
  447                    || (encoding.equals(AUTO) && !autoFound)) {
  448                   try {
  449                       //check to make sure that activation.jar 
  450                       //and mail.jar are available - see bug 31969
  451                       Class.forName("javax.activation.DataHandler");
  452                       Class.forName("javax.mail.internet.MimeMessage");
  453   
  454                       mailer = (Mailer) ClasspathUtils.newInstance(
  455                               "org.apache.tools.ant.taskdefs.email.MimeMailer",
  456                               EmailTask.class.getClassLoader(), Mailer.class);
  457                       autoFound = true;
  458   
  459                       log("Using MIME mail", Project.MSG_VERBOSE);
  460                   } catch (BuildException e) {
  461                       logBuildException("Failed to initialise MIME mail: ", e);
  462                   }
  463               }
  464               // SMTP auth only allowed with MIME mail
  465               if (!autoFound && ((user != null) || (password != null))
  466                   && (encoding.equals(UU) || encoding.equals(PLAIN))) {
  467                   throw new BuildException("SMTP auth only possible with MIME mail");
  468               }
  469               // SSL only allowed with MIME mail
  470               if (!autoFound  && (ssl || starttls)
  471                   && (encoding.equals(UU) || encoding.equals(PLAIN))) {
  472                   throw new BuildException("SSL and STARTTLS only possible with"
  473                                            + " MIME mail");
  474               }
  475               // try UU format
  476               if (encoding.equals(UU)
  477                    || (encoding.equals(AUTO) && !autoFound)) {
  478                   try {
  479                       mailer = (Mailer) ClasspathUtils.newInstance(
  480                               "org.apache.tools.ant.taskdefs.email.UUMailer",
  481                               EmailTask.class.getClassLoader(), Mailer.class);
  482                       autoFound = true;
  483                       log("Using UU mail", Project.MSG_VERBOSE);
  484                   } catch (BuildException e) {
  485                       logBuildException("Failed to initialise UU mail: ", e);
  486                   }
  487               }
  488               // try plain format
  489               if (encoding.equals(PLAIN)
  490                    || (encoding.equals(AUTO) && !autoFound)) {
  491                   mailer = new PlainMailer();
  492                   autoFound = true;
  493                   log("Using plain mail", Project.MSG_VERBOSE);
  494               }
  495               // a valid mailer must be present by now
  496               if (mailer == null) {
  497                   throw new BuildException("Failed to initialise encoding: "
  498                        + encoding);
  499               }
  500               // a valid message is required
  501               if (message == null) {
  502                   message = new Message();
  503                   message.setProject(getProject());
  504               }
  505               // an address to send from is required
  506               if (from == null || from.getAddress() == null) {
  507                   throw new BuildException("A from element is required");
  508               }
  509               // at least one address to send to/cc/bcc is required
  510               if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()) {
  511                   throw new BuildException("At least one of to, cc or bcc must "
  512                        + "be supplied");
  513               }
  514               // set the mimetype if not done already (and required)
  515               if (messageMimeType != null) {
  516                   if (message.isMimeTypeSpecified()) {
  517                       throw new BuildException("The mime type can only be "
  518                            + "specified in one location");
  519                   }
  520                   message.setMimeType(messageMimeType);
  521               }
  522               // set the character set if not done already (and required)
  523               if (charset != null) {
  524                   if (message.getCharset() != null) {
  525                       throw new BuildException("The charset can only be "
  526                            + "specified in one location");
  527                   }
  528                   message.setCharset(charset);
  529               }
  530   
  531               // identify which files should be attached
  532               Vector files = new Vector();
  533               if (attachments != null) {
  534                   Iterator iter = attachments.iterator();
  535   
  536                   while (iter.hasNext()) {
  537                       Resource r = (Resource) iter.next();
  538                       files.addElement(((FileProvider) r.as(FileProvider.class))
  539                                        .getFile());
  540                   }
  541               }
  542               // let the user know what's going to happen
  543               log("Sending email: " + subject, Project.MSG_INFO);
  544               log("From " + from, Project.MSG_VERBOSE);
  545               log("ReplyTo " + replyToList, Project.MSG_VERBOSE);
  546               log("To " + toList, Project.MSG_VERBOSE);
  547               log("Cc " + ccList, Project.MSG_VERBOSE);
  548               log("Bcc " + bccList, Project.MSG_VERBOSE);
  549   
  550               // pass the params to the mailer
  551               mailer.setHost(host);
  552               mailer.setPort(port);
  553               mailer.setUser(user);
  554               mailer.setPassword(password);
  555               mailer.setSSL(ssl);
  556               mailer.setEnableStartTLS(starttls);
  557               mailer.setMessage(message);
  558               mailer.setFrom(from);
  559               mailer.setReplyToList(replyToList);
  560               mailer.setToList(toList);
  561               mailer.setCcList(ccList);
  562               mailer.setBccList(bccList);
  563               mailer.setFiles(files);
  564               mailer.setSubject(subject);
  565               mailer.setTask(this);
  566               mailer.setIncludeFileNames(includeFileNames);
  567               mailer.setHeaders(headers);
  568               mailer.setIgnoreInvalidRecipients(ignoreInvalidRecipients);
  569   
  570               // send the email
  571               mailer.send();
  572   
  573               // let the user know what happened
  574               int count = files.size();
  575   
  576               log("Sent email with " + count + " attachment"
  577                    + (count == 1 ? "" : "s"), Project.MSG_INFO);
  578           } catch (BuildException e) {
  579               logBuildException("Failed to send email: ", e);
  580               if (failOnError) {
  581                   throw e;
  582               }
  583           } catch (Exception e) {
  584             log("Failed to send email: " + e.getMessage(), Project.MSG_WARN);
  585             if (failOnError) {
  586               throw new BuildException(e);
  587             }
  588           } finally {
  589               message = savedMessage;
  590           }
  591       }
  592   
  593       private void logBuildException(String reason, BuildException e) {
  594           Throwable t = e.getCause() == null ? e : e.getCause();
  595           log(reason + t.getMessage(), Project.MSG_WARN);
  596       }
  597   
  598       /**
  599        * Sets the character set of mail message.
  600        * Will be ignored if mimeType contains ....; Charset=... substring or
  601        * encoding is not a <code>mime</code>.
  602        * @param charset the character encoding to use.
  603        * @since Ant 1.6
  604        */
  605       public void setCharset(String charset) {
  606           this.charset = charset;
  607       }
  608   
  609       /**
  610        * Returns the character set of mail message.
  611        *
  612        * @return Charset of mail message.
  613        * @since Ant 1.6
  614        */
  615       public String getCharset() {
  616           return charset;
  617       }
  618   
  619   }
  620   

Save This Page
Home » apache-ant-1.8.1 » org.apache.tools » ant » taskdefs » email » [javadoc | source]