/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.
 *
 */

/*
 * The original version of this class was donated by Jason Hunter,
 * who wrote the class as part of the com.oreilly.servlet
 * package for his book "Java Servlet Programming" (O'Reilly).
 * See http://www.servlets.com.
 *
 */

package org.apache.tools.mail;

import java.io.IOException;
import java.io.PrintStream;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.InetAddress;
import java.util.Vector;
import java.util.Enumeration;

/**
 * A class to help send SMTP email.
 * This class is an improvement on the sun.net.smtp.SmtpClient class
 * found in the JDK.  This version has extra functionality, and can be used
 * with JVMs that did not extend from the JDK.  It's not as robust as
 * the JavaMail Standard Extension classes, but it's easier to use and
 * easier to install, and has an Open Source license.
 * <p>
 * It can be used like this:
 * <blockquote><pre>
 * String mailhost = "localhost";  // or another mail host
 * String from = "Mail Message Servlet &lt;MailMessage@server.com&gt;";
 * String to = "to@you.com";
 * String cc1 = "cc1@you.com";
 * String cc2 = "cc2@you.com";
 * String bcc = "bcc@you.com";
 * &nbsp;
 * MailMessage msg = new MailMessage(mailhost);
 * msg.setPort(25);
 * msg.from(from);
 * msg.to(to);
 * msg.cc(cc1);
 * msg.cc(cc2);
 * msg.bcc(bcc);
 * msg.setSubject("Test subject");
 * PrintStream out = msg.getPrintStream();
 * &nbsp;
 * Enumeration enum = req.getParameterNames();
 * while (enum.hasMoreElements()) {
 *   String name = (String)enum.nextElement();
 *   String value = req.getParameter(name);
 *   out.println(name + " = " + value);
 * }
 * &nbsp;
 * msg.sendAndClose();
 * </pre></blockquote>
 * <p>
 * Be sure to set the from address, then set the recipient
 * addresses, then set the subject and other headers, then get the
 * PrintStream, then write the message, and finally send and close.
 * The class does minimal error checking internally; it counts on the mail
 * host to complain if there's any malformatted input or out of order
 * execution.
 * <p>
 * An attachment mechanism based on RFC 1521 could be implemented on top of
 * this class.  In the meanwhile, JavaMail is the best solution for sending
 * email with attachments.
 * <p>
 * Still to do:
 * <ul>
 * <li>Figure out how to close the connection in case of error
 * </ul>
 *
 * @version 1.1, 2000/03/19, added angle brackets to address, helps some servers
 * version 1.0, 1999/12/29
 */
public class MailMessage {

    /** default mailhost */
    public static final String DEFAULT_HOST = "localhost";

    /** default port for SMTP: 25 */
    public static final int DEFAULT_PORT = 25;

    /** host name for the mail server */
    private String host;

    /** host port for the mail server */
    private int port = DEFAULT_PORT;

    /** sender email address */
    private String from;

    /** list of email addresses to reply to */
    private Vector replyto;

    /** list of email addresses to send to */
    private Vector to;

    /** list of email addresses to cc to */
    private Vector cc;

    /** headers to send in the mail */
    private Vector headersKeys;
    private Vector headersValues;

    private MailPrintStream out;

    private SmtpResponseReader in;

    private Socket socket;
    private static final int OK_READY = 220;
    private static final int OK_HELO = 250;
    private static final int OK_FROM = 250;
    private static final int OK_RCPT_1 = 250;
    private static final int OK_RCPT_2 = 251;
    private static final int OK_DATA = 354;
    private static final int OK_DOT = 250;
    private static final int OK_QUIT = 221;

  /**
   * Constructs a new MailMessage to send an email.
   * Use localhost as the mail server with port 25.
   *
   * @exception IOException if there's any problem contacting the mail server
   */
  public MailMessage() throws IOException {
    this(DEFAULT_HOST, DEFAULT_PORT);
  }

  /**
   * Constructs a new MailMessage to send an email.
   * Use the given host as the mail server with port 25.
   *
   * @param host the mail server to use
   * @exception IOException if there's any problem contacting the mail server
   */
  public MailMessage(String host) throws IOException {
    this(host, DEFAULT_PORT);
  }

  /**
   * Constructs a new MailMessage to send an email.
   * Use the given host and port as the mail server.
   *
   * @param host the mail server to use
   * @param port the port to connect to
   * @exception IOException if there's any problem contacting the mail server
   */
  public MailMessage(String host, int port) throws IOException {
    this.port = port;
    this.host = host;
    replyto = new Vector();
    to = new Vector();
    cc = new Vector();
    headersKeys = new Vector();
    headersValues = new Vector();
    connect();
    sendHelo();
  }

