/*
 * Copyright 2001-2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 ( the "License" );
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.mail;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.commons.lang.StringUtils;

/**
 * The base class for all email messages.  This class sets the
 * sender's email & name, receiver's email & name, subject, and the
 * sent date.  Subclasses are responsible for setting the message
 * body.
 *
 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
 * @author <a href="mailto:greg@shwoop.com">Greg Ritter</a>
 * @author <a href="mailto:unknown">Regis Koenig</a>
 * @author <a href="mailto:colin.chalmers@maxware.nl">Colin Chalmers</a>
 * @author <a href="mailto:matthias@wessendorf.net">Matthias Wessendorf</a>
 * @author <a href="mailto:corey.scott@gmail.com">Corey Scott</a>
 * @version $Revision: 1.1 $ $Date: 2004/11/25 09:56:56 $
 * @version $Id: Email.java,v 1.1 2004/11/25 09:56:56 epugh Exp $
 */
public abstract class Email
{
    /** Constants used by Email classes. */

    /** */
    public static final String SENDER_EMAIL = "sender.email";
    /** */
    public static final String SENDER_NAME = "sender.name";
    /** */
    public static final String RECEIVER_EMAIL = "receiver.email";
    /** */
    public static final String RECEIVER_NAME = "receiver.name";
    /** */
    public static final String EMAIL_SUBJECT = "email.subject";
    /** */
    public static final String EMAIL_BODY = "email.body";
    /** */
    public static final String CONTENT_TYPE = "content.type";

    /** */
    public static final String MAIL_HOST = "mail.host";
    /** */
    public static final String MAIL_PORT = "mail.smtp.port";
    /** */
    public static final String MAIL_SMTP_FROM = "mail.smtp.from";
    /** */
    public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
    /** */
    public static final String MAIL_TRANSPORT_PROTOCOL =
        "mail.transport.protocol";
    /** */
    public static final String SMTP = "smtp";
    /** */
    public static final String TEXT_HTML = "text/html";
    /** */
    public static final String TEXT_PLAIN = "text/plain";
    /** */
    public static final String ATTACHMENTS = "attachments";
    /** */
    public static final String FILE_SERVER = "file.server";
    /** */
    public static final String MAIL_DEBUG = "mail.debug";

    /** */
    public static final String KOI8_R = "koi8-r";
    /** */
    public static final String ISO_8859_1 = "iso-8859-1";
    /** */
    public static final String US_ASCII = "us-ascii";

    /** The email message to send. */
    protected MimeMessage message;

    /** The charset to use for this message */
    protected String charset;

    /** The Address of the sending party, mandatory */
    protected InternetAddress fromAddress;

    /** The Subject  */
    protected String subject;

    /** An attachment  */
    protected MimeMultipart emailBody;

    /** The content  */
    protected Object content;

    /** The content type  */
    protected String contentType;

    /** Set session debugging on or off */
    protected boolean debug = false;

    /** Sent date */
    protected Date sentDate;

    /** The Session to mail with */
    private Session session;

    /**
     * Instance of an <code>Authenticator</code> object that will be used
     * when authentication is requested from the mail server.
     */
    protected Authenticator authenticator;

    /**
     * The hostname of the mail server with which to connect. If null will try
     * to get property from system.properties. If still null, quit
     */
    protected String hostName;

    /**
     * The port number of the mail server to connect to.  
     * Defaults to the standard port ( 25 ).
     */
    protected String smtpPort = "25";

    /** List of "to" email adresses */
    protected ArrayList toList = new ArrayList();

    /** List of "cc" email adresses */
    protected ArrayList ccList = new ArrayList();

    /** List of "bcc" email adresses */
    protected ArrayList bccList = new ArrayList();

    /** List of "replyTo" email adresses */
    protected ArrayList replyList = new ArrayList();

    /** 
     * Address to which undeliverable mail should be sent. 
     * Because this is handled by JavaMail as a String property
     * in the mail session, this property is of type <code>String</code>
     * rather than <code>InternetAddress</code>.
     */
    protected String bounceAddress = null;

    /**
     * Used to specify the mail headers.  Example:
     *
     * X-Mailer: Sendmail, X-Priority: 1( highest )
     * or  2( high ) 3( normal ) 4( low ) and 5( lowest )
     * Disposition-Notification-To: user@domain.net
     */
    protected Hashtable headers = new Hashtable();

