blob: 251096ff0f424e9d8963363dc3667145b51e51c0 [file] [log] [blame]
/*
* 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);
}
}