Creating Multi-Media E-mails

Most modern e-mail clients have the capability of displaying formatted HTML messages. Many organizations now prefer to send HTML messages because they provide a richer viewing experience for the recipient. For example, a HTML message might incorporate an organization's logo and format the message's text so that it adheres to the organization's style preferences (font face, heading colors).

In the following example, HTML is used as the multi-media content. However, there is no intention to teach you HMTL (if you do not already know it), so the HTML is supplied for you.

The application you will now write is a typical example of an application an organization might use to send a marketing or informational e-mail to customers or potential customers. The application sends a HTML message to the recipient that contains an image file representing the organization's logo. To view the formatted output of the message, you must have an e-mail client that is capable of displaying HTML, such as Netscape Communicator, Microsoft Outlook, or a Java application that uses Swing JEditorPane.

There are two main ways of creating an HTML message that will display an image when viewed in an e-mail client. The simplest is when the HTML code references a URL that points to a publicly visible image location. This approach is simple to code, but does require that the image remains publicly visible for the potential lifetime of the message. In addition, it requires the e-mail client either to always have an external connection or cache a local copy of the images. The second approach is when you integrate the images into the message. This approach ensures that the recipient always sees the images. However, it does entail sending larger messages, which places higher loads on your server and the client's mail server. Today's lesson shows you both of these approaches starting with the external reference approach.

Creating the Message: Approach #1

The code for this approach to sending a HTML message is very similar to the code that sends a plain text message. The start of the code has a few additions. First, the code imports the java.io package to provide the classes that read the HTML file. Second, the code declares two extra variables—one defines the content type of the message and the other names the HTML source file.

import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
public class SendHTMLMail {
    public static void main(String[] args) {
        if (args.length!=3) {
System.out.println ("Usage: SendHTMLMail SMTPHost ToAddress FromAddress");
            System.exit(1);
        }
        String smtpHost = args[0];
        String to = args[1];
        String from = args[2];
        String contentType = "text/html";
        String htmlFile = "HTMLSource1.html";

In common with the plain text message, you create Properties, Session and Message objects. You also set the subject and sender's and recipient's addresses.

Properties props = System.getProperties();
props.put("mail.smtp.host",smtpHost);
Session session = Session.getDefaultInstance(props,null);
MimeMessage message = new MimeMessage(session);
message.setSubject("Hi!");
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,new InternetAddress(to));

Adding the HTML to the MimeMessage object is the first significant change to the code. Because the HTML is stored in a file, you must first read the file's contents. The following code does this; as you can see, it simply uses the java.io classes:

String msg="";
String line=null;
FileReader fr = new FileReader(htmlFile);
BufferedReader br = new BufferedReader(fr);
while ((line=br.readLine())!=null) {
    msg+=line;
}

The code that sent a plain text message used the setText() method to set the message text. In this example, you use another method—setContent(). This method takes two parameters—an object that represents the message body and a string that defines the MIME type of the message body. This method allows you to stipulate the MIME type of the message, whereas the setText() method always applies a MIME type of text/plain. In the application you are currently building, the setContent() method takes a first argument of a string (the HTML) and a second argument of a variable with the value text/html:

message.setContent(msg,contentType);

After you define the message body, you send the message using the send() method of the Transport class. This is exactly the same approach you took when sending a plain text message, so that code fragment isn't shown here. Instead, Listing 11.2 shows the complete code for sending a HTML e-mail message.

Listing 11.2. SendHTMLMail.java Full Listing
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;

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

        String smtpHost = args[0];
        String to = args[1];
        String from = args[2];
        String contentType = "text/html";
        String htmlFile = "HTMLSource1.html";

        // Get properties object
        Properties props = System.getProperties();

        // Define SMTP host property
        props.put("mail.smtp.host",smtpHost);

        try {
            // Get a session
            Session session = Session.getDefaultInstance(props,null);

            // Create a new message object
            MimeMessage message = new MimeMessage(session);

            // Populate message object
            message.setSubject("Hi!");
            message.setFrom(new InternetAddress(from));
message.addRecipient (Message.RecipientType.TO,new InternetAddress(to));

            // read the HTML source
            String msg="";
            String line=null;
            FileReader fr = new FileReader(htmlFile);
            BufferedReader br = new BufferedReader(fr);
            while ((line=br.readLine())!=null) {
                msg+=line;
            }

            // Add the content to the message
            message.setContent(msg,contentType);

            // Send the message
            Transport.send(message);
        }
        catch (MessagingException me) {
            System.err.println(me.getMessage());
        }
        catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
    }
}
						

