Sending Emails with Attachments

Sending emails with attachments is simply a matter of creating a multi-part email. The first part will be the email itself and subsequent parts will be the attachments. Each attachment will be MIME encoded so that binary, as well as textual, data can be sent with the message. Listing 11.5 shows an example of a multi-part email with a MIME header and footer that identifies the attached part of the message.

Listing 11.5. Email with MIME Attachment
Return-Path: <agency@localhost>
Received: from localhost ([127.0.0.1])
          by XXXX (JAMES SMTP Server 2.1) with SMTP ID 788
          for <juliet@localhost>;
          Thu, 8 Jan 2004 10:04:33 +0000 (GMT)
Message-ID: <12014584.1073556273610.JavaMail.xx@XXXX>
From: agency
To: juliet@localhost
Subject: HTML Message and Image
Mime-Version: 1.0
Content-Type: multipart/related;
   boundary="----=_Part_0_16416372.1073556273409"
Date: Thu, 8 Jan 2004 10:04:33 +0000 (GMT)

------=_Part_0_16416372.1073556273409
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<html><head><title>HTML Page</title></head><body>  <table><tr>
<td><img src="cid:image"></td>
<td><h2>Teach Yourself J2EE in 21 Days</h2></td>  </tr></table>
<p align="left">Visit the
<a href="http://www.samspublishing.com/">Sams Publishing</a>
 Web site for more books on Java and related technologies.</p></body></html>
------=_Part_0_16416372.1073556273409
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-ID: image
R0lGODlhWQAYAMQAAP3+//v9/gCZzAGZzAKazAyezg2ezxmj0SGm0y6r1Tiv10Kz2VK63F6/32/F
...
gWCJ2UprA7PWGiiStCYQ33K6WqPbEmk5EUEDD4oQAgA7
------=_Part_0_16416372.1073556273409--

In Listing 11.5 the first Content-Type: heading identifies this email as a multi-part email and defines the boundary string that separates each part (in this case ----=_Part_0_16416372.1073556273409). Each part of the message is separated by the boundary string and has its own set of headers. The first part is a text/html message while the second part is an image/gif message. The GIF image uses the base64 encoding to represent binary data in 7 bit characters; the GIF image is also given a Content-ID heading that is used to identify the image when it is used on the web page, as discussed later in this section.

Sending HTML Email with Embedded Graphics

You will now look at the code to generate an HTML email message with an image included as an attachment.

Like the previous application, the code for this application creates Properties, Session, and Message objects and sets the message subject, recipient's address, and sender's address. The code only differs in how it creates the message body.

In the previous application you set the message body text by using the setContent() method, where you supplied a string containing HTML and a MIME type. To create a multi-part message, you must define each part of the message separately and then associate the parts with the message. Figure 11.2 shows the process of creating multi-part content.

Figure 11.2. Creating a multi-part message.


Each part of a multi-part email is a javax.mail.MimeBodyPart object. The separate MimeBodyPart objects are collected together and stored in a javax.mail.MimeMultipart object which is added to the MimeMessage object using the setContent() method.

The following code creates the message part for the HTML document:

StringBuffer msgBuffer = new StringBuffer();
String line=null;
FileReader fr = new FileReader("src/HTMLEmbed.html");
BufferedReader br = new BufferedReader(fr);
while ((line=br.readLine())!=null) {
  msgBuffer.append(line);
}
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(msgBuffer.toString(), "text/html");

The MimeBodyPart.setContent() method accepts an object, and a string defining the MIME type of the object in the same manner as the Message.setContent() method shown previously.

To create a MimeBodyPart object to hold the GIF image you must use a javax.activation.DataHandler object to read and MIME encode the GIF image. This is shown in the following code:

BodyPart imageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource("src/sams.gif");
imageBodyPart.setDataHandler(new DataHandler(fds));
imageBodyPart.setHeader("Content-ID","image");

A DataHandler object provides a consistent interface to several different data sources and formats, for example, an image or an input stream. In this example, the DataHandler object will reference a DataSource object that encapsulates the image file. The MIME type of the part is automatically derived from the file contents. In this case the file DataHandler object identifies the data as a GIF image and sets the part MIME type to image/gif.

The last part of this code sets the Content-ID header to identify the part so that the HTML page can reference it. The example uses the name image to identify this part.

