ProblemYou want to build an email message with attachments in a servlet. SolutionUse the JavaMail API for basic email messaging, and the the JavaBeans Activation Framework (JAF) to generate the file attachments. DiscussionThe JAF classes provide fine-grained control over setting up a file attachment for an email message.
The sendMessage( ) method in Example 20-8 creates a new email message ( specifically , a new javax.mail.internet.MimeMessage ), adds its text message, and inserts a file attachment inside the message. The method then sends the message using the code you may have seen in Recipe 20.2 and Recipe 20.3: Transport.send(mailMsg); To accomplish this, the code creates a container (a javax.mail.Multipart object) and two javax.mail.BodyPart s that make up the the container. The first BodyPart is a text message (used usually to describe the file attachment to the user ), while the second BodyPart is the file attachment (in this case, a Microsoft Word file). Then the code sets the content of the MimeMessage to the Multipart . In a nutshell , the MimeMessage (an email message) contains a Multipart , which itself is composed of two BodyPart s: the email's text message and an attached file.
Example 20-8. Making email attachment in a servletspackage com.jspservletcookbook; import java.io.*; import java.util.Properties; import javax.activation.*; import javax.mail.*; import javax.mail.internet.*; import javax.servlet.*; import javax.servlet.http.*; public class EmailAttachServlet extends HttpServlet { //default value for mail server address, in case the user //doesn't provide one private final static String DEFAULT_SERVER = "mail.attbi.com"; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter( ); out.println( "<html><head><title>Email message sender</title></head><body>"); String smtpServ = request.getParameter("smtp"); if (smtpServ == null smtpServ.equals("")) smtpServ = DEFAULT_SERVER; String from = request.getParameter("from"); String to = request.getParameter("to"); String subject = request.getParameter("subject"); try { sendMessage(smtpServ, to, from, subject); } catch (Exception e) { throw new ServletException(e.getMessage( )); } out.println( "<H2>Your attachment has been sent.</H2>"); out.println("</body></html>"); }//doPost public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { doPost(request,response); }//doGet private void sendMessage(String smtpServ, String to, String from, String subject) throws Exception { Multipart multipart = null; BodyPart bpart1 = null; BodyPart bpart2 = null; Properties properties = System.getProperties( ); //populate the 'Properties' object with the mail //server address, so that the default 'Session' //instance can use it. properties.put("mail.smtp.host", smtpServ); Session session = Session.getDefaultInstance(properties); Message mailMsg = new MimeMessage(session);//a new email message InternetAddress[] addresses = null; try { if (to != null) { //throws 'AddressException' if the 'to' email address //violates RFC822 syntax addresses = InternetAddress.parse(to, false); mailMsg.setRecipients(Message.RecipientType.TO, addresses); } else { throw new MessagingException( "The mail message requires a 'To' address."); } if (from != null) { mailMsg.setFrom(new InternetAddress(from)); } else { throw new MessagingException( "The mail message requires a valid 'From' address."); } if (subject != null) mailMsg.setSubject(subject); //This email message's content is a 'Multipart' type //The MIME type for the message's content is 'multipart/mixed' multipart = new MimeMultipart( ); //The text part of this multipart email message bpart1 = new MimeBodyPart( ); String textPart = "Hello, just thought you'd be interested in this Word file."; // create the DataHandler object for the text part DataHandler data = new DataHandler(textPart, "text/plain"); //set the text BodyPart's DataHandler bpart1.setDataHandler(data); //add the text BodyPart to the Multipart container multipart.addBodyPart( bpart1); //create the BodyPart that represents the attached Word file bpart2 = new MimeBodyPart( ); //create the DataHandler that points to a File FileDataSource fds = new FileDataSource( new File( "h:/book/chapters/chap1/chap1.doc") ); //Make sure that the attached file is handled as //the appropriate MIME type: application/msword here MimetypesFileTypeMap ftm = new MimetypesFileTypeMap( ); //the syntax here is the MIME type followed by //space separated extensions ftm.addMimeTypes("application/msword doc DOC" ); fds.setFileTypeMap(ftm); //The DataHandler is instantiated with the //FileDataSource we just created DataHandler fileData = new DataHandler( fds ); //the BodyPart will contain the word processing file bpart2.setDataHandler(fileData); //add the second BodyPart, the one containing the attachment, to //the Multipart object multipart.addBodyPart( bpart2 ); //finally, set the content of the MimeMessage to the //Multipart object mailMsg.setContent( multipart ); // send the mail message; throws a 'SendFailedException' //if any of the message's recipients have an invalid adress Transport.send(mailMsg); } catch (Exception exc) { throw exc; }//try }//sendMessage }//EmailAttachServlet The comments in Example 20-8 explain what happens when you use the javax.activation classes to create a file attachment of the intended MIME type. The most confusing part is creating a javax.activation.FileDataSource that points to the file that you want to attach to the email message. The code uses the FileDataSource to instantiate the javax.activation.DataHandler , which is responsible for the content of the file attachment. //create the DataHandler that points to a File FileDataSource fds = new FileDataSource( new File( "h:/book/chapters/chap1/chap1.doc") ); Make sure that the MimeMessage identifies the attached file as a MIME type of application/msword , so that the user's email application can try to handle the attachment as a Microsoft Word file. Set the FileTypeMap of the FileDataSource with the following code: //Make sure that the attached file is handled as //the appropriate MIME type: application/msword here MimetypesFileTypeMap ftm = new MimetypesFileTypeMap( ); //the syntax here is the MIME type followed by //space separated extensions ftm.addMimeTypes("application/msword doc DOC" ); fds.setFileTypeMap(ftm); A MimetypesFileTypeMap is a class that associates MIME types (like application/msword ) with file extensions such as .doc .
Then the code performs the following steps:
See AlsoSun Microsystem's JavaMail API page: http://java.sun.com/products/javamail/; the JAF web page: http://java.sun.com/products/javabeans/glasgow/jaf.html; Recipe 20.1 on adding JavaMail- related JARs to your web application; Recipe 20.2 on sending email from a servlet; Recipe 20.3 on sending email using a JavaBean; Recipe 20.4 covering how to access email in a servlet; Recipe 20.5 on accessing email with a JavaBean; Recipe 20.6 on handling attachments in a servlet; Recipe 20.8 on reading an email's headers. |