    /**
     * Used to determine whether to use pop3 before smtp, and if so the settings.
     */

    /** */
    protected boolean popBeforeSmtp = false;
    /** */
    protected String popHost = null;
    /** */
    protected String popUsername = null;
    /** */
    protected String popPassword = null;

    /**
     * Setting to true will enable the display of debug information.
     *
     * @param d A boolean.
     */
    public void setDebug(boolean d)
    {
        this.debug = d;
    }

    /**
     * Sets the userName and password if authentication is needed.  If this
     * method is not used, no authentication will be performed.
     * <p>
     * This method will create a new instance of
     * <code>DefaultAuthenticator</code> using the supplied parameters.
     *
     * @param userName User name for the SMTP server
     * @param password password for the SMTP server
     * @see DefaultAuthenticator
     * @see #setAuthenticator
     */
    public void setAuthentication(String userName, String password)
    {
        this.authenticator = new DefaultAuthenticator(userName, password);
        this.setAuthenticator(this.authenticator);
    }

    /**
     * Sets the <code>Authenticator</code> to be used when authentication
     * is requested from the mail server.
     * <p>
     * This method should be used when your outgoing mail server requires
     * authentication.  Your mail server must also support RFC2554.
     *
     * @param newAuthenticator the <code>Authenticator</code> object.
     * @see Authenticator
     */
    public void setAuthenticator(Authenticator newAuthenticator)
    {
        this.authenticator = newAuthenticator;
    }

    /**
     * Set the charset of the message.
     *
     * @param newCharset A String.
     */
    public void setCharset(String newCharset)
    {
        this.charset = newCharset;
    }

    /**
     * Set the emailBody to a MimeMultiPart
     *
     * @param aMimeMultipart aMimeMultipart
     */
    public void setContent(MimeMultipart aMimeMultipart)
    {
        this.emailBody = aMimeMultipart;
    }

    /**
     * Set the content & contentType
     *
     * @param   aObject aObject
     * @param   aContentType aContentType
     */
    public void setContent(Object aObject, String aContentType)
    {
        this.content = aObject;
        if (!StringUtils.isNotEmpty(aContentType))
        {
            this.contentType = null;
        }
        else
        {
            // set the content type
            this.contentType = aContentType;

            // set the charset if the input was properly formed
            String strMarker = "; charset=";
            int charsetPos = aContentType.toLowerCase().indexOf(strMarker);

            if (charsetPos != -1)
            {
                // find the next space (after the marker)
                charsetPos += strMarker.length();
                int intCharsetEnd =
                    aContentType.toLowerCase().indexOf(" ", charsetPos);

                if (intCharsetEnd != -1)
                {
                    this.charset =
                        aContentType.substring(charsetPos, intCharsetEnd);
                }
                else
                {
                    this.charset = aContentType.substring(charsetPos);
                }
            }
        }
    }

    /**
     * Set the hostname of the outgoing mail server
     *
     * @param   aHostName aHostName
     */
    public void setHostName(String aHostName)
    {
        this.hostName = aHostName;
    }

    /**
     * Set the port number of the outgoing mail server.
     * @param   aPortNumber aPortNumber
     */
    public void setSmtpPort(int aPortNumber)
    {
        if (aPortNumber < 1)
        {
            throw new IllegalArgumentException(
                "Cannot connect to a port number that is less than 1 ( "
                    + aPortNumber
                    + " )");
        }

        this.smtpPort = Integer.toString(aPortNumber);
    }