The Java code for this application is now complete, but you still need the HTML source file. It is not one of the aims of this book to teach you HTML. However, there are two important points to note about the HTML source for this example. The first is that the HTML is regular HTML; you change nothing to include it within an e-mail message. The second point concerns the image that the message HTML message displays. The HTML defines an absolute URL to the image file:

http://www.samspublishing.com/images/topnav/logo-bottom.gif

You must use an absolute URL because the message does not include the image itself. Retaining the image source at a remote location offers some advantages over including the image within the message:

  • Loads— If messages do not include image data, they remain small. This places a lower load on the mail server, especially in the case of bulk mailings.

  • Maintenance— The image source file might be modified or updated and, as long as the image's URI remains the same, that modification or update will affect the already-delivered message.

In contrast, this approach also has disadvantages, because the external image must always be accessible to the client or the client must cache a copy of the image source. If the client is unable to do either of these things, the image will not render within the message.

To run this application, you must first compile it. When compiled, run the application by issuing the following command:

java SendHTMLMail mail.yourSMTPHost.com toAddress fromAddress

Remember that you must have an e-mail client that is capable of viewing HTML messages to view the output from this application. Figure 11.2 shows the message sent by this application:

Figure 11.2. Sample output for Listing 11.2.


Creating the Message: Approach #2

The second approach to sending a HTML e-mail message with an embedded image includes the image within the message itself. To create this type of message, you create a message that consists of multiple parts, where the HTML forms one part and the image a second part. This type of message is known as a multi-part message, and the next section of today's lesson explores these in some detail.

Writing the Code

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. For the sake of brevity, this part of today's lesson only walks through the code that differs from the previous application, but you can still see the full code in Listing 11.3.

As a result of creating a multi-part message, there are two small additions to the start of the code. You must import the javax.activation package (you'll learn why a little later) and create one additional variable with a value of the image file location:

String imageFile = "sams.gif";

In the previous application you set the message's body text by using the setContent() method, where you supplied a string containing HTML and a MIME type. The following is the line of code that did this:

message.setContent(msg,contentType);

To create a multi-part message, you must replace this line of code. The new code must define each of the parts of the message and then associate them with the message. Figure 11.3 shows the process of creating multi-part content.

Figure 11.3. Creating a multi-part message.


Figure 11.3 shows that you create BodyPart objects, each of which contains one part of the message's body. For example, in this application one part contains HTML and another part contains the image data. As you create each BodyPart, you add it to a MimeMultipart object by using its addBodyPart() method. After you have added all the BodyPart objects to the MimeMultipart object, you add this object to the MimeMessage object using its setContent() method. To write this as code, you start by creating a new BodyPart object:

BodyPart messageBodyPart = new MimeBodyPart();

In this example, the code creates an empty BodyPart object. However, the class offers two other constructors. The first creates accepts an input stream as an argument. The input stream is read and parsed, and then becomes the content of the BodyPart object. The final constructor accepts two arguments—an InternetHeaders object and a byte array of content. The InternetHeaders object contains the Internet headers that relate to the given content. In most instances, you will not directly code the Internet headers; service providers primarily use the object.

You must now set the content of this first BodyPart. In this example, the content is the HTML that you read from a file and assigned to the variable msg. The setContent() method sets the content of a body part:

messageBodyPart.setContent(msg, contentType);

You may notice that this setContent() method takes the same arguments as the setContent() method you used with the MimeMessage object. Both the MimeMessage class and BodyPart class subclass classes, which themselves implement the Part interface. This interface is common to all messages and BodyParts. The purpose of the interface is to define attributes, common to all mail systems, and then provide accessor methods for these attributes. For example, these attributes include headers and content. For a complete reference to this interface, refer to the API documentation, which is available locally in the docs directory under the J2EE installation directory or online at http://java.sun.com/products/javamail/1.2/docs/javadocs/overview-summary.html.

Now that you have created the first body part, you must create a MimeMultipart object and add the body part to it. MimeMultipart has three constructors—the default constructor creates an empty MimeMultipart object. This object has a content type of multipart/mixed and is given a unique boundary string that you can access through the contentType field. The second constructor accepts a DataSource object as an argument, you'll learn more about DataSource objects a little later in this section. 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. For further details about subtypes, refer to RFC 822, which is available at http://rfc.net/rfc822.html. The related subtype applies to objects that consist of multiple interrelated parts. It allows you to link these parts to present a single compound object. It is this subtype that you create with the following:

MimeMultipart multipart = new MimeMultipart("related");

Now you must add the body part, which contains the HTML, to the MimeMultipart object you just created. The MimeMultipart's addBodyPart() method provides two ways for adding the body part. The first way takes two arguments—a BodyPart and an index (int) to position the object. The seconds version of the addBodyPart() methods simply takes a BodyPart as an argument and then appends this to list of body parts it currently contains:

multipart.addBodyPart(messageBodyPart);

Now you must create a new BodyPart object that contains the image and then append this to the MimeMultipart object. In common with adding the HTML, you first create a new BodyPart:

messageBodyPart = new MimeBodyPart();

To add the image to the BodyPart object, you use the setDataHandler() method. This method accepts one argument—a DataHandler object. This 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:

DataSource fds = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(fds));

The final step before adding this body part to the MimeMultipart object is to set a header for the part. You need to set the header because your HTML source will reference the header to include the image within the message rather than reference the image via an absolute URL. You use the body part's setHeader() method to set the header:

messageBodyPart.setHeader("Content-ID","image1");

You can see that the method accepts two parameters. The first parameter is a string that represents an RFC 822 header value. The second parameter is the header's value that you will later reference from the HTML source.

That's it. You have created the body part that contains the image the message will display. Now you must add the body part to the MimeMultipart object that you created earlier. You add the body part in exactly the same way you added the first body part (the one containing the HTML source):

multipart.addBodyPart(messageBodyPart);

If you refer back to Figure 11.3, you can see that you must set the content of the message with the MimeMultipart object. As with the previous examples, you use the setContent() method to do this:

message.setContent(multipart);

The code that sends the message is identical to all the previous examples. Listing 11.3 shows the complete code for this application.

Listing 11.3. SendMultiPartMail.java Full Listing
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
import javax.activation.*;

public class SendMultiPartMail {
    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];
        String contentType = "text/html";
        String htmlFile = "HTMLSource2.html";
        String imageFile = "sams.gif";

        // Get properties object
        Properties props = System.getProperties();

        // Define SMTP host property
        props.put("mail.smtp.host",smtpHost);

        try {
            // Get a session
            Session session = Session.getDefaultInstance(props,null);

            // Create a new message object
            MimeMessage message = new MimeMessage(session);

            // Populate message object
            message.setSubject("Hi!");
            message.setFrom(new InternetAddress(from));
message.addRecipient (Message.RecipientType.TO,new InternetAddress(to));

            // read the HTML source
            String msg="";
            String line=null;
            FileReader fr = new FileReader(htmlFile);
            BufferedReader br = new BufferedReader(fr);
            while ((line=br.readLine())!=null) {
                msg+=line;
            }

            // Create your new message part
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setContent(msg, contentType);

            // Create a related multi-part to combine the parts
            MimeMultipart multipart = new MimeMultipart("related");
            multipart.addBodyPart(messageBodyPart);

            // Create part for the image
            messageBodyPart = new MimeBodyPart();

            // Fetch the image and associate to part
            DataSource fds = new FileDataSource(imageFile);
            messageBodyPart.setDataHandler(new DataHandler(fds));
            messageBodyPart.setHeader("Content-ID","image1");

            // Add part to multi-part
            multipart.addBodyPart(messageBodyPart);

            // Associate multi-part with message
            message.setContent(multipart);

            // Send the message
            Transport.send(message);
        }
        catch (MessagingException me) {
            System.err.println(me.getMessage());
        }
        catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
    }
}
							

The Java code for this application is now complete, but you still need the HTML code. The HTML is identical to that used in the previous example with one exception. In the previous example, you referenced the image with an absolute URL. In this application, you use a CID (Content ID) URL and the value of the header you set for the body part that contains the image, for example,

<img src="cid:image1">

To run this application, you must first compile it. When compiled, run the application by issuing the following command:

java SendMultiPartMail mail.yourSMTPHost.com toAddress fromAddress

The message sent by this application should appear identical to that sent in the previous application, as shown in Figure 11.2.

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

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