blob: e0e051c6f371f431310bf4ee25c4382f27bb27fb [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2002 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.email;
// Ant imports
import java.io.File;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
/**
* A task to send SMTP email. This is a refactoring of the SendMail and
* MimeMail tasks such that both are within a single task.
*
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
* @author glenn_twiggs@bmc.com
* @author steve_l@iseran.com steve loughran
* @author ehatcher@apache.org Erik Hatcher
* @author paulo.gaspar@krankikom.de Paulo Gaspar
* @author roxspring@imapmail.org Rob Oxspring
* @since Ant 1.5
* @ant.task name="mail" category="network"
*/
public class EmailTask
extends Task {
/** Constant to show that the best available mailer should be used. */
public static final String AUTO = "auto";
/** Constant to allow the Mime mailer to be requested */
public static final String MIME = "mime";
/** Constant to allow the UU mailer to be requested */
public static final String UU = "uu";
/** Constant to allow the plaintext mailer to be requested */
public static final String PLAIN = "plain";
/**
* Enumerates the encoding constants
*/
public static class Encoding extends EnumeratedAttribute {
/**
* finds the valid encoding values
*
* @return a list of valid entries
*/
public String[] getValues() {
return new String[]
{AUTO, MIME, UU, PLAIN};
}
}
private String encoding = AUTO;
/** host running SMTP */
private String host = "localhost";
private int port = 25;
/** subject field */
private String subject = null;
/** any text */
private Message message = null;
/** failure flag */
private boolean failOnError = true;
private boolean includeFileNames = false;
private String messageMimeType = null;
/** sender */
private EmailAddress from = null;
/** TO recipients */
private Vector toList = new Vector();
/** CC (Carbon Copy) recipients */
private Vector ccList = new Vector();
/** BCC (Blind Carbon Copy) recipients */
private Vector bccList = new Vector();
/** file list */
private Vector files = new Vector();
private Vector filesets = new Vector();
/**
* Allows the build writer to choose the preferred encoding method
*
* @param encoding The encoding (one of AUTO,MIME,UU,PLAIN)
*/
public void setEncoding(Encoding encoding) {
this.encoding = encoding.getValue();
}
/**
* Sets the mail server port
*
* @param port The port to use
*/
public void setMailport(int port) {
this.port = port;
}
/**
* Sets the host
*
* @param host The host to connect to
*/
public void setMailhost(String host) {
this.host = host;
}
/**
* Sets the subject line of the email
*
* @param subject Subject of this email.
*/
public void setSubject(String subject) {
this.subject = subject;
}
/**
* Shorthand method to set the message
*
* @param message Message body of this email.
*/
public void setMessage(String message) {
if (this.message != null) {
throw new BuildException("Only one message can be sent in an "
+ "email");
}
this.message = new Message(message);
this.message.setProject(getProject());
}
/**
* Shorthand method to set the message from a file
*
* @param file The file from which to take the message
*/
public void setMessageFile(File file) {
if (this.message != null) {
throw new BuildException("Only one message can be sent in an "
+ "email");
}
this.message = new Message(file);
this.message.setProject(getProject());
}
/**
* Shorthand method to set type of the text message, text/plain 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;
}
/**
* Add a message elemnt
*
* @param message The message object
* @throws BuildException if a message has already been added
*/
public void addMessage(Message message)
throws BuildException {
if (this.message != null) {
throw new BuildException("Only one message can be sent in an "
+ "email");
}
this.message = message;
}
/**
* Adds a from address element
*
* @param address The address to send from
*/
public void addFrom(EmailAddress address) {
if (this.from != null) {
throw new BuildException("Emails can only be from one address");
}
this.from = address;
}
/**
* Shorthand to set the from address element
*
* @param address The address to send mail from
*/
public void setFrom(String address) {
if (this.from != null) {
throw new BuildException("Emails can only be from one address");
}
this.from = new EmailAddress(address);
}
/**
* Adds a to address element
*
* @param address An email address
*/
public void addTo(EmailAddress address) {
toList.addElement(address);
}
/**
* Adds "to" address elements
*
* @param list Comma separated list of addresses
*/
public void setToList(String list) {
StringTokenizer tokens = new StringTokenizer(list, ",");
while (tokens.hasMoreTokens()) {
toList.addElement(new EmailAddress(tokens.nextToken()));
}
}
/**
* Adds "cc" address element
*
* @param address The email address
*/
public void addCc(EmailAddress address) {
ccList.addElement(address);
}
/**
* Adds "cc" address elements
*
* @param list Comma separated list of addresses
*/
public void setCcList(String list) {
StringTokenizer tokens = new StringTokenizer(list, ",");
while (tokens.hasMoreTokens()) {
ccList.addElement(new EmailAddress(tokens.nextToken()));
}
}
/**
* Adds "bcc" address elements
*
* @param address The email address
*/
public void addBcc(EmailAddress address) {
bccList.addElement(address);
}
/**
* Adds "bcc" address elements
*
* @param list comma separated list of addresses
*/
public void setBccList(String list) {
StringTokenizer tokens = new StringTokenizer(list, ",");
while (tokens.hasMoreTokens()) {
bccList.addElement(new EmailAddress(tokens.nextToken()));
}
}
/**
* Indicates whether BuildExceptions should be passed back to the core
*
* @param failOnError The new FailOnError value
*/
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
/**
* Adds a list of files to be attached
*
* @param filenames Comma separated list of files
*/
public void setFiles(String filenames) {
StringTokenizer t = new StringTokenizer(filenames, ", ");
while (t.hasMoreTokens()) {
files.addElement(project.resolveFile(t.nextToken()));
}
}
/**
* Adds a set of files (nested fileset attribute).
*
* @param fs The fileset
*/
public void addFileset(FileSet fs) {
filesets.addElement(fs);
}
/**
* Sets Includefilenames attribute
*
* @param includeFileNames Whether to include filenames in the text of the
* message
*/
public void setIncludefilenames(boolean includeFileNames) {
this.includeFileNames = includeFileNames;
}
/**
* Identifies whether file names should be included
*
* @return Identifies whether file names should be included
*/
public boolean getIncludeFileNames() {
return includeFileNames;
}
/** Sends an email */
public void execute() {
Message savedMessage = message;
Vector savedFiles = (Vector) files.clone();
try {
Mailer mailer = null;
// prepare for the auto select mechanism
boolean autoFound = false;
// try MIME format
if (encoding.equals(MIME)
|| (encoding.equals(AUTO) && !autoFound)) {
try {
mailer =
(Mailer) Class.forName("org.apache.tools.ant.taskdefs.email.MimeMailer")
.newInstance();
autoFound = true;
log("Using MIME mail", Project.MSG_VERBOSE);
} catch (Throwable e) {
log("Failed to initialise MIME mail", Project.MSG_WARN);
}
}
// try UU format
if (encoding.equals(UU)
|| (encoding.equals(AUTO) && !autoFound)) {
try {
mailer =
(Mailer) Class.forName("org.apache.tools.ant.taskdefs.email.UUMailer")
.newInstance();
autoFound = true;
log("Using UU mail", Project.MSG_VERBOSE);
} catch (Throwable e) {
log("Failed to initialise UU mail", Project.MSG_WARN);
}
}
// try plain format
if (encoding.equals(PLAIN)
|| (encoding.equals(AUTO) && !autoFound)) {
mailer = new PlainMailer();
autoFound = true;
log("Using plain mail", Project.MSG_VERBOSE);
}
// a valid mailer must be present by now
if (mailer == null) {
throw new BuildException("Failed to initialise encoding: "
+ encoding);
}
// a valid message is required
if (message == null) {
message = new Message();
message.setProject(getProject());
}
// an address to send from is required
if (from == null || from.getAddress() == null) {
throw new BuildException("A from element is required");
}
// at least one address to send to/cc/bcc is required
if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()) {
throw new BuildException("At least one of to,cc or bcc must "
+ "be supplied");
}
// set the mimetype if not done already (and required)
if (messageMimeType != null) {
if (message.isMimeTypeSpecified()) {
throw new BuildException("The mime type can only be "
+ "specified in one location");
} else {
message.setMimeType(messageMimeType);
}
}
// identify which files should be attached
Enumeration e = filesets.elements();
while (e.hasMoreElements()) {
FileSet fs = (FileSet) e.nextElement();
DirectoryScanner ds = fs.getDirectoryScanner(project);
String[] includedFiles = ds.getIncludedFiles();
File baseDir = ds.getBasedir();
for (int j = 0; j < includedFiles.length; ++j) {
File file = new File(baseDir, includedFiles[j]);
files.addElement(file);
}
}
// let the user know what's going to happen
log("Sending email: " + subject, Project.MSG_INFO);
log("From " + from, Project.MSG_VERBOSE);
log("To " + toList, Project.MSG_VERBOSE);
log("Cc " + ccList, Project.MSG_VERBOSE);
log("Bcc " + bccList, Project.MSG_VERBOSE);
// pass the params to the mailer
mailer.setHost(host);
mailer.setPort(port);
mailer.setMessage(message);
mailer.setFrom(from);
mailer.setToList(toList);
mailer.setCcList(ccList);
mailer.setBccList(bccList);
mailer.setFiles(files);
mailer.setSubject(subject);
mailer.setTask(this);
mailer.setIncludeFileNames(includeFileNames);
// send the email
mailer.send();
// let the user know what happened
int count = files.size();
log("Sent email with " + count + " attachment"
+ (count == 1 ? "" : "s"), Project.MSG_INFO);
} catch (BuildException e) {
log("Failed to send email", Project.MSG_WARN);
if (failOnError) {
throw e;
}
} finally {
message = savedMessage;
files = savedFiles;
}
}
}