Fundamentals of The Javamail API
Fundamentals of The Javamail API
Table of Contents
If you're viewing this document online, you can click any of the topics below to link directly to that section.
1. Tutorial tips 2. Introducing the JavaMail API 3. Reviewing related protocols 4. Installing JavaMail 5. Reviewing the core classes 6. Using the JavaMail API 7. Searching with SearchTerm 8. Exercises 9. Wrapup
2 3 4 6 8 13 21 22 32
Page 1
ibm.com/developerWorks
Objectives By the end of this module you will be able to: * Send and read mail using the JavaMail API * Deal with sending and receiving attachments * Work with HTML messages * Use search terms to search for messages
Prerequisites Instructions on how to download and install the JavaMail API are contained in the course. In addition, you will need a development environment such as the JDK 1.1.6+ or the Java 2 Platform, Standard Edition (J2SE) 1.2.x or 1.3.x. A general familiarity with object-oriented programming concepts and the Java programming language is necessary. The Java language essentials tutorial can help. copyright 1996-2000 Magelang Institute dba jGuru
Contact
jGuru has been dedicated to promoting the growth of the Java technology community through evangelism, education, and software since 1995. You can find out more about their activities, including their huge collection of FAQs at jGuru.com . To send feedback to jGuru about this course, send mail to [email protected] . Course author: Formerly with jGuru.com , John Zukowski does strategic Java consulting for JZ Ventures, Inc. His latest book is titled Java Collections from Apress .
Page 2
ibm.com/developerWorks
Page 3
ibm.com/developerWorks
You will also run across NNTP and some others. Understanding the basics of all the protocols will help you understand how to use the JavaMail API. While the API is designed to be protocol agnostic, you can't overcome the limitations of the underlying protocols. If a capability isn't supported by a chosen protocol, the JavaMail API doesn't magically add the capability on top of it. (As you'll soon see, this can be a problem when working with POP.)
SMTP
The Simple Mail Transfer Protocol (SMTP) is defined by RFC 821 . It defines the mechanism for delivery of e-mail. In the context of the JavaMail API, your JavaMail-based program will communicate with your company or Internet Service Provider's (ISP's) SMTP server. That SMTP server will relay the message on to the SMTP server of the recipient(s) to eventually be acquired by the user(s) through POP or IMAP. This does not require your SMTP server to be an open relay, as authentication is supported, but it is your responsibility to ensure the SMTP server is configured properly. There is nothing in the JavaMail API for tasks like configuring a server to relay messages or to add and remove e-mail accounts.
POP
POP stands for Post Office Protocol. Currently in version 3, also known as POP3, RFC 1939 defines this protocol. POP is the mechanism most people on the Internet use to get their mail. It defines support for a single mailbox for each user. That is all it does, and that is also the source of a lot of confusion. Much of what people are familiar with when using POP, like the ability to see how many new mail messages they have, are not supported by POP at all. These capabilities are built into programs like Eudora or Microsoft Outlook, which remember things like the last mail received and calculate how many are new for you. So, when using the JavaMail API, if you want this type of information, you have to calculate it yourself.
IMAP
IMAP is a more advanced protocol for receiving messages. Defined in RFC 2060 , IMAP stands for Internet Message Access Protocol, and is currently in version 4, also known as IMAP4. When using IMAP, your mail server must support the protocol. You can't just change your program to use IMAP instead of POP and expect everything in IMAP to be supported. Assuming your mail server supports IMAP, your JavaMail-based program can take
Fundamentals of the JavaMail API Page 4
ibm.com/developerWorks
advantage of users having multiple folders on the server and these folders can be shared by multiple users. Due to the more advanced capabilities, you might think IMAP would be used by everyone. It isn't. It places a much heavier burden on the mail server, requiring the server to receive the new messages, deliver them to users when requested, and maintain them in multiple folders for each user. While this does centralize backups, as users' long-term mail folders get larger and larger, everyone suffers when disk space is exhausted. With POP, saved messages get offloaded from the mail server.
MIME
MIME stands for Multipurpose Internet Mail Extensions. It is not a mail transfer protocol. Instead, it defines the content of what is transferred: the format of the messages, attachments, and so on. There are many different documents that take effect here: RFC 822 , RFC 2045 , RFC 2046 , and RFC 2047 . As a user of the JavaMail API, you usually don't need to worry about these formats. However, these formats do exist and are used by your programs.
Page 5
ibm.com/developerWorks
ibm.com/developerWorks
need to add pop3.jar to your CLASSPATH. If you don't want to change the CLASSPATH environment variable, copy the jar files to your lib/ext directory under the Java Runtime Environment (JRE) directory. For instance, for the J2SE 1.3 release, the default directory would be C:\jdk1.3\jre\lib\ext on a Windows platform.
Exercise
Exercise 1. How to set up a JavaMail environment on page 22
Page 7
ibm.com/developerWorks
Session
The Session class defines a basic mail session. It is through this session that everything else works. The Session object takes advantage of a java.util.Properties object to get information like mail server, username, password, and other information that can be shared across your entire application. The constructors for the class are private. You can get a single default session that can be shared with the getDefaultInstance() method:
Properties props = new Properties(); // fill props with any information Session session = Session.getDefaultInstance(props, null);
In both cases, the null argument is an Authenticator object that is not being used at this time. In most cases, it is sufficient to use the shared session, even if working with mail sessions for multiple user mailboxes. You can add the username and password combination in at a later step in the communication process, keeping everything separate.
Message
Once you have your Session object, it is time to move on to creating the message to send. This is done with a type of Message . Because Message is an abstract class, you must work with a subclass, in most cases javax.mail.internet.MimeMessage . A MimeMessage is an e-mail message that understands MIME types and headers, as defined in the different RFCs. Message headers are restricted to US-ASCII characters only, though non-ASCII characters can be encoded in certain header fields. To create a Message, pass along the Session object to the MimeMessage constructor:
MimeMessage message = new MimeMessage(session);
Page 8
ibm.com/developerWorks
Note: There are other constructors, like for creating messages from RFC822-formatted input streams. Once you have your message, you can set its parts, as Message implements the Part interface (with MimeMessage implementing MimePart ). The basic mechanism to set the content is the setContent() method, with arguments for the content and the mime type:
message.setContent("Hello", "text/plain");
If, however, you know you are working with a MimeMessage and your message is plain text, you can use its setText() method, which only requires the actual content, defaulting to the MIME type of text/plain:
message.setText("Hello");
For plain text messages, the latter form is the preferred mechanism to set the content. For sending other kinds of messages, like HTML messages, use the former. For setting the subject, use the setSubject() method:
message.setSubject("First");
Address
Once you've created the Session and the Message, as well as filled the message with content, it is time to address your letter with an Address . Like Message, Address is an abstract class. You use the javax.mail.internet.InternetAddress class. To create an address with just the e-mail address, pass the e-mail address to the constructor:
Address address = new InternetAddress("[email protected]");
If you want a name to appear next to the e-mail address, you can pass that along to the constructor, too:
Address address = new InternetAddress("[email protected]", "George Bush");
You will need to create address objects for the message's from field as well as the to field. Unless your mail server prevents you, there is nothing stopping you from sending a message that appears to be from anyone. Once you've created the addresses, you connect them to a message in one of two ways. For identifying the sender, you use the setFrom() and setReplyTo() methods.
message.setFrom(address)
If your message needs to show multiple from addresses, use the addFrom() method:
Page 9
ibm.com/developerWorks
For identifying the message recipients, you use the addRecipient() method. This method requires a Message.RecipientType besides the address.
message.addRecipient(type, address)
So, if the message was to go to the vice president, sending a carbon copy to the first lady, the following would be appropriate:
Address toAddress = new InternetAddress("[email protected]"); Address ccAddress = new InternetAddress("[email protected]"); message.addRecipient(Message.RecipientType.TO, toAddress); message.addRecipient(Message.RecipientType.CC, ccAddress);
The JavaMail API provides no mechanism to check for the validity of an e-mail address. While you can program in support to scan for valid characters (as defined by RFC 822) or verify the MX (mail exchange) record yourself, these are all beyond the scope of the JavaMail API.
Authenticator
Like the java.net classes, the JavaMail API can take advantage of an Authenticator to access protected resources via a username and password. For the JavaMail API, that resource is the mail server. The JavaMail Authenticator is found in the javax.mail package and is different from the java.net class of the same name. The two don't share the same Authenticator as the JavaMail API works with Java 1.1, which didn't have the java.net variety. To use the Authenticator, you subclass the abstract class and return a PasswordAuthentication instance from the getPasswordAuthentication() method. You must register the Authenticator with the session when created. Then, your Authenticator will be notified when authentication is necessary. You could pop up a window or read the username and password from a configuration file (though if not encrypted is not secure), returning them to the caller as a PasswordAuthentication object.
Properties props = new Properties(); // fill props with any information Authenticator auth = new MyAuthenticator(); Session session = Session.getDefaultInstance(props, auth);
Transport
The final part of sending a message is to use the Transport class. This class speaks the
Fundamentals of the JavaMail API Page 10
ibm.com/developerWorks
protocol-specific language for sending the message (usually SMTP). It's an abstract class and works something like Session. You can use the default version of the class by just calling the static send() method:
Transport.send(message);
Or, you can get a specific instance from the session for your protocol, pass along the username and password (blank if unnecessary), send the message, and close the connection:
message.saveChanges(); // implicit with send() Transport transport = session.getTransport("smtp"); transport.connect(host, username, password); transport.sendMessage(message, message.getAllRecipients()); transport.close();
This latter way is best when you need to send multiple messages, as it will keep the connection with the mail server active between messages. The basic send() mechanism makes a separate connection to the server for each method call. Note: To watch the mail commands go by to the mail server, set the debug flag with session.setDebug(true).
After connecting to the Store, you can then get a Folder , which must be opened before you can read messages from it:
Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); Message message[] = folder.getMessages();
For POP3, the only folder available is the INBOX. If you are using IMAP, you can have other folders available. Note: Sun's providers are meant to be smart. While Message message[] = folder.getMessages(); might look like a slow operation reading every message from the server, only when you actually need to get a part of the message is the message content retrieved. Once you have a Message to read, you can get its content with getContent() or write its content to a stream with writeTo(). The getContent() method only gets the message content, while writeTo() output includes headers.
Page 11
ibm.com/developerWorks
System.out.println(((MimeMessage)message).getContent());
Once you're done reading mail, close the connection to the folder and store.
folder.close(aBoolean); store.close();
The boolean passed to the close() method of folder states whether or not to update the folder by removing deleted messages.
Moving on
Essentially, understanding how to use these seven classes is all you need for nearly everything with the JavaMail API. Most of the other capabilities of the JavaMail API build off these seven classes to do something a little different or in a particular way, like if the content is an attachment. Certain tasks, like searching, are isolated and are discussed later.
Page 12
ibm.com/developerWorks
Sending messages
Sending an e-mail message involves getting a session, creating and filling a message, and sending it. You can specify your SMTP server by setting the mail.smtp.host property for the Properties object passed when getting the Session:
String host = ...; String from = ...; String to = ...; // Get system properties Properties props = System.getProperties(); // Setup mail server props.put("mail.smtp.host", host); // Get session Session session = Session.getDefaultInstance(props, null); // Define message MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject("Hello JavaMail"); message.setText("Welcome to JavaMail"); // Send message Transport.send(message);
You should place the code in a try-catch block, as setting up the message and sending it can throw exceptions. Exercise: Exercise 2. How to send your first message on page 23
Fetching messages
For reading mail, you get a session, get and connect to an appropriate store for your mailbox, open the appropriate folder, and get your messages. Also, don't forget to close the connection when done.
String host = ...; String username = ...; String password = ...; // Create empty properties Properties props = new Properties(); // Get session Session session = Session.getDefaultInstance(props, null);
Page 13
ibm.com/developerWorks
// Get the store Store store = session.getStore("pop3"); store.connect(host, username, password); // Get folder Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); // Get directory Message message[] = folder.getMessages(); for (int i=0, n=message.length; i<n; i++) { System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject()); } // Close connection folder.close(false); store.close();
What you do with each message is up to you. The above code block just displays whom the message is from and the subject. Technically speaking, the list of from addresses could be empty and the getFrom()[0] call could throw an exception. To display the whole message, you can prompt the user after seeing the from and subject fields, and then call the message's writeTo() method if the user wants to see it.
BufferedReader reader = new BufferedReader ( new InputStreamReader(System.in)); // Get directory Message message[] = folder.getMessages(); for (int i=0, n=message.length; i<n; i++) { System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject()); System.out.println("Do you want to read message? " + "[YES to read/QUIT to end]"); String line = reader.readLine(); if ("YES".equals(line)) { message[i].writeTo(System.out); } else if ("QUIT".equals(line)) { break; } }
ibm.com/developerWorks
Just because a flag exists doesn't mean the flag is supported by all mail servers or providers. For instance, except for deleting messages, the POP protocol supports none of them. Checking for new mail is not a POP task but a task built into mail clients. To find out what flags are supported, ask the folder with getPermanentFlags(). To delete messages, you set the message's DELETED flag:
message.setFlag(Flags.Flag.DELETED, true);
Then, when you are done processing all messages, close the folder, passing in a true value to expunge the deleted messages.
folder.close(true);
There is an expunge() method of Folder that can be used to delete the messages. However, it doesn't work for Sun's POP3 provider. Other providers may or may not implement the capabilities. It will more than likely be implemented for IMAP providers. Because POP only supports single access to the mailbox, you have to close the folder to delete the messages with Sun's provider. To unset a flag, just pass false to the setFlag() method. To see if a flag is set, check it with isSet().
Authenticating yourself
You learned that you can use an Authenticator to prompt for username and password when needed, instead of passing them in as strings. Here you'll actually see how to more fully use authentication. Instead of connecting to the Store with the host, username, and password, you configure the Properties to have the host, and tell the Session about your custom Authenticator instance, as shown here:
// Setup properties Properties props = System.getProperties(); props.put("mail.pop3.host", host); // Setup authentication, get session Authenticator auth = new PopupAuthenticator(); Session session = Session.getDefaultInstance(props, auth); // Get the store Store store = session.getStore("pop3"); store.connect();
You then subclass Authenticator and return a PasswordAuthentication object from the getPasswordAuthentication() method. The following is one such implementation, with a single field for both. (This isn't a Project Swing tutorial; just enter the two parts in the one field, separated by a comma.)
Fundamentals of the JavaMail API Page 15
ibm.com/developerWorks
import javax.mail.*; import javax.swing.*; import java.util.*; public class PopupAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication() { String username, password; String result = JOptionPane.showInputDialog( "Enter 'username,password'"); StringTokenizer st = new StringTokenizer(result, ","); username = st.nextToken(); password = st.nextToken(); return new PasswordAuthentication(username, password); } }
Because the PopupAuthenticator relies on Swing, it will start up the event-handling thread for AWT. This basically requires you to add a call to System.exit() in your code to stop the program.
Replying to messages
The Message class includes a reply() method to configure a new Message with the proper recipient and subject, adding "Re: " if not already there. This does not add any content to the message, only copying the from or reply-to header to the new recipient. The method takes a boolean parameter indicating whether to reply to only the sender (false) or reply to all (true).
MimeMessage reply = (MimeMessage)message.reply(false); reply.setFrom(new InternetAddress("[email protected]")); reply.setText("Thanks"); Transport.send(reply);
To configure the reply-to address when sending a message, use the setReplyTo() method. Exercise: Exercise 4. How to reply to mail on page 27
Forwarding messages
Forwarding messages is a little more involved. There is no single method to call, and you build up the message to forward by working with the parts that make up a message. A mail message can be made up of multiple parts. Each part is a BodyPart , or more specifically, a MimeBodyPart when working with MIME messages. The different body parts get combined into a container called Multipart or, again, more specifically a MimeMultipart . To forward a message, you create one part for the text of your message and a second part with the message to forward, and combine the two into a multipart. Then you add the multipart to a properly addressed message and send it. That's essentially it. To copy the content from one message to another, just copy over its
Fundamentals of the JavaMail API Page 16
ibm.com/developerWorks
Page 17
ibm.com/developerWorks
Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart); // Part two is attachment messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); multipart.addBodyPart(messageBodyPart); // Put parts in message message.setContent(multipart); // Send the message Transport.send(message);
When including attachments with your messages, if your program is a servlet, your users must upload the attachment besides telling you where to send the message. Uploading each file can be handled with a form encoding type of multipart/form-data.
<FORM ENCTYPE="multipart/form-data" method=post action="/myservlet"> <INPUT TYPE="file" NAME="thefile"> <INPUT TYPE="submit" VALUE="Upload"> </FORM>
Note: Message size is limited by your SMTP server, not the JavaMail API. If you run into problems, consider increasing the Java heap size by setting the ms and mx parameters. Exercise: Exercise 5. How to send attachments on page 28 Getting attachments: Getting attachments out of your messages is a little more involved then sending them because MIME has no simple notion of attachments. The content of your message is a Multipart object when it has attachments. You then need to process each Part, to get the main content and the attachment(s). Parts marked with a disposition of Part.ATTACHMENT from part.getDisposition() are clearly attachments. However, attachments can also come across with no disposition (and a non-text MIME type) or a disposition of Part.INLINE. When the disposition is either Part.ATTACHMENT or Part.INLINE, you can save off the content for that message part. Just get the original filename with getFileName() and the input stream with getInputStream().
Multipart mp = (Multipart)message.getContent(); for (int i=0, n=multipart.getCount(); i<n; i++) { Part part = multipart.getBodyPart(i)); String disposition = part.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))) { saveFile(part.getFileName(), part.getInputStream()); } }
The saveFile() method just creates a File from the filename, reads the bytes from the input stream, and writes them off to the file. In case the file already exists, a number is added to the end of the filename until one is found that doesn't exist.
// from saveFile() File file = new File(filename);
Page 18
ibm.com/developerWorks
The code above covers the simplest case where message parts are flagged appropriately. To cover all cases, handle when the disposition is null and get the MIME type of the part to handle accordingly.
if (disposition == null) { // Check if plain MimeBodyPart mbp = (MimeBodyPart)part; if (mbp.isMimeType("text/plain")) { // Handle plain } else { // Special non-attachment cases here of image/gif, text/html, ... } ... }
On the receiving end, if you fetch the message with the JavaMail API, there is nothing built into the API to display the message as HTML. The JavaMail API only sees it as a stream of bytes. To display the message as HTML, you must either use the Swing JEditorPane or some third-party HTML viewer component.
if (message.getContentType().equals("text/html")) { String content = (String)message.getContent(); JFrame frame = new JFrame(); JEditorPane text = new JEditorPane("text/html", content); text.setEditable(false); JScrollPane pane = new JScrollPane(text); frame.getContentPane().add(pane); frame.setSize(300, 300); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.show(); }
Including images with your messages: On the other hand, if you want your HTML content message to be complete, with embedded images included as part of the message, you must treat the image as an attachment and reference the image with a special cid URL, where the cid is a reference to the Content-ID header of the image attachment. The process of embedding an image is quite similar to attaching a file to a message, the only
Fundamentals of the JavaMail API Page 19
ibm.com/developerWorks
difference is you have to tell the MimeMultipart that the parts are related by setting its subtype in the constructor (or with setSubType()) and set the Content-ID header for the image to a random string which is used as the src for the image in the img tag. The following demonstrates this completely.
String file = ...; // Create the message Message message = new MimeMessage(session); // Fill its headers message.setSubject("Embedded Image"); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Create your new message part BodyPart messageBodyPart = new MimeBodyPart(); String htmlText = "<H1>Hello</H1>" + "<img src=\"cid:memememe\">"; messageBodyPart.setContent(htmlText, "text/html"); // 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(file); messageBodyPart.setDataHandler(new DataHandler(fds)); messageBodyPart.setHeader("Content-ID","memememe"); // Add part to multi-part multipart.addBodyPart(messageBodyPart); // Associate multi-part with message message.setContent(multipart);
Page 20
ibm.com/developerWorks
There are 22 different classes available to help you build a search term. * * * * * * AND terms (class AndTerm) OR terms (class OrTerm) NOT terms (class NotTerm) SENT DATE terms (class SentDateTerm) CONTENT terms (class BodyTerm) HEADER terms (FromTerm / FromStringTerm, RecipientTerm / RecipientStringTerm, SubjectTerm, etc..)
Essentially, you build up a logical expression for matching messages, then search. For instance the following term searches for messages with a (partial) subject string of ADV or a from field of [email protected]. You might consider periodically running this query and automatically deleting any messages returned.
SearchTerm st = new OrTerm( new SubjectTerm("ADV:"), new FromStringTerm("[email protected]")); Message[] msgs = folder.search(st);
Page 21
ibm.com/developerWorks
If you don't like copying the files to the extension library directory, detailed instructions are available from Sun for setting your CLASSPATH on Windows NT. Task 5: Go into the demo directory that comes with the JavaMail API implementation and compile the msgsend program to send a test message. Help for task 5:
javac msgsend.java
Page 22
ibm.com/developerWorks
Task 6: Execute the program passing in a from address with the -o option, your SMTP server with the -M option, and the to address (with no option). You'll then enter the subject, the text of your message, and the end-of-file character (CTRL-Z) to signal the end of the message input. Help for task 6: Be sure to replace the from address, SMTP server, and to address.
java msgsend -o from@address -M SMTP.Server to@address
If you are not sure of your SMTP server, contact your system administrator or check with your Internet Service Provider. Task 7: Check to make sure you received the message with your normal mail reader (Eudora, Outlook Express, pine, ...).
Task 1: Starting with the skeleton code , get the system Properties. Help for task 1:
Properties props = System.getProperties();
Task 2: Add the name of your SMTP server to the properties for the mail.smtp.host key.
Page 23
ibm.com/developerWorks
Task 3: Get a Session object based on the Properties. Help for task 3:
Session session = Session.getDefaultInstance(props, null);
Task 5: Set the from field of the message. Help for task 5:
message.setFrom(new InternetAddress(from));
Task 10: Compile and run the program, passing your SMTP server, from address, and to address on the command line.
Page 24
ibm.com/developerWorks
Task 11: Check to make sure you received the message with your normal mail reader (Eudora, Outlook Express, pine, ...).
Task 1: Starting with the skeleton code , get or create a Properties object. Help for task 1:
Properties props = new Properties();
Task 2: Get a Session object based on the Properties. Help for task 2:
Session session = Session.getDefaultInstance(props, null);
Task 3: Get a Store for your e-mail protocol, either pop3 or imap. Help for task 3:
Store store = session.getStore("pop3");
Task 4: Connect to your mail host's store with the appropriate username and password.
Page 25
ibm.com/developerWorks
Task 5: Get the folder you want to read. More than likely, this will be the INBOX. Help for task 5:
Folder folder = store.getFolder("INBOX");
Task 7: Get a directory of the messages in the folder. Save the message list in an array variable named message. Help for task 7:
Message message[] = folder.getMessages();
Task 8: For each message, display the from field and the subject. Help for task 8:
System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject());
Task 9: Display the message content when prompted. Help for task 9:
System.out.println(message[i].getContent());
Task 10: Close the connection to the folder and store. Help for task 10:
folder.close(false); store.close();
Task 11: Compile and run the program, passing your mail server, username, and password on the command line. Answer YES to the messages you want to read. Just hit ENTER if you don't. If you want to stop reading your mail before making your way through all the messages, enter QUIT. Help for task 11:
java GetMessageExample POP.Server username password
Page 26
ibm.com/developerWorks
Task 1: The skeleton code already includes the code to get the list of messages from the folder and prompt you to create a reply. Task 2: When answered affirmatively, create a new MimeMessage from the original message. Help for task 2:
MimeMessage reply = (MimeMessage)message[i].reply(false);
Task 3: Set the from field to your e-mail address. Task 4: Create the text for the reply. Include a canned message to start. When the original message is plain text, add each line of the original message, prefix each line with the "> " characters. Help for task 4: To check for plain text messages, check the messages MIME type with mimeMessage.isMimeType("text/plain"). Task 5: Set the message's content, once the message content is fully determined. Task 6: Send the message. Task 7: Compile and run the program, passing your mail server, SMTP server, username, password, and from address on the command line. Answer YES to the messages you want to send replies. Just hit ENTER if you don't. If you want to stop going through your mail before
Page 27
ibm.com/developerWorks
making your way through all the messages, enter QUIT. Help for task 7:
java ReplyExample POP.Server SMTP.Server username password from@address
Task 8: Check to make sure you received the message with your normal mail reader (Eudora, Outlook Express, pine, ...).
Task 1: The skeleton code already includes the code to get the initial mail session. Task 2: From the session, get a Message and set its header fields: to, from, and subject. Task 3: Create a BodyPart for the main message content and fill its content with the text of the message. Help for task 3:
BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText("Here's the file");
Task 4: Create a Multipart to combine the main content with the attachment. Add the main content to the multipart. Help for task 4:
Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart);
Page 28
ibm.com/developerWorks
Task 5: Create a second BodyPart for the attachment. Task 6: Get the attachment as a DataSource. Help for task 6:
DataSource source = new FileDataSource(filename);
Task 7: Set the DataHandler for the message part to the data source. Carry the original filename along. Help for task 7:
messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename);
Task 8: Add the second part of the message to the multipart. Task 9: Set the content of the message to the multipart. Help for task 9:
message.setContent(multipart);
Task 10: Send the message. Task 11: Compile and run the program, passing your SMTP server, from address, to address, and filename on the command line. This will send the file as an attachment. Help for task 11:
java AttachExample SMTP.Server from@address to@address filename
Task 12: Check to make sure you received the message with your normal mail reader (Eudora, Outlook Express, pine, ...).
Page 29
ibm.com/developerWorks
For more help with exercises, see About the exercises on page 22 . Prerequisites: * Exercise 5. How to send attachments on page 28
Task 1: The skeleton code already includes the code to get the initial mail session, create the main message, and fill its headers (to, from, subject). Task 2: Create a BodyPart for the HTML message content. Task 3: Create a text string of the HTML content. Include a reference in the HTML to an image (<img src="...">) that is local to the mail message. Help for task 3: Use a cid URL. The content-id will need to be specified for the image later.
String htmlText = "<H1>Hello</H1>" + "<img src=\"cid:memememe\">";
Task 4: Set the content of the message part. Be sure to specify the MIME type is text/html. Help for task 4:
messageBodyPart.setContent(htmlText, "text/html");
Task 5: Create a Multipart to combine the main content with the attachment. Be sure to specify that the parts are related. Add the main content to the multipart. Help for task 5:
MimeMultipart multipart = new MimeMultipart("related"); multipart.addBodyPart(messageBodyPart);
Task 6: Create a second BodyPart for the attachment. Task 7: Get the attachment as a DataSource, and set the DataHandler for the message part to the data source. Task 8: Set the Content-ID header for the part to match the image reference specified in the HTML. Help for task 8:
messageBodyPart.setHeader("Content-ID","memememe");
Task 9: Add the second part of the message to the multipart, and set the content of the
Fundamentals of the JavaMail API Page 30
ibm.com/developerWorks
message to the multipart. Task 10: Send the message. Task 11: Compile and run the program, passing your SMTP server, from address, to address, and filename on the command line. This will send the images as an inline image within the HTML text. Help for task 11:
java HtmlImageExample SMTP.Server from@address to@address filename
Task 12: Check if your mail reader recognizes the message as HTML and displays the image within the message, instead of as a link to an external attachment file. Help for task 12: If your mail reader can't display HTML messages, consider sending the message to a friend.
Page 31
ibm.com/developerWorks
Resources
You can do much more with the JavaMail API than what's found here. The lessons and exercises found here can be supplemented by the following resources: * * * * * * * * Download the JavaMail 1.2 API from the JavaMail API home page . The JavaBeans Activation Framework is required for versions 1.2 and 1.1.3 of the JavaMail API. The JavaMail-interest mailing list is a Sun-hosted discussion forum for developers. Sun's JavaMail FAQ addresses the use of JavaMail in applets and servlets, as well as prototol-specific questions. Tutorial author John Zukowski maintains jGuru's JavaMail FAQ . Want to see how others are using JavaMail? Check out Sun's list of third-party products. If you want more detail about JavaMail, read Rick Grehan's "How JavaMail keeps it simple" (Lotus Developer Network, June 2000). Benoit Marchal shows how to use Java and XML to produce plain text and HTML newsletters in this two-part series, "Managing e-zines with JavaMail and XSLT" Part 1 (developerWorks, March 2001) and Part 2 (developerWorks, April 2001). "Linking Applications with E-mail" (Lotus Developer Network, May 2000) discusses how groupware can facilitate communication, collaboration, and coordination among applications.
Page 32
ibm.com/developerWorks
Feedback
Please let us know whether this tutorial was helpful to you and how we could make it better. We'd also like to hear about other tutorial topics you'd like to see covered. Thanks! For questions about the content of this tutorial, contact the author John Zukowski ( [email protected] )
Colophon
This tutorial was written entirely in XML, using the developerWorks Toot-O-Matic tutorial generator. The Toot-O-Matic tool is a short Java program that uses XSLT stylesheets to convert the XML source into a number of HTML pages, a zip file, JPEG heading graphics, and PDF files. Our ability to generate multiple text and binary formats from a single source file illustrates the power and flexibility of XML.
Page 33