

자바메일 API는 전자메일을 읽고, 작성하고, 보내기 위한 옵션 패키지(표준 확장)이다. 이 API로 유도라, 파인, 아웃룩과 같은 메일 유저 에이전트(MUA) 타입 프로그램을 생성할 수 있다. 주목적은 sendmail 이나 다른 메일 전송 에이전트(MTA) 타입 프로그램처럼 메시지 전송, 배달, 포워딩이 아니다. 달리말하면, 유저는 MUA타입 프로그램을 이용해서 이메일을 읽거나 쓸 수 있다. MUA는 실제 배달은 MTA에 의존한다.
자바메일 API는 API를 두 부분으로 나누어 메일 송수신에 프로토콜 독립적 접근이 가능하도록 설계 되었다:
자바메일 API 스펙을 살펴보기 앞서, 되돌아가 API가 사용된 프로토콜을 알아보자. 앞으로 알아야 할 4가지 기본적인 프로토콜이 있다.
NNTP나 다른 프로토콜을 통해서도 실행할 수 있다. 기본적인 네가지 프로토콜을 이해하면 자바메일 API를 사용하는 방법을 이해하는데 도움이 될 것이다. API가 프로토콜 인지가 불가능하도록 설계되었기 때문에, 프로토콜 기저의 제한을 극복하는 것은 불가능하다. 만약 기능이 주어진 프로토콜에 의해 지원되지 않으면, 자바메일 API가 그 위에 마술처럼 기능을 붙이진 않는다.(곧 보게되겠지만, 이는 대게 POP로 작업할 때 문제가 된다.)
Simple Mail Transfer Protocol (SMTP)는 이메일 전송 메커니즘이다. 자바메일API의 컨텍스트에서 자바메일 기반 프로그램은 인터넷서비스 공급자의 SMTP 서버와 통신을 할 것이다. 이 SMTP 서버는 수신자의 SMTP서버로 메시지를 전달하게되고, 마지막에는 유저가 POP나 IMAP을 이용해 메시지를 받을 것이다. 이는 SMTP 서버가 공개중계되어야 한다는게 아니라, 인증이 지원되기 때문에, SMTP 서버가 적절하게 설정되어야한다는걸 의미한다. 자바메일 API에는 메일중계나 이메일 계정 추가/삭제 설정같은 작업은 없다.
POP는 Post Office Protocol이다. 현재 버전은 POP3라고 알려진 버전3이고, RFC1939에 정의되어 있다. POP는 인터넷의 대부분의 사람들이 메일을 받기 위해서 사용한다. 이는 각 유저의 단일 메일함에 대한 지원을 정의한다. 이게 POP가 하는 전부이며, 그래서 많은 혼란의 원인이 된다. 사람들이 많이 쓰는 새로운 메시지 수를 볼 수 있는 기능 같은건 POP가 전혀 지원하지 않는다. 최신메일들과 그 숫자가 얼마나 되는지는 유도라나 마이크로소프트 아웃룩과 같은 프로그램에 들어가있다. 그래서, 자바메일API를 쓸때, 이러한 정보를 얻으려면 스스로 계산해봐야한다.
IMAP은 메일 수신에 더 진보한 프로토콜이다. RFC 2060에 정의된 IMAP은 Internet Message Access Protocol을 말하며, 현재 버전은 IMAP4라 알려진 4이다. IMAP을 사용할 때, 메일 서버가 이 프로토콜을 지원해야한다. IMAP을 사용하려고 사용자 프로그램 상에서 POP를 IMAP으로 바꾸고 IMAP이 지원하는 모든걸 기대해봐야 소용없다. 메일서버가 IMAP을 지원한다고 가정하면, 자바메일 베이스 프로그램은 서버에 다수의 폴더를 가지고 여러 사용자가 함께 공유하게 할 수 있는 이점이 있다. 더 진보한 기능사용을 위해서는, 모두가 IMAP을 사용하면 좋겠지만 그렇지 않다. 서버가 새 메시지를 받도록 하고, 필요할때 사용자에게 전달하고, 각각의 사용자에 대해 다수의 폴더를 유지하게 하는건 메일서버에 엄청 무거운 짐이된다. 중앙집중식 백업을 할때, 사용자의 장기 메일폴더가 점점 더 커지면, 모두가 디스크 용량 고갈로 힘들어진다. POP로는 저장된 메시지는 메일서버에서 내려버릴수 있다.
MIME은 Multipurpose Internet Mail Extension이다. 메일 전송 프로토콜이 아니라 전송될 내용을 정의한다:메시지,첨부 등등의 형식. 여기 영향을 주는 여러 문서 있다.RFC 822, RFC 2045, RFC 2046, RFC 2047. 자바메일 API의 사용자라면, 대개 이런 포맷에 대해 걱정할 필요가 없다. 이 포맷들은 프로그램에 사용되기 위해 존재하는 것들이다.
자바메일 API가 공급자와 다른 모든것들을 분리해서 취급하기 때문에, 추가 프로토콜의 지원같은 건 쉽게 할 수 있다. SUN은 사용하는 프로토콜의 서드파티 공급자 리스트를 관리하며, 이 리스트 외의 지원은 제공하지 않는다. 거기서 NNTP(Network News Transport Protocol:Newsgroup), S/MIME(Secure Multipurpose Internet Mail Extension) 등에 대한 지원을 확인할 수 있다.
자바메일 API를 사용하기 위해서는, 자바메일 구현부를 다운로드 받아서 javamail[version].zip 파일 압축을 풀어서 mail.jar 파일을 클래스 경로에 추가해야한다. 구현부에는 코어 클래스 외에 SMTP, IMAP4, POP3 공급자도 있다.
참고 : SUN의 자바메일 구현부를 설치하면, 데모 디렉토리에 예제 프로그램이 많이 있다. |
자바메일 설치 후, JavaBeans Activation Framework를 설치한다.
자바메일API의 모든 버전은 JavaBeans Activation Framework가 필요하다. 프레임워크는 임의의 데이터 블록 형식화와 핸들링에 대한 지원을 추가한다. 이런건 많아 보이진 않지만, 오늘날의 많은 브라우저와 메일 툴에서 볼 수 있는 기본적인 MIME 타입에 대한 지원이다. 프레임워크를 다운로드 받은 후, jaf-[version].zip 파일을 압축해제하여 activation.jar를 클래스 경로에 추가한다
이제 mail.jar와 activation.jar를 클래스 경로에 추가하여야한다.
만약 클래스 경로 환경변수를 바꾸고 싶으면, JAR 파일을 자바 런타임 환경 디렉토리 아래의 lib/ext 디렉토리에 복사한다. 예를 들어, J2SE 1.3릴리즈에서, 기본 디렉토리는 윈도우 플랫폼은 c:\jdk1.3\jre\lib\ext 이다.
만약 J2EE를 사용한다면, 기본적인 자바메일 API를 사용하기 위해 특별히 할 일은 없다; J2EE 클래스에 포함되어 있다. 클래스 경로에 j2ee.jar 파일이 있는걸 확인하였으면, 모두 준비 되었다.
자바 클래스를 깊이 살펴보기 전에, API를 구성하는 코어 클래스는 다음과 같다 : Session, Message, Address, Authenticator, Transport, Store, 그리고 Folder. 이들 클래스 모두는 자바메일 API의 최상위 패키지에 에 있다:javax.mail.internet 패키지에서 찾을 수 있는 서브 클래스를 자주 찾게 될것이다.
The Session class defines a basic mail session. It is through this session that everything else works. TheSession object takes advantage of a java.util.Propertiesobject 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);
Or, you can create a unique session with getInstance():
Properties props = new Properties(); // fill props with any information Session session = Session.getInstance(props, null);
In both cases here the null argument is an Authenticator object which is not being used at this time. More on Authenticator shortly.
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.
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. Being an abstract class, you must work with a subclass, in most cases javax.mail.internet.MimeMessage. A MimeMessage is a email 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 theMimeMessage constructor:
MimeMessage message = new MimeMessage(session);
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 ). The basic mechanism to set the content is the MimePartsetContent() 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. More on HTML messages later though.
For setting the subject, use the setSubject() method:
message.setSubject("First");
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 . Like AddressMessage, Address is an abstract class. You use the javax.mail.internet.InternetAddress class.
To create an address with just the email address, pass the email address to the constructor:
Address address = new InternetAddress("president@whitehouse.gov");
If you want a name to appear next to the email address, you can pass that along to the constructor, too:
Address address = new InternetAddress("president@whitehouse.gov", "George Bush");
You will need to create address objects for the message's from field as well as theto 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:
Address address[] = ...; message.addFrom(address);
For identifying the message recipients, you use the addRecipient() method. This method requires a Message.RecipientType besides the address.
message.addRecipient(type, address)
The three predefined types of address are:
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("vice.president@whitehouse.gov");
Address ccAddress = new InternetAddress("first.lady@whitehouse.gov");
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 email 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.
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 sameAuthenticator as the JavaMail API works with Java 1.1, which didn't have thejava.net variety.
To use the Authenticator, you subclass the abstract class and return a instance from the PasswordAuthenticationgetPasswordAuthentication()method. You must register the Authenticator with the session when created. Then, yourAuthenticator will be notified when authentication is necessary. You could popup a window or read the username and password from a configuration file (though if not encrypted it 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);
The final part of sending a message is to use the Transportclass. This class speaks the 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 |
Getting messages starts similarly to sending messages, with a Session. However, after getting the session, you connect to a Store, quite possibly with a username and password or Authenticator. Like Transport, you tell the Store what protocol to use:
// Store store = session.getStore("imap");
Store store = session.getStore("pop3");
store.connect(host, username, password);
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 |
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.
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.
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.
You've seen how to work with the core parts of the JavaMail API. In the following sections you'll find a how-to approach for connecting the pieces to do specific tasks.
Sending an email 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 theProperties 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.
For reading mail, you get a session, get and connect to an appropriate store for your mailbox, open the appropriate folder, and get your message(s). 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);
// 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 who the message is from and the subject. Technically speaking, the list of from addresses could be empty and thegetFrom()[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 they want 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;
}
}
|
Deleting messages involves working with the Flags associated with the messages. There are different flags for different states, some system-defined and some user-defined. The predefined flags are defined in the inner class Flags.Flagand are listed below:
Flags.Flag.ANSWEREDFlags.Flag.DELETEDFlags.Flag.DRAFTFlags.Flag.FLAGGEDFlags.Flag.RECENTFlags.Flag.SEENFlags.Flag.USERJust because a flag exists doesn't mean the flag is supported by all mail servers/providers. For instance, besides deleting messages, the POP protocol supports none of them. Checking for newmail is not a POP task but one 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);
Open up the folder in READ_WRITE mode first though:
folder.open(Folder.READ_WRITE);
Then, when you are done processing all messages, close the folder, passing in a true value toexpunge 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 with isSet().
You previously learned that you can use anAuthenticator 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 customAuthenticator 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. As this isn't a Project Swing tutorial, just enter the two parts in the one field, separated by a comma.
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);
}
}
|
Since 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.
The Message class includes a reply() method to configure a newMessage 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("president@whitehouse.gov"));
reply.setText("Thanks");
Transport.send(reply);
To configure the reply-to address when sending a message, use the setReplyTo()method.
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 itsDataHandler, a class from the JavaBeans Activation Framework.
// Create the message to forward
Message forward = new MimeMessage(session);
// Fill in header
forward.setSubject("Fwd: " + message.getSubject());
forward.setFrom(new InternetAddress(from));
forward.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Create your new message part
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(
"Here you go with the original message:\n\n");
// Create a multi-part to combine the parts
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Create and fill part for the forwarded content
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(message.getDataHandler());
// Add part to multi part
multipart.addBodyPart(messageBodyPart);
// Associate multi-part with message
forward.setContent(multipart);
// Send message
Transport.send(forward);
|
Attachments are resources associated with a mail message, usually kept outside of the message like a text file, spreadsheet, or image. As with common mail programs like Eudora and pine, you canattach resources to your mail message with the JavaMail API and get those attachments when you receive the message.
Sending attachments is quite like forwarding messages. You build up the parts to make the complete message. After the first part, your message text, you add other parts where the DataHandlerfor each is your attachment, instead of the shared handler in the case of a forwarded message. If you are reading the attachment from a file, your attachment data source is a FileataSource. Reading from a URL, it is a URLDataSource. Once you have your DataSource, just pass it on to theDataHandler constructor, before finally attaching it to the BodyPart withsetDataHandler(). Assuming you want to retain the original filename for the attachment, the last thing to do is to set the filename associated with the attachment with thesetFileName() method of BodyPart. All this is shown here:
// Define message
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
message.setSubject("Hello JavaMail Attachment");
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setText("Pardon Ideas");
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 tell 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 |
Getting attachments out of your messages is a little more involved then sending them, as 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 frompart.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);
for (int i=0; file.exists(); i++) {
file = new File(filename+i);
}
|
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, ...
}
...
}
|
Sending HTML-based messages can be a little more work than sending plain text messages, though it doesn't have to be that much more work. It all depends on your specific requirements.
If all you need to do is send the equivalent of an HTML file as the message and let the mail reader worry about fetching any embedded images or related pieces, use the setContent() method ofMessage, passing along the content as a String and setting the content type totext/html.
String htmlText = "<H1>Hello</H1>" + "<img src=\"http://www.jguru.com/images/logo.gif\">"; message.setContent(htmlText, "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();
}
|
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 specialcid 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 difference is that 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-IDheader for the image to a random string which is used as the src for the image in theimg 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);
|
The JavaMail API includes a filtering mechanism found in the javax.mail.search package to build up a SearchTerm. Once built, you then ask a Folder what messages match, retrieving an array ofMessage objects:
SearchTerm st = ...; Message[] msgs = folder.search(st);
There are 22 different classes available to help you build a search term.
AndTerm)OrTerm)NotTerm)SentDateTerm)BodyTerm)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 friend@public.com. You might consider periodically running this query and automatically deleting any messages returned.
SearchTerm st =
new OrTerm(
new SubjectTerm("ADV:"),
new FromStringTerm("friend@public.com"));
Message[] msgs = folder.search(st);
|
You can do much more with the JavaMail API than what's described here. The lessons and exercises found here can be supplemented by the following resources: