/*
 * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

import java.io.*;
import java.util.*;
import java.text.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.Part;
import javax.mail.internet.*;
import javax.activation.*;


/**
 * This is a servlet that demonstrates the use of JavaMail APIs
 * in a 3-tier application. It allows the user to login to an 
 * IMAP store, list all the messages in the INBOX folder, view
 * selected messages, compose and send a message, and logout.
 * <p>
 * Please note: This is NOT an example of how to write servlets! 
 * This is simply to show that JavaMail can be used in a servlet.
 * <p>
 * For more information on this servlet, see the 
 * JavaMailServlet.README.txt file. 
 * <p>
 * For more information on servlets, see 
 * <a href="http://java.sun.com/products/java-server/servlets/index.html">
 * http://java.sun.com/products/java-server/servlets/index.html</a>
 *
 * @author Max Spivak
 */
public class JavaMailServlet extends HttpServlet implements SingleThreadModel {
    String protocol = "imap";
    String mbox = "INBOX";


    /**
     * This method handles the "POST" submission from two forms: the
     * login form and the message compose form. The login form has the
     * following parameters: <code>hostname</code>, <code>username</code>,
     * and <code>password</code>. The <code>send</code> parameter denotes
     * that the method is processing the compose form submission.
     */
    public  void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException {

	// get the session
	HttpSession ssn = req.getSession(true);

	String send = req.getParameter("send");
	String host = req.getParameter("hostname");
	String user = req.getParameter("username");
	String passwd = req.getParameter("password");
	URLName url = new URLName(protocol, host, -1, mbox, user, passwd);

	ServletOutputStream out = res.getOutputStream();
	res.setContentType("text/html");
	out.println("<html><body bgcolor=\"#CCCCFF\">");

	if (send != null) {
	    // process message sending
	    send(req, res, out, ssn);

	} else {
	    // initial login

	    // create 
	    MailUserData mud = new MailUserData(url);
	    ssn.putValue("javamailservlet", mud);
	    
	    try {
		Properties props = System.getProperties();
		props.put("mail.smtp.host", host);
		Session session = Session.getDefaultInstance(props, null);
		session.setDebug(false);
		Store store = session.getStore(url);
		store.connect();
		Folder folder = store.getDefaultFolder();
		if (folder == null) 
		    throw new MessagingException("No default folder");
		
		folder = folder.getFolder(mbox);
		if (folder == null)
		    throw new MessagingException("Invalid folder");
		
		folder.open(Folder.READ_WRITE);
		int totalMessages = folder.getMessageCount();
		Message[] msgs = folder.getMessages();
		FetchProfile fp = new FetchProfile();
		fp.add(FetchProfile.Item.ENVELOPE);
		folder.fetch(msgs, fp);
		
		// track who logged in
		System.out.println("Login from: " + store.getURLName());
		
		// save stuff into MUD
		mud.setSession(session);
		mud.setStore(store);
		mud.setFolder(folder);
		
		// splash
		out.print("<center>");
		out.print("<font face=\"Arial,Helvetica\" font size=+3>");
		out.println("<b>Welcome to JavaMail!</b></font></center><p>");

		// folder table
		out.println("<table width=\"50%\" border=0 align=center>");
		// folder name column header
		out.print("<tr><td width=\"75%\" bgcolor=\"#ffffcc\">");
		out.print("<font face=\"Arial,Helvetica\" font size=-1>");
		out.println("<b>FolderName</b></font></td><br>");
		// msg count column header
		out.print("<td width=\"25%\" bgcolor=\"#ffffcc\">");
		out.print("<font face=\"Arial,Helvetica\" font size=-1>");
		out.println("<b>Messages</b></font></td><br>");
		out.println("</tr>");
		// folder name
		out.print("<tr><td width=\"75%\" bgcolor=\"#ffffff\">");
		out.print("<a href=\"" + HttpUtils.getRequestURL(req) + "\">" +
			  "Inbox" + "</a></td><br>");
		// msg count
		out.println("<td width=\"25%\" bgcolor=\"#ffffff\">" + 
			    totalMessages + "</td>");
		out.println("</tr>");
		out.println("</table");
	    } catch (Exception ex) {
		out.println(ex.toString());            
	    } finally {
		out.println("</body></html>");
		out.close();
	    }
	}
    }