    /**
     * Supply a mail Session object to use
     * @param aSession mail session to be used
     */
    public void setMailSession(Session aSession)
    {
        this.session = aSession;
    }
    /**
     * Initialise a mailsession object
     *
     * @return A Session.
     * @throws MessagingException thrown when host name was not set
     */
    protected Session getMailSession() throws MessagingException
    {
        if (this.session == null)
        {
            Properties properties = new Properties(System.getProperties());
            properties.setProperty(MAIL_TRANSPORT_PROTOCOL, SMTP);

            if (!StringUtils.isNotEmpty(this.hostName))
            {
                this.hostName = properties.getProperty(MAIL_HOST);
            }

            if (!StringUtils.isNotEmpty(this.hostName))
            {
                throw new MessagingException(
                    "Cannot find valid hostname for mail session");
            }

            properties.setProperty(MAIL_PORT, smtpPort);
            properties.setProperty(MAIL_HOST, hostName);
            properties.setProperty(MAIL_DEBUG, String.valueOf(this.debug));

            if (this.authenticator != null)
            {
                properties.setProperty(MAIL_SMTP_AUTH, "true");
            }

            if (this.bounceAddress != null)
            {
                properties.setProperty(MAIL_SMTP_FROM, this.bounceAddress);
            }

            // changed this (back) to getInstance due to security exceptions 
            // caused when testing using maven
            this.session =
                Session.getInstance(properties, this.authenticator);
        }
        return this.session;
    }

    /**
     * Set the FROM field of the email.
     *
     * @param email A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email setFrom(String email) throws MessagingException
    {
        return setFrom(email, null);
    }

    /**
     * Set the FROM field of the email.
     *
     * @param email A String.
     * @param name A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email setFrom(String email, String name) throws MessagingException
    {
        try
        {
            // check name input
            if (!StringUtils.isNotEmpty(name))
            {
                name = email;
            }

            // set/update the from address
            if (this.fromAddress == null)
            {
                if (StringUtils.isNotEmpty(this.charset))
                {
                    this.fromAddress =
                        new InternetAddress(email, name, this.charset);
                }
                else
                {
                    this.fromAddress = new InternetAddress(email, name);
                }
            }
            else
            {
                this.fromAddress.setAddress(email);
                this.fromAddress.setPersonal(name);
            }
        }
        catch (UnsupportedEncodingException e)
        {
            throw new MessagingException("cannot set from", e);
        }

        return this;
    }

    /**
     * Add a recipient TO to the email.
     *
     * @param email A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addTo(String email) throws MessagingException
    {
        return addTo(email, null);
    }

    /**
     * Add a recipient TO to the email.
     *
     * @param email A String.
     * @param name A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addTo(String email, String name) throws MessagingException
    {
        try
        {
            if (!StringUtils.isNotEmpty(name))
            {
                name = email;
            }

            if (StringUtils.isNotEmpty(this.charset))
            {
                this.toList.add(new InternetAddress(email, name, this.charset));
            }
            else
            {
                this.toList.add(new InternetAddress(email, name));
            }
        }
        catch (UnsupportedEncodingException e)
        {
            throw new MessagingException("cannot add to", e);
        }
        return this;
    }

    /**
     * Set a list of "TO" addresses
     *
     * @param   aCollection collection of InternetAddress objects
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email setTo(Collection aCollection) throws MessagingException
    {
        if (aCollection == null || aCollection.isEmpty())
        {
            throw new MessagingException("Address List provided was invalid");
        }

        this.toList = new ArrayList(aCollection);
        return this;
    }

    /**
     * Add a recipient CC to the email.
     *
     * @param email A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addCc(String email) throws MessagingException
    {
        return this.addCc(email, null);
    }

    /**
     * Add a recipient CC to the email.
     *
     * @param email A String.
     * @param name A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addCc(String email, String name) throws MessagingException
    {
        try
        {
            if (!StringUtils.isNotEmpty(name))
            {
                name = email;
            }

            if (StringUtils.isNotEmpty(this.charset))
            {
                this.ccList.add(new InternetAddress(email, name, this.charset));
            }
            else
            {
                this.ccList.add(new InternetAddress(email, name));
            }
        }
        catch (UnsupportedEncodingException e)
        {
            throw new MessagingException("cannot add cc", e);
        }

        return this;
    }

    /**
     * Set a list of "CC" addresses
     *
     * @param   aCollection collection of InternetAddress objects
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email setCc(Collection aCollection) throws MessagingException
    {
        if (aCollection == null || aCollection.isEmpty())
        {
            throw new MessagingException("Address List provided was invalid");
        }

        this.ccList = new ArrayList(aCollection);
        return this;
    }

    /**
     * Add a blind BCC recipient to the email.
     *
     * @param email A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addBcc(String email) throws MessagingException
    {
        return this.addBcc(email, null);
    }

    /**
     * Add a blind BCC recipient to the email.
     *
     * @param email A String.
     * @param name A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addBcc(String email, String name) throws MessagingException
    {
        try
        {
            if (!StringUtils.isNotEmpty(name))
            {
                name = email;
            }

            if (StringUtils.isNotEmpty(this.charset))
            {
                this.bccList.add(
                    new InternetAddress(email, name, this.charset));
            }
            else
            {
                this.bccList.add(new InternetAddress(email, name));
            }

        }
        catch (UnsupportedEncodingException e)
        {
            throw new MessagingException("cannot add bcc", e);
        }

        return this;
    }

    /**
     * Set a list of "BCC" addresses
     *
     * @param   aCollection collection of InternetAddress objects
     * @return  An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email setBcc(Collection aCollection) throws MessagingException
    {
        if (aCollection == null || aCollection.isEmpty())
        {
            throw new MessagingException("Address List provided was invalid");
        }

        this.bccList = new ArrayList(aCollection);
        return this;
    }

    /**
     * Add a reply to address to the email.
     *
     * @param email A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addReplyTo(String email) throws MessagingException
    {
        return this.addReplyTo(email, null);
    }

    /**
     * Add a reply to address to the email.
     *
     * @param email A String.
     * @param name A String.
     * @return An Email.
     * @throws MessagingException Indicates an invalid email address
     */
    public Email addReplyTo(String email, String name)
        throws MessagingException
    {
        try
        {
            if (!StringUtils.isNotEmpty(name))
            {
                name = email;
            }

            if (StringUtils.isNotEmpty(this.charset))
            {
                this.replyList.add(
                    new InternetAddress(email, name, this.charset));
            }
            else
            {
                this.replyList.add(new InternetAddress(email, name));
            }
        }
        catch (UnsupportedEncodingException e)
        {
            throw new MessagingException("cannot add replyTo", e);
        }
        return this;
    }

