Browse Source

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 <glenn_twiggs@bmc.com>
                 Steve Loughran <steve_l@iseran.com>
                 Erik Hatcher <erik@hatcher.net>
                 Paulo Gaspar <paulo.gaspar@krankikom.de>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269321 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 24 years ago
parent
commit
891ef62c7b
7 changed files with 565 additions and 30 deletions
  1. +1
    -1
      WHATSNEW
  2. +25
    -2
      build.xml
  3. +96
    -0
      docs/manual/OptionalTasks/mimemail.html
  4. +1
    -0
      docs/manual/optionaltasklist.html
  5. +1
    -3
      src/main/org/apache/tools/ant/taskdefs/Definer.java
  6. +432
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java
  7. +9
    -24
      webpage/build.xml

+ 1
- 1
WHATSNEW View File

@@ -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



+ 25
- 2
build.xml View File

@@ -89,7 +89,7 @@
Check to see what optional dependencies are available
===================================================================
-->
<target name="check_for_optional_packages">
<target name="check_for_optional_packages_1">
<available property="jdk1.2+" classname="java.lang.ThreadLocal" />
<available property="jdk1.3+" classname="java.lang.StrictMath" />
<available property="jdk1.4+" classname="java.lang.CharSequence" />
@@ -147,6 +147,18 @@
<available property="jdepend.present"
classname="jdepend.framework.JDepend"
classpathref="classpath"/>
<available property="jaf.present"
classname="javax.activation.DataHandler"
classpathref="classpath"/>
</target>

<target name="check_for_optional_packages"
depends="check_for_optional_packages_1"
if="jaf.present">
<available property="javamail.complete"
classname="javax.mail.Transport"
classpathref="classpath"/>
</target>

@@ -201,7 +213,9 @@
<exclude name="${optional.package}/ejb/IPlanet*.java" unless="jdk1.2+" />
<exclude name="${optional.package}/Javah.java" unless="jdk1.2+" />
<exclude name="${optional.package}/junit/*" unless="junit.present" />
<exclude name="${optional.package}/net/*.java" unless="netcomp.present" />
<exclude name="${optional.package}/net/MimeMail.java" unless="javamail.complete" />
<exclude name="${optional.package}/net/FTP.java" unless="netcomp.present" />
<exclude name="${optional.package}/net/TelnetTask.java" unless="netcomp.present" />
<exclude name="${optional.package}/scm/AntStarTeam*.java" unless="starteam.present" />
<exclude name="${optional.package}/ANTLR.java" unless="antlr.present" />
<exclude name="${optional.package}/ide/VAJ*.java" unless="vaj.present" />
@@ -697,4 +711,13 @@
<antcall target="dist-lite"/>
</target>
<!--
===================================================================
Creates the Ant website
===================================================================
-->
<target name="website"
description="--> creates the Ant website">
<ant dir="webpage" target="docs" />
</target>
</project>

+ 96
- 0
docs/manual/OptionalTasks/mimemail.html View File

@@ -0,0 +1,96 @@
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>Ant User Manual</title>
</head>

<body>

