From 891ef62c7b4dec400ee766d775e0066a04fb7adc Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Wed, 11 Jul 2001 16:11:47 +0000 Subject: [PATCH] New task mimemail - this task requires JavaMail (and JAF) that's why it is optional and doesn't replace the existing mail task. The main improvement is that it supports attachments you can specify via a fileset. Submitted by: Glenn Twiggs Steve Loughran Erik Hatcher Paulo Gaspar git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269321 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 2 +- build.xml | 27 +- docs/manual/OptionalTasks/mimemail.html | 96 ++++ docs/manual/optionaltasklist.html | 1 + .../apache/tools/ant/taskdefs/Definer.java | 4 +- .../ant/taskdefs/optional/net/MimeMail.java | 432 ++++++++++++++++++ webpage/build.xml | 33 +- 7 files changed, 565 insertions(+), 30 deletions(-) create mode 100644 docs/manual/OptionalTasks/mimemail.html create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java diff --git a/WHATSNEW b/WHATSNEW index 1e6ba4fb9..7ca362571 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -32,7 +32,7 @@ Other changes: -------------- * New tasks: ear, p4counter, record, cvspass, vsscheckin, vsscheckout, - typedef, sleep + typedef, sleep, mimemail * Ant now uses JAXP 1.1 diff --git a/build.xml b/build.xml index 44aee2832..09254e4ed 100644 --- a/build.xml +++ b/build.xml @@ -89,7 +89,7 @@ Check to see what optional dependencies are available =================================================================== --> - + @@ -147,6 +147,18 @@ + + + + + + @@ -201,7 +213,9 @@ - + + + @@ -697,4 +711,13 @@ + + + + diff --git a/docs/manual/OptionalTasks/mimemail.html b/docs/manual/OptionalTasks/mimemail.html new file mode 100644 index 000000000..2cc6e367c --- /dev/null +++ b/docs/manual/OptionalTasks/mimemail.html @@ -0,0 +1,96 @@ + + + + +Ant User Manual + + + + +

MimeMail

+

Description

+

Sends SMTP mail with MIME attachments.   If  no attachments +are needed, use the built-in Mail +task.  JavaMail +and Java +Activation Framework are required for this task.

+

Multiple files can be attached using FileSets.

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
messageThe message bodyNo, but only one of of 'message' or + 'messageFile' may be specified.  If not specified, a fileset must be + provided.
messageFileA filename to read and used as the message body
messageMimeTypeMIME type to use for 'message' or 'messageFile' when + attached.No, defaults to "text/plain"
tolistComma-separated list of To: recipientsYes, at least one of 'tolist', 'cclist', + or 'bcclist' must be specified.
cclistComma-separated list of CC: recipients 
bcclistComma-separated list of BCC: recipients 
mailhostHost name of the mail server.No, default to "localhost"
subjectEmail subject line.No
fromEmail address of sender.Yes
failonerrorStop the build process if an error occurs sending the + e-mail.No, default to "true"
+

Examples

+

Send a single HTML file as the body of a message

+
	<mimemail messageMimeType="text/html" messageFile="overview-summary.html" 
+		tolist="you" subject="JUnit Test Results: ${TODAY}" from="me"/>
+

Sends all files in a directory as attachments

+
	<mimemail message="See attached files" tolist="you" subject="Attachments" from="me">
+	    <fileset dir=".">
+	        <include name="dist/*.*"/>
+	    </fileset>
+	</mimemail>
+
+

Copyright © 2000,2001 Apache Software Foundation. All rights +Reserved.