    /**
     * Set the port to connect to the SMTP host.
     * @param port the port to use for connection.
     * @see #DEFAULT_PORT
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * Sets the from address.  Also sets the "From" header.  This method should
     * be called only once.
     * @param from the from address
     * @exception IOException if there's any problem reported by the mail server
     */
    public void from(String from) throws IOException {
        sendFrom(from);
        this.from = from;
    }

    /**
     * Sets the replyto address
     * This method may be
     * called multiple times.
     * @param rto the replyto address
     *
     */
    public void replyto(String rto) {
      this.replyto.addElement(rto);
    }

  /**
   * Sets the to address.  Also sets the "To" header.  This method may be
   * called multiple times.
   *
   * @param to the to address
   * @exception IOException if there's any problem reported by the mail server
   */
  public void to(String to) throws IOException {
    sendRcpt(to);
    this.to.addElement(to);
  }

  /**
   * Sets the cc address.  Also sets the "Cc" header.  This method may be
   * called multiple times.
   *
   * @param cc the cc address
   * @exception IOException if there's any problem reported by the mail server
   */
  public void cc(String cc) throws IOException {
    sendRcpt(cc);
    this.cc.addElement(cc);
  }

  /**
   * Sets the bcc address.  Does NOT set any header since it's a *blind* copy.
   * This method may be called multiple times.
   *
   * @param bcc the bcc address
   * @exception IOException if there's any problem reported by the mail server
   */
  public void bcc(String bcc) throws IOException {
    sendRcpt(bcc);
    // No need to keep track of Bcc'd addresses
  }

  /**
   * Sets the subject of the mail message.  Actually sets the "Subject"
   * header.
   * @param subj the subject of the mail message
   */
  public void setSubject(String subj) {
    setHeader("Subject", subj);
  }

  /**
   * Sets the named header to the given value.  RFC 822 provides the rules for
   * what text may constitute a header name and value.
   * @param name name of the header
   * @param value contents of the header
   */
  public void setHeader(String name, String value) {
    // Blindly trust the user doesn't set any invalid headers
    headersKeys.add(name);
    headersValues.add(value);
  }

  /**
   * Returns a PrintStream that can be used to write the body of the message.
   * A stream is used since email bodies are byte-oriented.  A writer can
   * be wrapped on top if necessary for internationalization.
   * This is actually done in Message.java
   *
   * @return a printstream containing the data and the headers of the email
   * @exception IOException if there's any problem reported by the mail server
   * @see org.apache.tools.ant.taskdefs.email.Message
   */
  public PrintStream getPrintStream() throws IOException {
    setFromHeader();
    setReplyToHeader();
    setToHeader();
    setCcHeader();
    setHeader("X-Mailer", "org.apache.tools.mail.MailMessage (ant.apache.org)");
    sendData();
    flushHeaders();
    return out;
  }


  // RFC 822 s4.1: "From:" header must be sent
  // We rely on error checking by the MTA
  void setFromHeader() {
    setHeader("From", from);
  }

  // RFC 822 s4.1: "Reply-To:" header is optional
  void setReplyToHeader() {
    if (!replyto.isEmpty()) {
      setHeader("Reply-To", vectorToList(replyto));
    }
  }

  void setToHeader() {
    if (!to.isEmpty()) {
      setHeader("To", vectorToList(to));
    }
  }

  void setCcHeader() {
    if (!cc.isEmpty()) {
      setHeader("Cc", vectorToList(cc));
    }
  }

