/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-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.mail;

import java.io.*;
import java.util.*;
import org.apache.tools.ant.*;
//import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;

//imported for the mail api
import javax.mail.*;
import javax.mail.internet.*;
//imported for data source and handler
import javax.activation.*;

/**
 * A task to send SMTP email. This version has near identical syntax to
 * the SendEmail task, but is mime aware. It also requires J2EE 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
 * @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;
    /**
     * recipients
     */
    private String toList = null;
    /**
     * subject field
     */
    private String subject = null;
    /**
     * file list
     */
    private Vector files = 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;
    }


    /**
     * 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 "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;
    }



    /**
     * 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;
    }


    /**
     * Sets the file parameter of this build task.
     *
     * @param filenames Filenames to include as the message body of this
     *      email.
     */
    public void setFiles(String filenames) {
        StringTokenizer t = new StringTokenizer(filenames, ", ");

        while (t.hasMoreTokens()) {
            files.addElement(project.resolveFile(t.nextToken()));
        }
    }



    /**
     * verify parameters
     *
     * @throws BuildException if something is invalid
     */
    public void validate() {
        if (from == null) {
            throw new BuildException("Attribute \"from\" is required.");
        }

        if (toList == null) {
            throw new BuildException("Attribute \"toList\" is required.");
        }

        if (message == null && files.isEmpty()) {
            throw new BuildException("Attribute \"file\" or \"message\" is required.");
        }
    }


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


    /**
     * 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));
        //build the recipient list, first cracking the string open
        //into a list to get the size
        Vector addresses = new Vector();
        int count = 0;
        StringTokenizer t = new StringTokenizer(toList, ", ", false);
        while (t.hasMoreTokens()) {
            String to = t.nextToken();
            log("to: " + to, Project.MSG_VERBOSE);
            msg.addRecipient(Message.RecipientType.TO,
                    new InternetAddress(to));
            count++;
        }
        if (count == 0) {
            throw new BuildException("no recipients specified");
        }
        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 (message != null) {
            MimeBodyPart textbody = new MimeBodyPart();
            textbody.setContent(message, messageMimeType);
            attachments.addBodyPart(textbody);
        }
        //then the fileset
        if (!files.isEmpty()) {
            for (Enumeration e = files.elements(); e.hasMoreElements(); ) {
                File file = (File) e.nextElement();
                MimeBodyPart body;
                body = new MimeBodyPart();
                if (!file.exists() || !file.canRead()) {
                    throw new BuildException("File \"" + file.getName()
                             + "\" 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);
            }
        }
        msg.setContent(attachments);
        log("sending email ");
        Transport.send(msg);
    }

}