You have now created the two parts that comprise the message. The last step is to create a MimeMultipart object to hold the body parts. MimeMultipart has three constructors:

  • The default constructor sets the message content type of multipart/mixed and defines a unique boundary string for each part.

  • A second constructor accepts a javax.activation.DataSource object and uses that object to define the message body and its MIME type.

  • The final constructor accepts a single string that represents a given media subtype. There are a wide range of possible subtypes, such as digest, encrypted, and related described in RFC 1521(http://www.ietf.org/rfc/rfc1521.txt).

The code to create the multi-part message and add the two body parts is as follows:

MimeMultipart multipart = new MimeMultipart("related");
multipart.addBodyPart(messageBodyPart);
multipart.addBodyPart(imageBodyPart);
message.setContent(multipart);

The example code uses the MimeMultiPart constructor accepting the related media subtype to specify that the message consists of multiple interrelated parts.

Listing 11.6 shows the complete code for this application.

Listing 11.6. SendMultiPartMail.java Full Listing
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
import javax.activation.*;

public class SendMultiPartMail {
    private static final String htmlFile = "src/HTMLLink.html";
    private static final String imageFile = "src/sams.gif";

    public static void main(String[] args) {
        if (args.length!=3) {
            System.out.println("Usage: SendMultiPartMail SMTPHost ToAddress FromAddress");
            System.exit(1);
        }

        String smtpHost = args[0];
        String to = args[1];
        String from = args[2];

        Properties props = new Properties();
        props.put("mail.smtp.host",smtpHost);

        try {
            Session session = Session.getDefaultInstance(props,null);
            MimeMessage message = new MimeMessage(session);
            message.setSubject("HTML Message and Image");
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            StringBuffer msgBuffer = new StringBuffer();
            String line=null;
            FileReader fr = new FileReader(htmlFile);
            BufferedReader br = new BufferedReader(fr);
            while ((line=br.readLine())!=null) {
                msgBuffer.append(line);
            }

            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setContent(msgBuffer.toString(), "text/html");

            BodyPart imageBodyPart = new MimeBodyPart();
            DataSource fds = new FileDataSource(imageFile);
            imageBodyPart.setDataHandler(new DataHandler(fds));
            imageBodyPart.setHeader("Content-ID","image");

            MimeMultipart multipart = new MimeMultipart("related");
            multipart.addBodyPart(messageBodyPart);
            multipart.addBodyPart(imageBodyPart);
            message.setContent(multipart);
            Transport.send(message);
        }
        catch (MessagingException me) {
            System.err.println(me);
        }
        catch (IOException ioe) {
            System.err.println(ioe);
        }
    }
}

The Java code for this application is now complete, but you will need to update the HTML code to refer to the attached image. In the previous example, you referenced the image with an absolute URL. In this application, you use a CID (Content ID) URL and the name of the image body part. For example:

<img src="cid:image">

That's it, you can now run your example using

asant SendMutliPartMail

As usual, you will need to provide the SMTP host, recipient address and sender's address. If you use the values from Table 11.2 the message you send will be the one shown previously in Listing 11.5.

One final consideration for this example is that the HTML message part is read from a file. Rather than store the HTML in a String Buffer, the Java Activation DataHandler technique could have been used. This would have simplified the code as the first message part could be defined as:

BodyPart messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource("src/HTMLEmbed.html");
messageBodyPart.setDataHandler(new DataHandler(fds));

This HTML example is a special case of sending an email with an attachment. Before you look at using JavaMail to read email it is worth looking at a program for sending any file as an attachment.

Sending Email with File Attachments

In the previous example, you used MIME multi-part messages to send an HTML message that displays an image. Another use of MIME is to send message attachments, such as MPEG videos, JPEG images, and plain text files. In this example, you will create a small command line application that sends a message with an attached file to a named recipient.

The process is very similar to that of creating the multi-part HTML message in the previous section. The only extra requirement is to include the filename in the multi-part for the MIME encoded data. For example,

BodyPart fileBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(fileName);
fileBodyPart.setDataHandler(new DataHandler(source));
File file = new File(fileName);
fileBodyPart.setFileName(file.getName());

The MimeBodyPart.setFileName() method takes a filename and includes it as part of the Content-Disposition header of the part. The following example shows part of the mail resulting message if the src/sams.gif file is sent as an attachment:

------=_Part_0_31378924.1073573040284
Content-Type: image/gif; name="sams.gif"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="sams.gif"
R0lGODlhWQAYAMQAAP3+//v9/gCZzAGZzAKazAyezg2ezxmj0SGm0y6r1Tiv10Kz2VK63F6/32/F
...
gWCJ2UprA7PWGiiStCYQ33K6WqPbEmk5EUEDD4oQAgA7
------=_Part_0_31378924.1073573040284--

The Content-Type header defines the type of the attachment (image/gif) and the filename. The filename is also included in the Content-Disposition header. An attachment filename should not include a directory component and the sample code uses the File.getName() method to remove any directory names preceding the required filename. In practical use most mail clients will simply ignore any directory component of the filename when saving the attachment to disk.

The remaining code is similar to the previous examples and is shown in Listing 11.7.

Listing 11.7. SendAttachmentMail.java Full Listing
import java.util.Properties;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class SendAttachmentMail {
    public static void main(String[] args) {
        if (args.length!=4) {
            System.out.println("Usage: SendAttachmentMail SMTPHost ToAddress FromAddress
 AttachmentName");
            System.exit(1);
        }

        String smtpHost = args[0];
        String to = args[1];
        String from = args[2];
        String fileName = args[3];

        Properties props = new Properties();
        props.put("mail.smtp.host",smtpHost);

        try {
            Session session = Session.getDefaultInstance(props,null);
            MimeMessage message = new MimeMessage(session);
            message.setSubject("Message with attachment");
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setText("Here's an attachment!");

            BodyPart fileBodyPart = new MimeBodyPart();
            DataSource source = new FileDataSource(fileName);
            fileBodyPart.setDataHandler(new DataHandler(source));
            File file = new File(fileName);
            fileBodyPart.setFileName(file.getName());

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);
            multipart.addBodyPart(fileBodyPart);
            message.setContent(multipart);
           Transport.send(message);
        }
        catch (MessagingException me) {
            System.err.println(me);
        }
        catch (IllegalStateException ise) {
            System.err.println(ise);
        }
    }
}

Run this example with the command

asant SendAttachmentMail

and supply the requested parameters. You can use the values in Table 11.2 and a filename of src/sams.gif.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.165.234