<h2><a name="mimemail">MimeMail</a></h2>
<h3>Description</h3>
<p>Sends SMTP mail with MIME attachments.&nbsp;&nbsp; If&nbsp; no attachments
are needed, use the built-in <a href="http://jakarta.apache.org/ant/manual/CoreTasks/mail.html">Mail</a>
task.&nbsp; <a href="http://java.sun.com/products/javamail/index.html">JavaMail</a>
and <a href="http://java.sun.com/products/javabeans/glasgow/jaf.html">Java
Activation Framework</a> are required for this task.</p>
<p>Multiple files can be attached using <a href="../CoreTypes/fileset.html">FileSets.</a></p>
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">message</td>
<td valign="top">The message body</td>
<td valign="top" align="center" rowspan="2">No, but only one of of 'message' or
'messageFile' may be specified.&nbsp; If not specified, a fileset must be
provided.</td>
</tr>
<tr>
<td valign="top">messageFile</td>
<td valign="top">A filename to read and used as the message body</td>
</tr>
<tr>
<td valign="top">messageMimeType</td>
<td valign="top">MIME type to use for 'message' or 'messageFile' when
attached.</td>
<td align="center" valign="top">No, defaults to "text/plain"</td>
</tr>
<tr>
<td valign="top">tolist</td>
<td valign="top">Comma-separated list of To: recipients</td>
<td valign="top" align="center" rowspan="3">Yes, at least one of 'tolist', 'cclist',
or 'bcclist' must be specified.</td>
</tr>
<tr>
<td valign="top">cclist</td>
<td valign="top">Comma-separated list of CC: recipients</td>
<td valign="top" align="center">&nbsp;</td>
</tr>
<tr>
<td valign="top">bcclist</td>
<td valign="top">Comma-separated list of BCC: recipients</td>
<td valign="top" align="center">&nbsp;</td>
</tr>
<tr>
<td valign="top">mailhost</td>
<td valign="top">Host name of the mail server.</td>
<td valign="top" align="center">No, default to &quot;localhost&quot;</td>
</tr>
<tr>
<td valign="top">subject</td>
<td valign="top">Email subject line.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">from</td>
<td valign="top">Email address of sender.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the build process if an error occurs sending the
e-mail.</td>
<td valign="top" align="center">No, default to &quot;true&quot;</td>
</tr>
</table>
<h3>Examples</h3>
<p><b>Send a single HTML file as the body of a message</b></p>
<pre> &lt;mimemail messageMimeType=&quot;text/html&quot; messageFile=&quot;overview-summary.html&quot;
tolist=&quot;you&quot; subject=&quot;JUnit Test Results: ${TODAY}&quot; from=&quot;me&quot;/&gt;</pre>
<p><b>Sends all files in a directory as attachments</b></p>
<pre> &lt;mimemail message=&quot;See attached files&quot; tolist=&quot;you&quot; subject=&quot;Attachments&quot; from=&quot;me&quot;&gt;
&lt;fileset dir=&quot;.&quot;&gt;
&lt;include name=&quot;dist/*.*&quot;/&gt;
&lt;/fileset&gt;
&lt;/mimemail&gt;
</pre>
<hr><p align="center">Copyright &copy; 2000,2001 Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 1
- 0
docs/manual/optionaltasklist.html View File

@@ -26,6 +26,7 @@
<a href="OptionalTasks/jlink.html">Jlink</a><br>
<a href="OptionalTasks/junit.html">JUnit</a><br>
<a href="OptionalTasks/junitreport.html">JUnitReport</a><br>
<a href="OptionalTasks/mimemail.html">MimeMail</a><br>
<a href="OptionalTasks/mparse.html">MParse</a><br>
<a href="OptionalTasks/native2ascii.html">Native2Ascii</a><br>
<a href="OptionalTasks/netrexxc.html">NetRexxC</a><br>


+ 1
- 3
src/main/org/apache/tools/ant/taskdefs/Definer.java View File

@@ -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) {


+ 432
- 0
src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java View File

@@ -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
* <http://www.apache.org/>.
*/

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);
}
}


+ 9
- 24
webpage/build.xml View File

@@ -1,9 +1,11 @@
<project name="build-site" default="docs" basedir=".">

<!-- Initialization properties -->
<property name="project.name" value="ant"/>
<property name="docs.src" value="./xdocs"/>
<property name="docs.dest" value="./docs"/>
<property name="project.name" value="ant"/>
<property name="docs.src" location="xdocs"/>
<property name="docs.dest" location="docs"/>
<property name="project.file" value="stylesheets/project.xml" />
<property name="templ.path" location="xdocs/stylesheets" />

<path id="anakia.classpath">
<fileset dir="../../jakarta-site2/lib">
@@ -32,36 +34,19 @@
<anakia basedir="${docs.src}" destdir="${docs.dest}/"
extension=".html" style="./site.vsl"
projectFile="stylesheets/project.xml"
projectFile="${project.file}"
excludes="**/stylesheets/** faq.xml"
includes="**/*.xml"
lastModifiedCheck="true"
templatePath="./xdocs/stylesheets">
templatePath="${templ.path}">
</anakia>

<anakia basedir="${docs.src}" destdir="${docs.dest}/"
extension=".html" style="./faq.vsl"
projectFile="stylesheets/project.xml"
projectFile="${project.file}"
includes="faq.xml"
lastModifiedCheck="true"
templatePath="./xdocs/stylesheets">
templatePath="${templ.path}">
</anakia>

<!-- In case we have images some day
<copy todir="${docs.dest}/images" filtering="no">
<fileset dir="${docs.src}/images">
<include name="**/*.gif"/>
<include name="**/*.jpeg"/>
<include name="**/*.jpg"/>
</fileset>
</copy>
-->
<!-- In case we have CSS someday
<copy todir="${docs.dest}" filtering="no">
<fileset dir="${docs.src}">
<include name="**/*.css"/>
</fileset>
</copy>
-->
</target>
</project>

Loading…
Cancel
Save