  String vectorToList(Vector v) {
    StringBuffer buf = new StringBuffer();
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      buf.append(e.nextElement());
      if (e.hasMoreElements()) {
        buf.append(", ");
      }
    }
    return buf.toString();
  }

  void flushHeaders() throws IOException {
    // RFC 822 s4.1:
    //   "Header fields are NOT required to occur in any particular order,
    //    except that the message body MUST occur AFTER the headers"
    // (the same section specifies a reccommended order, which we ignore)
   final int size = headersKeys.size();
   for (int i = 0; i < size; i++) {
      String name = (String) headersKeys.elementAt(i);
      String value = (String) headersValues.elementAt(i);
      out.println(name + ": " + value);
    }
    out.println();
    out.flush();
  }

  /**
   * Sends the message and closes the connection to the server.
   * The MailMessage object cannot be reused.
   *
   * @exception IOException if there's any problem reported by the mail server
   */
  public void sendAndClose() throws IOException {
      try {
          sendDot();
          sendQuit();
      } finally {
          disconnect();
      }
  }

  // Make a limited attempt to extract a sanitized email address
  // Prefer text in <brackets>, ignore anything in (parentheses)
  static String sanitizeAddress(String s) {
    int paramDepth = 0;
    int start = 0;
    int end = 0;
    int len = s.length();

    for (int i = 0; i < len; i++) {
      char c = s.charAt(i);
      if (c == '(') {
        paramDepth++;
        if (start == 0) {
          end = i;  // support "address (name)"
        }
      } else if (c == ')') {
        paramDepth--;
        if (end == 0) {
          start = i + 1;  // support "(name) address"
        }
      } else if (paramDepth == 0 && c == '<') {
        start = i + 1;
      } else if (paramDepth == 0 && c == '>') {
        end = i;
      }
    }

    if (end == 0) {
      end = len;
    }

    return s.substring(start, end);
  }

  // * * * * * Raw protocol methods below here * * * * *

  void connect() throws IOException {
    socket = new Socket(host, port);
    out = new MailPrintStream(
          new BufferedOutputStream(
          socket.getOutputStream()));
    in = new SmtpResponseReader(socket.getInputStream());
    getReady();
  }

  void getReady() throws IOException {
    String response = in.getResponse();
    int[] ok = {OK_READY};
    if (!isResponseOK(response, ok)) {
      throw new IOException(
        "Didn't get introduction from server: " + response);
    }
  }
  void sendHelo() throws IOException {
    String local = InetAddress.getLocalHost().getHostName();
    int[] ok = {OK_HELO};
    send("HELO " + local, ok);
  }
  void sendFrom(String from) throws IOException {
    int[] ok = {OK_FROM};
    send("MAIL FROM: " + "<" + sanitizeAddress(from) + ">", ok);
  }
  void sendRcpt(String rcpt) throws IOException {
    int[] ok = {OK_RCPT_1, OK_RCPT_2};
    send("RCPT TO: " + "<" + sanitizeAddress(rcpt) + ">", ok);
  }

  void sendData() throws IOException {
    int[] ok = {OK_DATA};
    send("DATA", ok);
  }

  void sendDot() throws IOException {
    int[] ok = {OK_DOT};
    send("\r\n.", ok);  // make sure dot is on new line
  }

    void sendQuit() throws IOException {
        int[] ok = {OK_QUIT};
        try {
            send("QUIT", ok);
        } catch (IOException e) {
            throw new ErrorInQuitException(e);
        }
    }

    void send(String msg, int[] ok) throws IOException {
        out.rawPrint(msg + "\r\n");  // raw supports <CRLF>.<CRLF>
        String response = in.getResponse();
        if (!isResponseOK(response, ok)) {
            throw new IOException("Unexpected reply to command: "
                                  + msg + ": " + response);
        }
    }

  boolean isResponseOK(String response, int[] ok) {
    // Check that the response is one of the valid codes
    for (int i = 0; i < ok.length; i++) {
      if (response.startsWith("" + ok[i])) {
        return true;
      }
    }
    return false;
  }

    void disconnect() throws IOException {
        if (out != null) {
            out.close();
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                // ignore
            }
        }
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }
}

/**
 * This PrintStream subclass makes sure that <CRLF>. becomes <CRLF>..
 *  per RFC 821.  It also ensures that new lines are always \r\n.
*/
class MailPrintStream extends PrintStream {

  private int lastChar;

  public MailPrintStream(OutputStream out) {
    super(out, true);  // deprecated, but email is byte-oriented
  }

  // Mac does \n\r, but that's tough to distinguish from Windows \r\n\r\n.
  // Don't tackle that problem right now.
  public void write(int b) {
    if (b == '\n' && lastChar != '\r') {
      rawWrite('\r');  // ensure always \r\n
      rawWrite(b);
    } else if (b == '.' && lastChar == '\n') {
      rawWrite('.');  // add extra dot
      rawWrite(b);
    } else {
      rawWrite(b);
    }
    lastChar = b;
  }

  public void write(byte[] buf, int off, int len) {
    for (int i = 0; i < len; i++) {
      write(buf[off + i]);
    }
  }

  void rawWrite(int b) {
    super.write(b);
  }

  void rawPrint(String s) {
    int len = s.length();
    for (int i = 0; i < len; i++) {
      rawWrite(s.charAt(i));
    }
  }
}