    /**
     * Used to specify the mail headers.  Example:
     *
     * X-Mailer: Sendmail, X-Priority: 1( highest )
     * or  2( high ) 3( normal ) 4( low ) and 5( lowest )
     * Disposition-Notification-To: user@domain.net
     *
     * @param ht A Hashtable.
     */
    public void setHeaders(Hashtable ht)
    {
        Enumeration enumKeyBad = ht.keys();

        while (enumKeyBad.hasMoreElements())
        {
            String strName = (String) enumKeyBad.nextElement();
            String strValue = (String) ht.get(strName);

            if (!StringUtils.isNotEmpty(strName))
            {
                throw new IllegalArgumentException("name can not be null");
            }
            if (!StringUtils.isNotEmpty(strValue))
            {
                throw new IllegalArgumentException("value can not be null");
            }
        }

        // all is ok, update headers
        this.headers = ht;
    }

    /**
     * Adds a header ( name, value ) to the headers Hashtable.
     *
     * @param name A String with the name.
     * @param value A String with the value.
     */
    public void addHeader(String name, String value)
    {
        if (!StringUtils.isNotEmpty(name))
        {
            throw new IllegalArgumentException("name can not be null");
        }
        if (!StringUtils.isNotEmpty(value))
        {
            throw new IllegalArgumentException("value can not be null");
        }

        this.headers.put(name, value);
    }

    /**
     * Set the email subject.
     *
     * @param aSubject A String.
     * @return An Email.
     */
    public Email setSubject(String aSubject)
    {
        this.subject = aSubject;
        return this;
    }

    /**
     * Set the "bounce address" - the address to which undeliverable messages
     * will be returned.  If this value is never set, then the message will be
     * sent to the address specified with the System property "mail.smtp.from",
     * or if that value is not set, then to the "from" address.
     *
     * @param email A String.
     * @return An Email.
     */
    public Email setBounceAddress(String email)
    {
        this.bounceAddress = email;
        return this;
    }


    /**
     * Define the content of the mail.  It should be overidden by the
     * subclasses.
     *
     * @param msg A String.
     * @return An Email.
     * @throws MessagingException generic exception
     */
    public abstract Email setMsg(String msg) throws MessagingException;