+ + + + diff --git a/docs/manual/optionaltasklist.html b/docs/manual/optionaltasklist.html index fb925458e..eeef161e2 100644 --- a/docs/manual/optionaltasklist.html +++ b/docs/manual/optionaltasklist.html @@ -26,6 +26,7 @@ Jlink
JUnit
JUnitReport
+MimeMail
MParse
Native2Ascii
NetRexxC
diff --git a/src/main/org/apache/tools/ant/taskdefs/Definer.java b/src/main/org/apache/tools/ant/taskdefs/Definer.java index 86af92d20..0bbeb839b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Definer.java +++ b/src/main/org/apache/tools/ant/taskdefs/Definer.java @@ -96,7 +96,6 @@ public abstract class Definer extends Task { throw new BuildException(msg); } try { - ClassLoader loader = null; AntClassLoader al = null; if (classpath != null) { al = new AntClassLoader(project, classpath); @@ -107,9 +106,8 @@ public abstract class Definer extends Task { // task we want to define will never be a Task but always // be wrapped into a TaskAdapter. al.addSystemPackageRoot("org.apache.tools.ant"); - loader = al; - Class c = loader.loadClass(value); + Class c = al.loadClass(value); AntClassLoader.initializeClass(c); addDefinition(name, c); } catch (ClassNotFoundException cnfe) { diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java new file mode 100644 index 000000000..251096ff0 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java @@ -0,0 +1,432 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.optional.net; + + +// Standard SDK imports +import java.util.Properties; +import java.util.Vector; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +//imported for the mail api +import javax.mail.Address; +import javax.mail.Session; +import javax.mail.Message; +import javax.mail.BodyPart; +import javax.mail.Multipart; +import javax.mail.SendFailedException; +import javax.mail.MessagingException; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.AddressException; + +//imported for data source and handler +import javax.activation.DataHandler; +import javax.activation.FileDataSource; + +// Ant imports +import org.apache.tools.ant.Task; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.FileScanner; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.FileSet; + + + +/** + * A task to send SMTP email. This version has near identical syntax to + * the SendEmail task, but is MIME aware. It also requires Sun's mail.jar and + * activation.jar to compile and execute, which puts it clearly into the + * very optional category. + * + * @author glenn_twiggs@bmc.com + * @author steve_l@iseran.com steve loughran + * @author erik@hatcher.net Erik Hatcher + * @author paulo.gaspar@krankikom.de Paulo Gaspar + * @created 01 May 2001 + */ +public class MimeMail extends Task { + /** + * failure flag + */ + private boolean failOnError = true; + + /** + * sender + */ + private String from = null; + + /** + * host running SMTP + */ + private String mailhost = "localhost"; + + /** + * any text + */ + private String message = null; + + + /** + * message file (mutually exclusive from message) + */ + private File messageFile = null; + + /** + * TO recipients + */ + private String toList = null; + + /** + * CC (Carbon Copy) recipients + */ + protected String ccList = null; + + /** + * BCC (Blind Carbon Copy) recipients + */ + protected String bccList = null; + + /** + * subject field + */ + private String subject = null; + + /** + * file list + */ + private Vector filesets = new Vector(); + + /** + * type of the text message, plaintext by default but text/html or + * text/xml is quite feasible + */ + private String messageMimeType = "text/plain"; + + /** + * Creates new instance + */ + public MimeMail() { + } + + + /** + * Sets the FailOnError attribute of the MimeMail object + * + * @param failOnError The new FailOnError value + */ + public void setFailOnError(boolean failOnError) { + this.failOnError = failOnError; + } + + /** + * Adds a set of files (nested fileset attribute). + */ + public void addFileset(FileSet set) { + filesets.addElement(set); + } + + /** + * Sets the toList parameter of this build task. + * + * @param toList Comma-separated list of email recipient addreses. + */ + public void setToList(String toList) { + this.toList = toList; + } + + /** + * Sets the toList parameter of this build task. + * + * @param toList Comma-separated list of email recipient addreses. + */ + public void setCcList(String ccList) { + this.ccList = ccList; + } + + /** + * Sets the toList parameter of this build task. + * + * @param toList Comma-separated list of email recipient addreses. + */ + public void setBccList(String bccList) { + this.bccList = bccList; + } + + + /** + * Sets the "from" parameter of this build task. + * + * @param from Email address of sender. + */ + public void setFrom(String from) { + this.from = from; + } + + + /** + * Sets the mailhost parameter of this build task. + * + * @param mailhost Mail host name. + */ + public void setMailhost(String mailhost) { + this.mailhost = mailhost; + } + + + /** + * Sets the message parameter of this build task. + * + * @param message Message body of this email. + */ + public void setMessage(String message) { + this.message = message; + } + + public void setMessageFile(File messageFile) { + this.messageFile = messageFile; + } + + + /** + * set type of the text message, plaintext by default but text/html + * or text/xml is quite feasible + * + * @param type The new MessageMimeType value + */ + public void setMessageMimeType(String type) { + this.messageMimeType = type; + } + + /** + * Sets the subject parameter of this build task. + * + * @param subject Subject of this email. + */ + public void setSubject(String subject) { + this.subject = subject; + } + + + /** + * verify parameters + * + * @throws BuildException if something is invalid + */ + public void validate() { + if (from == null) { + throw new BuildException("Attribute \"from\" is required."); + } + + if ((toList == null) && (ccList == null) && (bccList == null)) { + throw new BuildException("Attribute \"toList\", \"ccList\" or \"bccList\" is required."); + } + + if (message == null && filesets.isEmpty() && messageFile == null) { + throw new BuildException("FileSet, \"message\", or \"messageFile\" is required."); + } + + if (message != null && messageFile != null) { + throw new BuildException("Only one of \"message\" or \"messageFile\" may be specified."); + } + } + + + /** + * Executes this build task. throws org.apache.tools.ant.BuildException + * if there is an error during task execution. + * + * @exception BuildException Description of Exception + */ + public void execute() + throws BuildException { + try { + validate(); + doMail(); + } + catch (Exception e) { + if (failOnError) { + throw new BuildException(e); + } + else { + String text = e.toString(); + log(text, Project.MSG_ERR); + } + } + } + + + // helper method to add recipients + private static void addRecipients( MimeMessage msg, + Message.RecipientType recipType, + String addrUserName, + String addrList + ) throws MessagingException, BuildException { + if ((null == addrList) || (addrList.trim().length() <= 0)) + return; + + try { + InternetAddress[] addrArray = InternetAddress.parse(addrList); + + if ((null == addrArray) || (0 == addrArray.length)) + throw new BuildException("Empty " + addrUserName + " recipients list was specified"); + + msg.setRecipients(recipType, addrArray); + } + catch(AddressException ae) { + throw new BuildException("Invalid " + addrUserName + " recipient list"); + } + } + + /** + * here is where the mail is sent + * + * @exception MessagingException Description of Exception + * @exception AddressException Description of Exception + * @exception BuildException Description of Exception + */ + public void doMail() + throws MessagingException, AddressException, BuildException { + Properties props = new Properties(); + props.put("mail.smtp.host", mailhost); + + //Aside, the JDK is clearly unaware of the scottish 'session', which + //involves excessive quantities of alcohol :-) + Session sesh = Session.getDefaultInstance(props, null); + + //create the message + MimeMessage msg = new MimeMessage(sesh); + + //set the sender + log("message sender: " + from, Project.MSG_VERBOSE); + msg.setFrom(new InternetAddress(from)); + + // add recipient lists + addRecipients(msg, Message.RecipientType.TO, "To", toList); + addRecipients(msg, Message.RecipientType.CC, "Cc", ccList); + addRecipients(msg, Message.RecipientType.BCC, "Bcc", bccList); + + if (subject != null) { + log("subject: " + subject, Project.MSG_VERBOSE); + msg.setSubject(subject); + } + + //now the complex bit; adding multiple mime objects. And guessing + //the file type + MimeMultipart attachments = new MimeMultipart(); + + //first a message + if (messageFile != null) { + int size = (int)messageFile.length(); + byte data[] = new byte[size]; + + try { + FileInputStream inStream = new FileInputStream(messageFile); + inStream.read(data); + inStream.close(); + message = new String(data); + } catch (IOException e) { + throw new BuildException(e); + } + } + + if (message != null) { + MimeBodyPart textbody = new MimeBodyPart(); + textbody.setContent(message, messageMimeType); + attachments.addBodyPart(textbody); + } + + for (int i = 0; i < filesets.size(); i++) + { + FileSet fs = (FileSet) filesets.elementAt(i); + if (fs != null) + { + DirectoryScanner ds = fs.getDirectoryScanner(project); + String[] dsfiles = ds.getIncludedFiles(); + File baseDir = ds.getBasedir(); + + for (int j = 0; j < dsfiles.length; j++) + { + File file = new File(baseDir, dsfiles[j]); + MimeBodyPart body; + body = new MimeBodyPart(); + if (!file.exists() || !file.canRead()) { + throw new BuildException("File \"" + file.getAbsolutePath() + + "\" does not exist or is not readable."); + } + log("Attaching " + file.toString()+" - " +file.length()+" bytes", + Project.MSG_VERBOSE); + FileDataSource fileData = new FileDataSource(file); + DataHandler fileDataHandler = new DataHandler(fileData); + body.setDataHandler(fileDataHandler); + body.setFileName(file.getName()); + attachments.addBodyPart(body); + } // for j + } // if (fs != null) + } // for i + + msg.setContent(attachments); + log("sending email "); + Transport.send(msg); + } +} + diff --git a/webpage/build.xml b/webpage/build.xml index c98637480..942ed599e 100644 --- a/webpage/build.xml +++ b/webpage/build.xml @@ -1,9 +1,11 @@ - - - + + + + + @@ -32,36 +34,19 @@ + templatePath="${templ.path}"> + templatePath="${templ.path}"> - - -