    /**
     * This method handles the GET requests for the client.
     */
    public void doGet (HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException {

	HttpSession ses = req.getSession(false); // before we write to out
	ServletOutputStream out = res.getOutputStream();
	MailUserData mud = getMUD(ses);

	if (mud == null) {
	    res.setContentType("text/html");
	    out.println("<html><body>Please Login (no session)</body></html>");
	    out.close();
	    return;
	}

	if (!mud.getStore().isConnected()) {
	    res.setContentType("text/html");
	    out.println("<html><body>Not Connected To Store</body></html>");
	    out.close();
	    return;
	}


	// mux that takes a GET request, based on parameters figures
	// out what it should do, and routes it to the
	// appropriate method

	// get url parameters
	String msgStr = req.getParameter("message");
	String logout = req.getParameter("logout");
	String compose = req.getParameter("compose");
	String part = req.getParameter("part");
	int msgNum = -1;
	int partNum = -1;

	// process url params
	if (msgStr != null) {
	    // operate on message "msgStr"
	    msgNum = Integer.parseInt(msgStr);

	    if (part == null) {
		// display message "msgStr"
		res.setContentType("text/html");
		displayMessage(mud, req, out, msgNum);

	    } else {
		// display part "part" in message "msgStr"
		partNum = Integer.parseInt(part);
		displayPart(mud, msgNum, partNum, out, res);
	    }

	} else if (compose != null) {
	    // display compose form
	    compose(mud, res, out);

	} else if (logout != null) {
	    // process logout
	    try {
		mud.getFolder().close(false);
		mud.getStore().close();
		ses.invalidate();
		out.println("<html><body>Logged out OK</body></html>");
	    } catch (MessagingException mex) {
		out.println(mex.toString());
	    }

	} else {
	    // display headers
	    displayHeaders(mud, req, out);
	}
    }

    /* main method to display messages */
    private void displayMessage(MailUserData mud, HttpServletRequest req, 
				ServletOutputStream out, int msgNum) 
	throws IOException {
	    
	out.println("<html>");
	out.println("<HEAD><TITLE>JavaMail Servlet</TITLE></HEAD>");
	out.println("<BODY bgcolor=\"#ccccff\">");
	out.print("<center><font face=\"Arial,Helvetica\" ");
	out.println("font size=\"+3\"><b>");
	out.println("Message " + (msgNum+1) + " in folder " + 
		    mud.getStore().getURLName() + 
		    "/INBOX</b></font></center><p>");

	try {
	    Message msg = mud.getFolder().getMessage(msgNum);

	    // first, display this message's headers
	    displayMessageHeaders(mud, msg, out);

	    // and now, handle the content
	    Object o = msg.getContent();
	    
	    //if (o instanceof String) {
	    if (msg.isMimeType("text/plain")) {
		out.println("<pre>");
		out.println((String)o);
		out.println("</pre>");
	    //} else if (o instanceof Multipart){
	    } else if (msg.isMimeType("multipart/*")) {
		Multipart mp = (Multipart)o;
		int cnt = mp.getCount();
		for (int i = 0; i < cnt; i++) {
		    displayPart(mud, msgNum, mp.getBodyPart(i), i, req, out);
		}
	    } else {
		out.println(msg.getContentType());
	    }

	} catch (MessagingException mex) {
	    out.println(mex.toString());
	}

	out.println("</BODY></html>");
	out.close();
    }

    /** 
     * This method displays a message part. <code>text/plain</code>
     * content parts are displayed inline. For all other parts,
     * a URL is generated and displayed; clicking on the URL
     * brings up the part in a separate page.
     */
    private void displayPart(MailUserData mud, int msgNum, Part part, 
			     int partNum, HttpServletRequest req, 
			     ServletOutputStream out) 
	throws IOException {

	if (partNum != 0)
	    out.println("<p><hr>");

	try {

	    String sct = part.getContentType();
	    if (sct == null) {
		out.println("invalid part");
		return;
	    }
	    ContentType ct = new ContentType(sct);
	    
	    if (partNum != 0)
		out.println("<b>Attachment Type:</b> " +   
			    ct.getBaseType() + "<br>");

	    if (ct.match("text/plain")) {  
		// display text/plain inline
		out.println("<pre>");
		out.println((String)part.getContent());
		out.println("</pre>");

	    } else {
		// generate a url for this part
		String s;
		if ((s = part.getFileName()) != null)
		    out.println("<b>Filename:</b> " + s + "<br>");
		s = null;
		if ((s = part.getDescription()) != null)
		    out.println("<b>Description:</b> " + s + "<br>");
		
		out.println("<a href=\"" +
			    HttpUtils.getRequestURL(req) + 
			    "?message=" +
			    msgNum + "&part=" +
			    partNum + "\">Display Attachment</a>");
	    }
	} catch (MessagingException mex) {
	    out.println(mex.toString());
	}
    }

    /**
     * This method gets the stream from for a given msg part and 
     * pushes it out to the browser with the correct content type.
     * Used to display attachments and relies on the browser's
     * content handling capabilities.
     */
    private void displayPart(MailUserData mud, int msgNum,
			     int partNum, ServletOutputStream out, 
			     HttpServletResponse res) 
	throws IOException {

	Part part = null;
	
	try {
	    Message msg = mud.getFolder().getMessage(msgNum);

	    Multipart mp = (Multipart)msg.getContent();
	    part = mp.getBodyPart(partNum);
	    
	    String sct = part.getContentType();
	    if (sct == null) {
		out.println("invalid part");
		return;
	    }
	    ContentType ct = new ContentType(sct);

	    res.setContentType(ct.getBaseType());
	    InputStream is = part.getInputStream();
	    int i;
	    while ((i = is.read()) != -1)
		out.write(i);
	    out.flush();
	    out.close();
	} catch (MessagingException mex) {
	    out.println(mex.toString());
	}
    }

    /**
     * This is a utility message that pretty-prints the message 
     * headers for message that is being displayed.
     */
    private void displayMessageHeaders(MailUserData mud, Message msg, 
				       ServletOutputStream out) 
	throws IOException {

	try {
	    out.println("<b>Date:</b> " + msg.getSentDate() + "<br>");

	    Address[] fr = msg.getFrom();
	    if (fr != null) {
		boolean tf = true;
		out.print("<b>From:</b> ");
		for (int i = 0; i < fr.length; i++) {
		    out.print(((tf) ? " " : ", ") + getDisplayAddress(fr[i]));
		    tf = false;
		}
		out.println("<br>");
	    }

	    Address[] to = msg.getRecipients(Message.RecipientType.TO);
	    if (to != null) {
		boolean tf = true;
		out.print("<b>To:</b> ");
		for (int i = 0; i < to.length; i++) {
		    out.print(((tf) ? " " : ", ") + getDisplayAddress(to[i]));
		    tf = false;
		}
		out.println("<br>");
	    }

	    Address[] cc = msg.getRecipients(Message.RecipientType.CC);
	    if (cc != null) {
		boolean cf = true;
		out.print("<b>CC:</b> ");
		for (int i = 0; i < cc.length; i++) {
		    out.print(((cf) ? " " : ", ") + getDisplayAddress(cc[i]));
		    cf = false;
		}
		out.println("<br>");
	    }
	    
	    out.print("<b>Subject:</b> " + 
		      ((msg.getSubject() !=null) ? msg.getSubject() : "") + 
		      "<br>");

	} catch (MessagingException mex) {
	    out.println(msg.toString());
	}
    }

    /**
     * This method displays the URL's for the available commands and the
     * INBOX headerlist 
     */
    private void displayHeaders(MailUserData mud,
				HttpServletRequest req, 
				ServletOutputStream out)
	throws IOException {

	SimpleDateFormat df = new SimpleDateFormat("EE M/d/yy");

	out.println("<html>");
	out.println("<HEAD><TITLE>JavaMail Servlet</TITLE></HEAD>");
	out.println("<BODY bgcolor=\"#ccccff\"><hr>");
	out.print("<center><font face=\"Arial,Helvetica\" font size=\"+3\">");
	out.println("<b>Folder " + mud.getStore().getURLName() + 
		    "/INBOX</b></font></center><p>");

	// URL's for the commands that are available
	out.println("<font face=\"Arial,Helvetica\" font size=\"+3\"><b>");
	out.println("<a href=\"" +
		    HttpUtils.getRequestURL(req) +
		    "?logout=true\">Logout</a>");
	out.println("<a href=\"" +
		    HttpUtils.getRequestURL(req) +
		    "?compose=true\" target=\"compose\">Compose</a>");
	out.println("</b></font>");
	out.println("<hr>");

	// List headers in a table
	out.print("<table cellpadding=1 cellspacing=1 "); // table
	out.println("width=\"100%\" border=1>");          // settings

	// sender column header
	out.println("<tr><td width=\"25%\" bgcolor=\"ffffcc\">");
	out.println("<font face=\"Arial,Helvetica\" font size=\"+1\">");
	out.println("<b>Sender</b></font></td>");
	// date column header
	out.println("<td width=\"15%\" bgcolor=\"ffffcc\">");
	out.println("<font face=\"Arial,Helvetica\" font size=\"+1\">");
	out.println("<b>Date</b></font></td>");
	// subject column header
	out.println("<td bgcolor=\"ffffcc\">");
	out.println("<font face=\"Arial,Helvetica\" font size=\"+1\">");
	out.println("<b>Subject</b></font></td></tr>");

	try {
	    Folder f = mud.getFolder();
	    int msgCount = f.getMessageCount();
	    Message m = null;
	    // for each message, show its headers
	    for (int i = 1; i <= msgCount; i++) {
		m = f.getMessage(i);
		
		// if message has the DELETED flag set, don't display it
		if (m.isSet(Flags.Flag.DELETED))
		    continue;

		// from 
		out.println("<tr valigh=middle>");
		out.print("<td width=\"25%\" bgcolor=\"ffffff\">");
		out.println("<font face=\"Arial,Helvetica\">" + 
			    ((m.getFrom() != null) ? 
				       m.getFrom()[0].toString() : 
				       "" ) +
			    "</font></td>");

		// date
		out.print("<td nowrap width=\"15%\" bgcolor=\"ffffff\">");
		out.println("<font face=\"Arial,Helvetica\">" + 
			    df.format((m.getSentDate()!=null) ? 
				      m.getSentDate() : m.getReceivedDate()) +
			    "</font></td>");

		// subject & link
		out.print("<td bgcolor=\"ffffff\">");
		out.println("<font face=\"Arial,Helvetica\">" + 
			    "<a href=\"" +
			    HttpUtils.getRequestURL(req) + 
			    "?message=" +
			    i + "\">" +
			    ((m.getSubject() != null) ? 
				   m.getSubject() :
				   "<i>No Subject</i>") +
			    "</a>" +
			    "</font></td>");
		out.println("</tr>");
	    }
	} catch (MessagingException mex) {
	    out.println("<tr><td>" + mex.toString() + "</td></tr>");
	    mex.printStackTrace();
	}

	out.println("</table>");
	out.println("</BODY></html>");
	out.flush();
	out.close();
    }

    /** 
     * This method handles the request when the user hits the
     * <i>Compose</i> link. It send the compose form to the browser.
     */
    private void compose(MailUserData mud, HttpServletResponse res,
			 ServletOutputStream out) 
	throws IOException {
	
	res.setContentType("text/html");
	out.println(composeForm);
	out.close();
    }

    /**
     * This method processes the send request from the compose form
     */
    private void send(HttpServletRequest req, HttpServletResponse res,
		      ServletOutputStream out, HttpSession ssn)
	throws IOException {
	    
	String to = req.getParameter("to");
	String cc = req.getParameter("cc");
	String subj = req.getParameter("subject");
	String text = req.getParameter("text");

	try {
	    MailUserData mud = getMUD(ssn);
	    if (mud == null)
		throw new Exception("trying to send, but not logged in");

	    Message msg = new MimeMessage(mud.getSession());
	    InternetAddress[] toAddrs = null, ccAddrs = null;

	    if (to != null) {
		toAddrs = InternetAddress.parse(to, false);
		msg.setRecipients(Message.RecipientType.TO, toAddrs);
	    } else
		throw new MessagingException("No \"To\" address specified");

	    if (cc != null) {
		ccAddrs = InternetAddress.parse(cc, false);
		msg.setRecipients(Message.RecipientType.CC, ccAddrs);
	    }

	    if (subj != null)
		msg.setSubject(subj);

	    URLName u = mud.getURLName();
	    msg.setFrom(new InternetAddress(u.getUsername() + "@" +
					    u.getHost()));

	    if (text != null)
		msg.setText(text);

	    Transport.send(msg);
	    
	    out.println("<h1>Message sent successfully</h1></body></html>");
	    out.close();
	    
	} catch (Exception mex) {
	    out.println("<h1>Error sending message.</h1>");
	    out.println(mex.toString());
	    out.println("<br></body></html>");
	}
    }


    // utility method; returns a string suitable for msg header display
    private String getDisplayAddress(Address a) {
	String pers = null;
	String addr = null;
	if (a instanceof InternetAddress &&
	    ((pers = ((InternetAddress)a).getPersonal()) != null)) {
	    
	    addr = pers + "  "+"&lt;"+((InternetAddress)a).getAddress()+"&gt;";
	} else 
	    addr = a.toString();
	
	return addr;
    }

    // utility method; retrieve the MailUserData 
    // from the HttpSession and return it
    private MailUserData getMUD(HttpSession ses) throws IOException {
	MailUserData mud = null;

	if (ses == null) {
	    return null;
	} else {
	    if ((mud = (MailUserData)ses.getValue("javamailservlet")) == null){
		return null;
	    }
	}
	return mud;
    }


    public String getServletInfo() {
	return "A mail reader servlet";
    }

    /**
     * This is the HTML code for the compose form. Another option would
     * have been to use a separate html page.
     */
    private static String composeForm = "<HTML><HEAD><TITLE>JavaMail Compose</TITLE></HEAD><BODY BGCOLOR=\"#CCCCFF\"><FORM ACTION=\"/servlet/JavaMailServlet\" METHOD=\"POST\"><input type=\"hidden\" name=\"send\" value=\"send\"><P ALIGN=\"CENTER\"><B><FONT SIZE=\"4\" FACE=\"Verdana, Arial, Helvetica\">JavaMail Compose Message</FONT></B><P><TABLE BORDER=\"0\" WIDTH=\"100%\"><TR><TD WIDTH=\"16%\" HEIGHT=\"22\">	<P ALIGN=\"RIGHT\"><B><FONT FACE=\"Verdana, Arial, Helvetica\">To:</FONT></B></TD><TD WIDTH=\"84%\" HEIGHT=\"22\"><INPUT TYPE=\"TEXT\" NAME=\"to\" SIZE=\"30\"> <FONT SIZE=\"1\" FACE=\"Verdana, Arial, Helvetica\"> (separate addresses with commas)</FONT></TD></TR><TR><TD WIDTH=\"16%\"><P ALIGN=\"RIGHT\"><B><FONT FACE=\"Verdana, Arial, Helvetica\">CC:</FONT></B></TD><TD WIDTH=\"84%\"><INPUT TYPE=\"TEXT\" NAME=\"cc\" SIZE=\"30\"> <FONT SIZE=\"1\" FACE=\"Verdana, Arial, Helvetica\"> (separate addresses with commas)</FONT></TD></TR><TR><TD WIDTH=\"16%\"><P ALIGN=\"RIGHT\"><B><FONT FACE=\"Verdana, Arial, Helvetica\">Subject:</FONT></B></TD><TD WIDTH=\"84%\"><INPUT TYPE=\"TEXT\" NAME=\"subject\" SIZE=\"55\"></TD></TR><TR><TD WIDTH=\"16%\">&nbsp;</TD><TD WIDTH=\"84%\"><TEXTAREA NAME=\"text\" ROWS=\"15\" COLS=\"53\"></TEXTAREA></TD></TR><TR><TD WIDTH=\"16%\" HEIGHT=\"32\">&nbsp;</TD><TD WIDTH=\"84%\" HEIGHT=\"32\"><INPUT TYPE=\"SUBMIT\" NAME=\"Send\" VALUE=\"Send\"><INPUT TYPE=\"RESET\" NAME=\"Reset\" VALUE=\"Reset\"></TD></TR></TABLE></FORM></BODY></HTML>";

}


/**
 * This class is used to store session data for each user's session. It
 * is stored in the HttpSession.
 */
class MailUserData {
    URLName url;
    Session session;
    Store store;
    Folder folder;

    public MailUserData(URLName urlname) {
	url = urlname;
    }

    public URLName getURLName() {
	return url;
    }

    public Session getSession() {
	return session;
    }

    public void setSession(Session s) {
	session = s;
    }

    public Store getStore() {
	return store;
    }

    public void setStore(Store s) {
	store = s;
    }

    public Folder getFolder() {
	return folder;
    }

    public void setFolder(Folder f) {
	folder = f;
    }
}