    /**
     * Does the work of actually sending the email.
     *
     * @throws MessagingException if there was an error.
     */
    public void send() throws MessagingException
    {
        this.getMailSession();
        this.message = new MimeMessage(this.session);

        if (StringUtils.isNotEmpty(this.subject))
        {
            if (StringUtils.isNotEmpty(this.charset))
            {
                this.message.setSubject(this.subject, this.charset);
            }
            else
            {
                this.message.setSubject(this.subject);
            }
        }

        //
        //      As far as i can tell, this logic is circular with 
        //      the setContent( Object, String ) method.
        //      There is no way for the content variable to be set without 
        //      the contentType also being set.
        //      The logic below therefore appears to be a duplication of 
        //      the setContent( Object, String ) method
        //      or if not should it not be moved to that method? 
        //      (Proposed replacement code below)
        //      if ( this.content != null )
        //      {
        //          String type = this.contentType;
        //
        //          if ( type != null && !type.trim().equals( "" ) 
        //              && this.charset != null 
        //              && !this.charset.trim().equals( "" ) )
        //          {
        //              type += "; charset=" + this.charset;
        //          }
        //
        //          this.message.setContent( this.content, type );
        //      }

        // ========================================================
        // Start of replacement code
        if (this.content != null)
        {
            this.message.setContent(this.content, this.contentType);
        }
        // end of replacement code
        // ========================================================
        else if (this.emailBody != null)
        {
            this.message.setContent(this.emailBody);
        }
        else
        {
            this.message.setContent("", Email.TEXT_PLAIN);
        }

        if (this.fromAddress != null)
        {
            this.message.setFrom(this.fromAddress);
        }
        else
        {
            throw new MessagingException("Sender address required");
        }

        if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0)
        {
            throw new MessagingException(
                        "At least one receiver address required");
        }

        if (this.toList.size() > 0)
        {
            this.message.setRecipients(
                Message.RecipientType.TO,
                this.toInternetAddressArray(this.toList));
        }

        if (this.ccList.size() > 0)
        {
            this.message.setRecipients(
                Message.RecipientType.CC,
                this.toInternetAddressArray(this.ccList));
        }

        if (this.bccList.size() > 0)
        {
            this.message.setRecipients(
                Message.RecipientType.BCC,
                this.toInternetAddressArray(this.bccList));
        }

        if (this.replyList.size() > 0)
        {
            this.message.setReplyTo(
                this.toInternetAddressArray(this.replyList));
        }

        if (this.headers.size() > 0)
        {
            Enumeration enum = this.headers.keys();

            while (enum.hasMoreElements())
            {
                String name = (String) enum.nextElement();
                String value = (String) headers.get(name);
                this.message.addHeader(name, value);
            }
        }

        if (this.message.getSentDate() == null)
        {
            this.message.setSentDate(getSentDate());
        }

        if (this.popBeforeSmtp)
        {
            Store store = session.getStore("pop3");
            store.connect(this.popHost, this.popUsername, this.popPassword);
        }

        Transport.send(this.message);
    }

    /**
     * Sets the sent date for the email.  The sent date will default to the
     * current date if not explictly set.
     *
     * @param date Date to use as the sent date on the email
     */
    public void setSentDate(Date date)
    {
        this.sentDate = date;
    }

    /**
     * Gets the sent date for the email.
     *
     * @return date to be used as the sent date for the email
     */
    public Date getSentDate()
    {
        if (this.sentDate == null)
        {
            return new Date();
        }
        else
        {
            return this.sentDate;
        }
    }

    /**
     * Utility to copy ArrayList of known InternetAddress objects into an
     * array.
     *
     * @param aList A ArrayList.
     * @return An InternetAddress[].
     */
    protected InternetAddress[] toInternetAddressArray(ArrayList aList)
    {
        InternetAddress[] ia =
            (InternetAddress[]) aList.toArray(new InternetAddress[0]);

        return ia;
    }

    /**
     * Set details regarding "pop3 before smtp" authentication
     * @param newPopBeforeSmtp Wether or not to log into pop3 
     *      server before sending mail
     * @param newPopHost The pop3 host to use.
     * @param newPopUsername The pop3 username.
     * @param newPopPassword The pop3 password.
     */
    public void setPopBeforeSmtp(
        boolean newPopBeforeSmtp,
        String newPopHost,
        String newPopUsername,
        String newPopPassword)
    {
        this.popBeforeSmtp = newPopBeforeSmtp;
        this.popHost = newPopHost;
        this.popUsername = newPopUsername;
        this.popPassword = newPopPassword;
    }
}
