Send out Mail in a Servlet : Email « Servlet « Java Tutorial

Java Tutorial
1. Language
2. Data Type
3. Operators
4. Statement Control
5. Class Definition
6. Development
7. Reflection
8. Regular Expressions
9. Collections
10. Thread
11. File
12. Generics
13. I18N
14. Swing
15. Swing Event
16. 2D Graphics
17. SWT
18. SWT 2D Graphics
19. Network
20. Database
21. JSP
22. JSTL
23. Servlet
24. Web Services SOA
25. Email
26. J2ME
27. J2EE Application
28. XML
29. Design Pattern
30. Log
31. Security
32. Apache Common
Java
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Tutorial » Servlet » Email 
23. 32. 1. Send out Mail in a Servlet
JavaMail Servlet
           ~~~~~~~~~~~~~~~~

Overview:
=========

JavaMailServlet should not be taken as a demo of how to use the Java 
Servlet API. It is rather an example of how the JavaMail APIs could 
be used in a server in a three-tier environment described by the 
following diagram:

  +-----------+        +-----------+        +-----------+
  |   IMAP    |        |           |        |           |
  |  Server   |<-IMAP->| JavaMail  |<-HTTP->|    WWW    |
  +-----------+        | Servlet   |--HTML->|  Browser  |
  |   SMTP    |<-SMTP->|           |        |           |
  |  Server   |        |           |        |           |
  +-----------+        +-----------+        +-----------+


The JavaMailServlet supports the following functionality:
  * login to an IMAP server
  * list all the messages in the INBOX folder
  * view the selected message
  * compose and send a message


Setting up and running the demo:
================================
Note: These instructions explain how to compile and run the servlet 
demo with Java Web Server (JWS). The procedure should be similar with 
other web servers that support the Java Servlet API.

  1. Download the latest version of the Java Web Server from
     http://www.sun.com/software/jwebserver/index.html and
     install according to the included documentation. Make
     sure JWS is listening to requests on port 80 (you may 
     need to modify it from default port 8080; use the JWS 
     Admin Applet). Make sure you can load the Java Web 
     Server welcome page when you connect with your browser 
     to the machine that the server is installed on. Also,
     make sure your web browser has cookie support turned on.

  2. Set your classpath to include the following:
      * mail.jar:    in the JavaMail API distribution
      * activation.jar:  in the JAF distribution
      * jws.jar:    in the /lib/ directory in JWS installation

  3. In javamail-1.1/demo/servlet directory, compile the 
     JavaMailServlet.java file. That produces two class files,
     JavaMailServlet.class and MailUserData.class. Copy these
     class files to the /servlets/ directory in the JWS 
     installation.

  4. Copy the mail.jar and activation.jar to the /lib/
     directory in the JWS installation.

  5. Copy the JavaMail.html file to the /public_html/
     directory in the JWS installation.

  6. Restart Java Web Server to pick up the new jar files
     added to its lib directory. Check again that you can
     load the default JWS page to verify that the server
     is working fine.

  7. Using a web browser, go to 
     http://<hostname>/JavaMail.html and login to a
     valid IMAP account. From here on, you can view 
     messages in your INBOX and create and send new 
     messages.



JavaMailServlet Design:
=======================

The following is a brief description of JavaMailServlet class. It
is not intended to serve as an example of how to develop servlets;
see http://java.sun.com/products/servlet for information on the Java
Servlet API. You may find it useful to refer to JavaMailServlet.java
source while reading this.

The JavaMailServlet uses two primary methods to process all
requests: doPost() and doGet(). doPost() processes submissions
from the login and compose forms. When the user logs in, the
doPost() method gets a JavaMail Session and uses the values
of the "hostname""username" and "password" parameters to login
to the IMAP Store and get the INBOX Folder. To preserve state
between multiple HTTP requests, the necessary information
(Session, Store, Folder, URLNameare collected in the
MailUserData object which is stored using JWS's Session
technology (don't confuse HttpSession and JavaMail's Session--
they are different). Finally, the doPost() method outputs 
a table listing the INBOX and the number of messages in it.

Clicking on the "INBOX" link calls the doGet() method
which displays a table of message headers. (See the doGet() 
and displayHeaders() methods.)

Clicking on a message generates a request to the servlet with
the message sequence number as a parameter. The doGet() method
receives the request and calls the displayMessage() method 
passing it the message sequence number to display. The 
displayMessage() method first lists the message headers 
by calling the displayMessageHeaders() utility method. 
For text/plain messages, the message content is then displayed
as a string wrapped in HTML <pre>...</pre> tags. For multipart 
messages, each part is passed to the displayPart() method.

There are two displayPart() methods. The one with signature
  displayPart(MailUserData mud, int msgNum, Part part, 
        int partNum, HttpServletRequest req, 
        ServletOutputStream out
is called from the displayMessage() method for each part. For
any part with text/plain content type, the content is output
as a string wrapped in HTML <pre>...</pre> tags. For other
content types, a link representing the part is displayed,
along with the part filename and description, if available.

Clicking in the part link generates a request to the servlet
with two parameters: the message sequence number and the
part number. The doGet() method interprets the parameters and 
invokes the second displayPart() method with the signature 
  displayPart(MailUserData mud, int msgNum,
              int partNum, ServletOutputStream out, 
        HttpServletResponse res
This method retrieves the specified part from the message and
streams it to the web browser, preceded by the MIME content type 
of this part. For example, if the part has a MIME type image/gif,
the method will set the servlet response MIME content type to 
"image/gif" and then follow it with the bytes of the actual 
image. This leverages the web browser's content handling
ability to display different media types.

Message composition and sending is very similar to message
viewing. When the "Compose" link is clicked in the headerlist
page, the servlet outputs the HTML source for the compose
form stored in the composeForm variable. The user then fills
in the destination address, subject, text, and presses
send. This sends a POST request to the servlet, which 
invokes the doPost() method. doPost() calls the servlet's 
send() method, which creates a new MimeMessage and fills 
it with data retrieved from the POST request. The message
is then sent to its destination using the Transport.send()
static method.
/*
 * @(#)JavaMailServlet.java  1.5 01/05/23
 *
 * Copyright 1998, 1999 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 
 * - Redistribution 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.
 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
 * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR LIABILITIES
 * SUFFERED BY LICENSEE AS A RESULT OF  OR RELATING TO USE, MODIFICATION
 * OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
 * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
 * ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS
 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
 * You acknowledge that Software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */

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

import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.*;
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 if (part != null) {
    // 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\">");