JavaMail API简介

JavaMail API简介 
JavaMail API是一种可选的、能用于读取、编写和发送电子消息的包(标准扩展)。您可使用这种包创建邮件用户代理(Mail User Agent ,MUA) 类型的程序,它类似于Eudora、Pine及Microsoft Outlook这些邮件程序。其主要目的不是像发送邮件或其他邮件传输代理(Mail Transfer Agent,MTA)类型的程序那样用于传输、发送和转发消息。换句话说,用户可以与MUA类型的程序交互,以阅读和撰写电子邮件。MUA依靠MTA处理实际的发送任务。 
JavaMail API的设计是,为收发信息提供与协议无关的访问。方式是把该API划分成两个部分: 
· 该API的第一个部分是本课程的重点。基本上是如何发送和接收独立于提供程序/协议的消息。 
· 第二个部分则使用特定的协议语言,如:SMTP、POP、IMAP和NNTP。如果要让JavaMail API与服务器通信,就需要为之提供协议。由于Sun公司对特定协议提供程序有充分的介绍,用户可以免费获取,所以本课程没有介绍创建特定协议提供程序的内容。 
复习相关协议 
在学习JavaMail API的深层知识之前,让我们回过头来看一看在该API中使用的协议,本质上有4种人们常用的协议: 
· SMTP 
· POP 
· IMAP 
· MIME 
您还需要了解NNTP及其他一些协议。理解这些协议的基本原理有助于您理解如何使用JavaMail API。而该API的设计要与协议无关,所以不能克服这些基础协议的限制。如果选用的协议不支持某种功能,那么JavaMail API也无法在其上添加这种功能。(正如您一会儿就会看到的,在操作POP协议时,常常会碰到这种问题)。 
SMTP 
简单邮件传输协议(SMTP)是用于传送电子邮件的机制。在JavaMail API环境中,您的基于JavaMail的程序将与您公司或Internet服务提供商(ISP)的SMTP服务器通信。该SMTP服务器将会把消息转发给用作接收消息的SMTP服务器,最后用户可通过POP或IMAP协议获取该消息。由于支持身份验证,所以不需要SMTP服务器是一种开放的转发器,但需要确保SMTP服务器配置正确。JavaMail API中没有集成用于处理诸如配置服务器以转发消息或添加/删除电子邮件帐户这一类任务的功能。 
POP 
POP的含义是邮局协议,当前的版本为3,也称作POP3,该协议是在RFC 1939中定义的。POP是Internet上的大多数人用来接收邮件的机制。它为每个用户的每个邮箱定义支持,这是它所做的全部工作,也是大多数问题的根源。在使用POP协议时,人们熟悉的很多功能,如查看收到了多少新邮件消息的功能,POP根本不支持。这些功能都内置到诸如Eudora或Microsoft Outlook之类的邮件程序中,能为您记住接收的上一封邮件,以及计算有多少新邮件这类信息。因此,使用JavaMail API时,如果想获取这类信息,将需要由自己进行计算。 
IMAP 
IMAP是用于接收消息的更加高级的协议,它是在RFC 2060中定义的。IMAP的含义是“Internet消息访问协议”,当前版本是第4版,也称作IMAP4。使用IMAP时,您的邮件服务器必须支持该协议。您不能只是简单地把程序转变为支持IMAP,而不是支持POP,就指望能支持IMAP中的一切。假定您的邮件服务器支持IMAP,那么基于JavaMail的程序就可利用在服务器上拥有多个文件夹的用户,并且这些文件夹可以被多个用户共享的功能。 
由于IMAP协议具有更高级的功能,您也许会想IMAP应该被每一个人使用,但事实不是这样。因为IMAP会加重邮件服务器的负荷,它需要服务器接收新消息,发送消息给请求的用户,并在多个文件夹中为每个用户维护这些消息。而这要集中备份,因而长期下去用户的文件夹会变得越来越大,当磁盘空间用光了时,每个人都会遭受损失。而使用POP协议时,已保存消息可以解除服务器的重负。 
MIME 
MIME的含义是“多用途的网际邮件扩充协议”。它不是一种邮件传输协议,相反,它定义传输的内容:消息的格式、附件等。许多文档都定义了MIME协议,包含:RFC 822、RFC 2045、RFC 2046和RFC 2047。作为JavaMail API的用户,一般不需要担心这些格式。但是,这些格式确实存在,并为您的程序所用。 
NNP和其他协议 
由于JavaMail API分开了提供程序和其他部分,所以您可以轻松地为附加协议添加支持。Sun公司提供第3方提供程序清单,这些提供程序要利用 Sun公司不支持的少见的协议。在这份清单中,您将会看到对NNTP(网络新闻传输协议)[新闻组]、S/MIME(安全多用途的网际邮件扩充协议)及其他协议的提供支持的第3方提供程序。 
安装 
目前有两种版本的JavaMail API最常用:1.2和1.1.3。本课程中的所有例子都适用于这两种版本。其中JavaMail API 1.2是最新的,而JavaMail API 1.1.3中包含了Java 2企业版(J2EE)平台1.2.1版,所以它仍然很常用。使用JavaMail API的版本会对您的下载和安装产生一些影响。这两种版本的JavaMail API都能与JDK 1.1.6、Java 2标准版(J2SE)平台1.2.x和1.3.x协同工作。 
注意:在安装了Sun公司的JavaMail工具后,会在演示目录下看到许多示例程序。 
安装JavaMail 1.2 
要使用JavaMail 1.2 API,可以下载JavaMail 1.2工具,然后解压缩javamail-1_2.zip文件,并把mail.jar文件添加到典型安装路径下。JavaMail 1.2工具带有SMTP、IMAP4和POP3提供程序以及核心类。 
安装完JavaMail 1.2后,再安装JavaBeans Activation Framework。 
安装JavaMail 1.1.3 
要使用JavaMail 1.1.3 API,可以下载JavaMail 1.1.3工具,然后解压缩javamail1_1_3.zip文件,并把mail.jar文件添加到典型安装路径下。JavaMail 1.1.3工具带有SMTP和IMAP4提供程序以及核心类。 
如果您想用JavaMail 1.1.3访问POP服务器,需要下载并安装POP3提供程序。Sun公司拥有一个独立于 JavaMail 工具的提供程序。在下载并解压缩pop31_1_1.zip文件后,也还需要把pop3.jar添加到典型安装路径下。 
安装完JavaMail 1.1.3后,再安装JavaBeans Activation Framework。 
安装JavaBeans Activation Framework 
JavaMail API的所有版本都需要JavaBeans Activation Framework(JavaBeans激活框架),这种框架提供了对输入任意数据块的支持,并能相应地对其进行处理。看上去效果好像不太好,但该框架是在当今的许多浏览器和邮件工具中可以找到的基本MIME类型支持。下载该框架后,解压缩jaf1_0_1.zip文件,并将activation.jar文件添加到典型安装路径下。 
对于JavaMail 1.2用户,现在应该把mail.jar和activation.jar文件添加到典型安装路径下。 
对于JavaMail 1.1.3用户,现在应该把mail.jar、pop3.jar和activation.jar添加到典型安装路径下。如果您不打算使用POP3,就不需要把pop3.jar文件添加到典型安装路径下。 
如果您不想更改安装路径环境变量,可以把JAR文件复制到Java运行时环境(JRE)目录下的lib/ext目录下。例如,对于J2SE 1.3版本,Windows平台上的默认目录应该是C:/jdk1.3/jre/lib/ext。 
使用Java 2企业版 
如果您使用的是J2EE,则在使用基本JavaMail API时,不需要做什么特殊的工作;JavaMail API带有J2EE类。只要确保j2ee.jar文件位于典型安装路径下,并完成了所有的设置工作。 
对于J2EE 1.2.1,POP3提供程序是单独提供的,因此需要下载该提供程序,并按安装JavaMail 1.1.3的步骤,在J2EE 1.2.1中包含POP3提供程序。J2EE 1.3的用户会获得J2EE和POP3提供程序,因而不需要对POP3提供程序执行独立安装。使用这两种版本的J2EE用户,都不需要安装JavaBeans Activation Framework。 
练习 
设置您的 JavaMail 环境。 
复习核心类 
在开始深入研究JavaMail类之前,首先让用户浏览一下构成API的核心类:会话、消息、地址、验证程序、传输,存储和文件夹。所有这些类都可以在JavaMail API即javax.mail的顶层包中找到,尽管您将频繁地发现您自己使用的子类是在javax.mail.internet包中找到的。 
Session类 
Session类定义了一个基本的邮件会话。通过该会话可让别的工作顺利执行。Session对象利用java.util.Properties对象获取诸如邮件服务器、用户名、密码等信息,以及其他可在整个应用程序中共享的信息。 
Session类的构造器是私有的。您可以获得一个可被getDefaultInstance()方法共享的单一的默认会话: 
Properties props = new Properties(); 
// fill props with any information 
Session session = Session.getDefaultInstance(props, null); 
或者,您可以用getInstance()方法创建一个独特的会话: 
Properties props = new Properties(); 
// fill props with any information 
Session session = Session.getInstance(props, null); 
这两种情形下的null参数都是一种Authenticator对象,它不是在此时使用的。详细信息请参阅其后的“Autherticator”一节。 
在大多数情况下,使用共享会话就足够了,即使为多个用户邮箱处理邮件会话也是如此。您可以在通信过程的后面一步添加上用户名和密码的组合,并保持所有的一切是独立的。 
Message类 
一旦创建了自己的Session对象,就是该去创建要发送的消息的时候了。这时就要用到消息类型。作为一个抽象类,您必须操作一个子类,在大多数情况下,该子类是javax.mail.internet.MimeMessage。一个MimeMessage是一种理解MIME类型和报头(在不同的RFC文档中均有定义)的消息。消息的报头被严格限制成只能使用US-ASCII字符,尽管非ASCII字符可以被编码到某些报头字段中。 
可以通过将Session对象传递给MimeMessage构造器的方法来创建消息: 
MimeMessage message = new MimeMessage(session); 
注意:还有其他的构造器,像用于创建消息的源于RFC822格式化的输入流的构造器。 
一旦创建了消息,就可以设置其各个部分,如Message(消息)实现Part(部分)接口(以MimeMessage实现MimePart)。设置内容的基本机制是setContent()方法,它带有表示内容和MIME类型的参数: 
message.setContent("Hello", "text/plain"); 
但是,如果正在使用 MimeMessage,并且您的消息是纯文本,那么您就可以使用setText()方法。该方法只需要一个表示实际内容的参数,默认的MIME类型为纯文本: 
message.setText("Hello"); 
对于纯文本消息,setText()方法更常常被用来设置内容。要发送其他类型的消息,如HTML消息,就要使用setContent方法()。现在用的更多的是HTML消息。 
要设置主题,可以使用setSubject()方法: 
message.setSubject("First"); 
Address类 
一旦创建了会话和消息,并为消息填充了内容,就需要用Address类为您的信件标上地址了。同Message类一样,Address类也是一种抽象类。您可以使用javax.mail.internet.InternetAddress类。 
要创建只带有电子邮件地址的地址,可以把电子邮件地址传递给Address类的构造器: 
Address address = new InternetAddress("president@whitehouse.gov"); 
如果想让一个名字出现在电子邮件地址后,也可以将其传递给构造器: 
Address address = new InternetAddress("president@whitehouse.gov", "George Bush"); 
您要为消息的from(发送者)字段和to(接收者)字段创建地址对象。除非您的邮件服务器阻止这样做,否则要在发送的消息中注明该消息的发送者。 
一旦创建好了地址,有两种方法可让您将地址与消息连接起来。为了鉴别发送者,您可以使用setFrom()和setReplyTo()方法。 
message.setFrom(address) 
如果您的消息需要显示多个地址来源,则可以使用addFrom()方法: 
Address address[] = ...; 
message.addFrom(address); 
为了鉴别消息接收者,您可以使用addRecipient()方法。该方法除了需要一个地址参数外,还需要一个Message.RecipientType属性(消息的接收类型)。 
message.addRecipient(type, address) 
地址的3种预定义类型如下: 
· Message.RecipientType.TO 
· Message.RecipientType.CC 
· Message.RecipientType.BCC 
因此,如果一条消息将发送给副总统,同时还将发送该消息的副本给第一夫人,则采用下面的代码: 
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); 
JavaMail API没有提供检查电子邮件地址有效性的机制。您可以自己编写支持扫描有效字符(在RFC 822文档中所定义的)的程序或检验MX(邮件交换)记录,这些都超越了JavaMail API的范围。 
Authenticator类 
与java.net类一样,JavaMail API可以利用Authenticator(验证程序)类通过用户名和密码来访问受保护的资源。对于JavaMail API来说,这种受保护的资源是指邮件服务器。JavaMail的Authenticator类可以在javax.mail包中找到,并有别于同名的java.net类。当JavaMail API在Java 1.1下工作时,JavaMail和java.net不会共享同一个Authenticator类名称,这是因为Java 1.1中不含有java.net。 
要使用Authenticator类,您可以使用该抽象类的子类,并通过getPasswordAuthentication()方法返回一个PasswordAuthentication实例。在创建时,您必须用会话记录Authentication类。其后,当需要进行身份验证时,会通知您的Authenticator。会弹出一个窗口,或从一个配置文件(尽管不加密就不安全)中读取用户名和密码,并把它们作为一个PasswordAuthentication对象返回给调用程序。 
Properties props = new Properties(); 
// fill props with any information 
Authenticator auth = new MyAuthenticator(); 
Session session = Session.getDefaultInstance(props, auth); 
Transport类 
发送消息的最后一步操作是使用Transport类。该类使用特定于协议(通常是SMTP)的语言来发送消息。它是一个抽象类,其操作与Session类有些相似。您可以通过只调用静态的send()方法来使用该类的默认版本: 
Transport.send(message); 
或者,您可以从用于您的协议的会话中获取一个特定的实例,然后传递用户名和密码(不必要时可以为空)并发送消息,最后关闭连接: 
message.saveChanges(); // implicit with send() 
Transport transport = session.getTransport("smtp"); 
transport.connect(host, username, password); 
transport.sendMessage(message, message.getAllRecipients()); 
transport.close(); 
当您需要发送多个消息时,建议采用后一种方法,因为它将保持消息间活动服务器的连接。而基本的send()机制会为每一个方法调用都建立一条独立的连接。 
注意:要查看经过邮件服务器邮件命令,可以用session.setDebug(true)方法设置调试标志。 
Store和Folder类 
使用Session类来获取消息,开始时与发送消息很相似。但是,在获取会话后,很有可能使用用户名和密码或Authenticator类来连接Store类。与Transport类一样,您要告诉Store类将使用什么协议: 
// Store store = session.getStore("imap"); 
Store store = session.getStore("pop3"); 
store.connect(host, username, password); 
在连接Store类后,就可以获取一个Folder类,在读取其中的消息前必须先打开该类。 
Folder folder = store.getFolder("INBOX"); 
folder.open(Folder.READ_ONLY); 
Message message[] = folder.getMessages(); 
对于POP3协议,惟一可用的文件夹是INBOX。如果使用的是IMAP协议,则可以使用其他的文件夹。 
注意:Sun公司的提供程序本来想提供方便。而Message message[]=folder.getMessages();这条语句却是一种从服务器逐条读取消息的缓慢操作,所以仅当您确实需要获取消息部分(该内容是所检索消息的内容)时可以使用这条语句。 
一旦读取消息,就可以使用getContent()方法获取其内容,或使用writeTo()方法将其内容写到一个流中。getContent()方法只获取消息内容,而writeTo()方法则还会输出报头。 
System.out.println(((MimeMessage)message).getContent()); 
一旦您阅读完邮件,就可以关闭对文件夹和存储的连接。 
folder.close(aBoolean); 
store.close(); 
传递给文件夹的close()方法的布尔变量指定了是否通过清除已删除的消息来更新文件夹。 
继续前进 
实际上,理解使用这7个类的方式,是使用JavaMail API处理几乎所有事情所需要的全部内容。用这7个类以外的方式构建的JavaMail API,其大多数功能都是以几乎完全相同或特定的方式来执行任务的,就好像内容是附件。特定的任务,如:搜索、隔离等将在后面进行介绍。 
使用JavaMail API 
您已经看到了如何操作JavaMail API的核心部分。在下面几节中,您将学习如何连接几个部分以执行特定的任务。 
发送消息 
发送电子邮件消息涉及到获取会话、创建和填充消息并发送消息这些操作。您可以在获取Session时,通过为要传递的Properties对象设置mail.smtp.host属性来指定您的SMTP服务器。 
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); 
您应该在try-catch块中编写代码,以在创建消息并发送它时可以抛出一个异常。 
练习 
发送您的第一个消息 
获取消息 
对于阅读邮件来说,首先您要获取一个会话,然后获取并连接到一个相应的用于您的收件箱的存储上,接着打开相应的文件夹,再获取消息。同时,不要忘记了操作完成后关闭连接。 
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(); 
每一条消息执行何种操作取决于自己决定。上面的代码块只是显示了消息的发送者和主题。从技术上讲,发送者地址列表可以为空,此时getFrom()[0]调用会抛出一个异常。 
为了显示整条消息,您可以提示用户在看完消息的发送者和主题字段后,如果想看到消息的内容,可以再调用消息的writeTo()方法。 
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; 


练习 
检查邮件 
删除消息和标志 
删除消息涉及到操作与消息关联的标志。对不同的状态有不同的标志,有些标志是系统定义的,有些则是由用户定义的。预定义的标志都是在内部类Flags.Flag中定义的,如下所示: 
· Flags.Flag.ANSWERED 
· Flags.Flag.DELETED 
· Flags.Flag.DRAFT 
· Flags.Flag.FLAGGED 
· Flags.Flag.RECENT 
· Flags.Flag.SEEN 
· Flags.Flag.USER 
仅仅因为标志存在,并不表示标志为所有的邮件服务器/提供程序所支持。例如,除了删除消息外,POP协议对它们都不支持。检查新邮件不是POP的任务,但它已内置到邮件客户程序中。要搞清楚什么标志受到支持,可以使用getPermanentFlags()方法来询问文件夹。 
要删除消息,需要为消息设置DELETE标志: 
message.setFlag(Flags.Flag.DELETED, true); 
第一次以READ_WRITE(读-写)模式打开文件夹: 
folder.open(Folder.READ_WRITE); 
然后,处理完了所有的消息,请关闭文件夹,并传递true值以擦去删除的消息。 
folder.close(true); 
用户可使用Folder类的expunge()方法来删除消息。但是,该方法对Sun公司的POP3提供程序不起作用。其他提供程序或许能也或许不能实现其功能。它更有可能适用于IMAP提供程序。由于POP只支持对收件箱的简单访问,使用Sun公司的提供程序时,您将不得不关闭文件夹以删除消息。 
要移去标志,只需传递一个false值给setFlag()方法。要看看是否设置了某个标志,可以使用isSet()进行检查。 
自我验证 
先前学到的是使用Authenticator类,以在需要时提示输入用户名和密码,而不是以字符串的形式传入它们。这里,您将真正看到如何更加充分地使用验证。 
不需使用主机、用户名和密码连接到Store,您可以配置Properties带有主机,并告诉Session关于您自定义的Authenticator实例,如下所示: 
// 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(); 
然后您可以使用Authenticator类的子类,并通过getPasswordAuthentication()方法返回一个PasswordAuthentication对象。下面是这种实现的一个例子,其中一个字段同时适用于两部分内容。它不是一个Project Swing指南,只是在一个字段中输入了两部分内容,它们是用逗号隔开的。 
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); 


由于PopupAuthenticator依赖于Swing,因而将会启动用于AWT的事件处理线程。这在本质上要求您在代码中添加一个对System.exit()的调用,以终止程序的执行。 
回复消息 
Message类包含一个reply()方法,以用正确的接收者和主题(添加“Re::”,如果没有的话)配置一条新消息。该方法不会为消息添加任何内容,只是为新的接收者复制发送者或回复到的报头。该方法使用一个布尔型参数,提示是否只回复给发送者(false)或回复给所有人(true)。 
MimeMessage reply = (MimeMessage)message.reply(false); 
reply.setFrom(new InternetAddress("president@whitehouse.gov")); 
reply.setText("Thanks"); 
Transport.send(reply); 
在发送消息时要配置回复到地址,可使用setReplyTo()方法。 
练习 
回复邮件 
转发消息 
转发消息涉及的内容要稍微多一点,没有一个专门用于转发消息的方法,您可以通过处理组成消息的各个部分来创建要转发的消息。 
一条邮件消息可由多个部分组成,每一部分是一个BodyPart(报文部分),或更特殊一点,在操作MIME消息时则是MimeBodyPart。不同的报文部分组合到一个称为Multipart的容器中,或者又更特殊一点,是一个MimeMultipart容器。要转发消息,您要创建一个用于消息文本的部分,和用于要转发的消息的第二个部分,并将这两个部分组合成一个multipart(多个部分)。然后您可以把这个multipart添加到一个合适的注明地址的消息中并发送它。 
这就是转发消息的本质。要把一条消息的内容复制给另一条消息,只需通过它的DataHandler类复制即可,它是出自于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); 
操作附件 
附件是与邮件消息关联的资源,通常保存在消息之外,如:一个文本文件,电子表格或图片。对于像Eudora和Pine之类的常用邮件程序,您可以通过JavaMail API把资源附加到邮件消息上,并在您接收消息时获取附件。 
发送附件 
发送附件与转发消息非常相似,您要创建组成完整消息的各个部分。在创建好第一个部分即消息文本之后,您添加的用DataHandler类处理的其他部分就是您的附件,而不是转发消息中的共享处理程序。当您从一个文件读取附件时,附件的数据资源是FileDataSource;从URL读取时,则是URLDataSource。一旦您有了自己的DataSource,在将其通过setDataHandler()方法最终附加到BodyPart上之前,只需将其传递给DataHandler类的构造器即可。假定您想保留附件的原始文件名,要做的最后一件事就是用BodyPart类的setFileName()方法设置与附件关联的文件名。所有这些操作如下所示: 
// 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); 
在消息中包含附件时,如果您的程序是一个servlet,您的用户就必须上传附件,并告诉您要把消息发送到什么位置。上传的每一个文件都可以用一个表单来处理,该表单是以multipart/表单数据(form-data)来编码的。 
<FORM ENCTYPE="multipart/form-data" 
method=post action="/myservlet"> 
<INPUT TYPE="file" NAME="thefile"> 
<INPUT TYPE="submit" VALUE="Upload"> 
</FORM> 
注意:消息的大小要受到您的SMTP服务器的限制,而不是由JavaMail API限制的。如果出现了问题,可以通过设置ms和mx参数来考虑增加Java堆区的空间尺寸。 
练习 
发送附件 
获取附件 
从消息中取出附件比发送附件涉及的操作要稍微多一点,而MIME没有简单的附件概念。当消息带有附件时,消息的内容就是一个Multipart对象。然后需要处理各个部分,以获取主要内容和附件。通过part.getDisposition()方法标记上Part.ATTACHMENT配置的部分显然就是附件。同时,附件也可以不带有配置(和非文本MIME类型)或Part.INLINE配置。当配置是Part.ATTACHMENT或Part.INLINE时,您可以脱离该消息部分的内容将其保存起来。只需通过getFileName()方法获取原始文件名,并通过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()); 


saveFile()方法只用于根据文件名创建一个文件,从输入流中读取字节,并将它们写入一个文件中去。如果文件已存在,将在文件名后添加一个编号,直到找到一个不存在的文件为止。 
// from saveFile() 
File file = new File(filename); 
for (int i=0; file.exists(); i++) { 
file = new File(filename+i); 

上面的代码介绍了消息的各个部分被标上相应的标志的一个最简单的例子。要想包含所有的情况,还要对disposition值为null及消息部分为MIME类型的情况作相应处理。 
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, ... 

... 

处理HTML消息 
发送基于HTML的消息比发送纯文本消息要稍微复杂一点,尽管它不需要做大量的工作。它全部取决于您特定的需求。 
发送HTML消息 
如果您所要做的全部工作是发送一个等价的HTML文件作为消息,并让邮件阅读者忧心于取出任何嵌入的图片或相关片段,那么就可以使用消息的setContent()方法,以字符串形式传递消息内容,并把内容类型设置为text/html。 
String htmlText = "<H1>Hello</H1>" + 
"<img src=/"http://www.jguru.com/images/logo.gif/">"; 
message.setContent(htmlText, "text/html")); 
在接收端,如果您用JavaMail API获取消息,在该API中没有内置任何用于以HTML格式显示消息的功能。JavaMail API只以字节流的形式来查看消息。要以HTML格式显示消息,您必须使用Swing JeditorPane或某些第3方HTML阅读器组件。 
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(); 

在消息中包含图片 
另一方面,如果您的HTML消息中嵌入了作为消息一部分的图片,并且您想保持消息内容的完整,就必须把图片看作附件,并用特殊的通信标识符URL引用该图片,该通信标识符引用的是图片附件的内容ID报文。 
嵌入图片的处理与附加一个文件到消息上非常相似,惟一的不同之处在于:您必须区分MimeMultipart中,哪些部分是在构造器(或通过setSubType()方法)通过设置其子类型而使之相关的,以及将图片的内容ID报头设置成任意字符串,它将在img标记中用作图片的源路径。下面显示了一个完整的示例: 
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); 
练习 
发送带有图片的 HTML 消息 
用SearchTerm搜索 
JavaMail API包含一种可用于创建SearchTerm(搜索条件)的筛选机制,它可以在javax.mail.search包中找到。一旦创建了SearchTerm,您就可以询问某个文件夹匹配的消息,并检索出消息对象数组: 
SearchTerm st = ...; 
Message[] msgs = folder.search(st); 
有22种不同的类可用于帮助创建搜索条件。 
· AND条件(AndTerm类) 
· OR条件(OrTerm类) 
· NOT条件(NotTerm类) 
· SENT DATE条件(SentDateTerm类) 
· CONTENT条件(BodyTerm类) 
· HEADER条件(FromTerm / FromStringTerm, RecipientTerm / RecipientStringTerm, SubjectTerm, etc.) 
本质上,您可以为匹配的消息创建一个逻辑表达式,然后进行搜索。例如,下面显示了一条消息的条件搜索示例,该消息带有(部分带有)一个ADV主题字符串,其发送者字段为friend@public.com。您可能考虑定期运行该查询,并自动删除任何返回的消息。 
SearchTerm st = 
new OrTerm( 
new SubjectTerm("ADV:"), 
new FromStringTerm("friend@public.com")); 
Message[] msgs = folder.search(st);  
Fundamentals of the JavaMail API Presented by developerWorks, your source for great tutorials ibm.com/developerWorks 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 2. Introducing the JavaMail API 3 3. Reviewing related protocols 4 4. Installing JavaMail 6 5. Reviewing the core classes 8 6. Using the JavaMail API 13 7. Searching with SearchTerm 21 8. Exercises 22 9. Wrapup 32 Fundamentals of the JavaMail API Page 1 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 1. Tutorial tips Should I take this tutorial? Looking to incorporate mail facilities into your platform-independent Java solutions? Look no further than the JavaMail API, which offers a protocol-independent model for working with IMAP, POP, SMTP, MIME, and all those other Internet-related messaging protocols. With the help of the JavaBeans Activation Framework (JAF), your applications can now be mail-enabled through the JavaMail API. Concepts After completing this module you will understand the: * Basics of the Internet mail protocols SMTP, POP3, IMAP, and MIME * Architecture of the JavaMail framework * Connections between the JavaMail API and the JavaBeans Activation Framework 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 producer@jguru.com . 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 . Fundamentals of the JavaMail API Page 2 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 2. Introducing the JavaMail API What is the JavaMail API? The JavaMail API is an optional package (standard extension) for reading, composing, and sending electronic messages. You use the package to create Mail User Agent (MUA) type programs, similar to Eudora, pine, and Microsoft Outlook. The API's main purpose is not for transporting, delivering, and forwarding messages; this is the purview of applications such as sendmail and other Mail Transfer Agent (MTA) type programs. MUA-type programs let users read and write e-mail, whereas MUAs rely on MTAs to handle the actual delivery. The JavaMail API is designed to provide protocol-independent access for sending and receiving messages by dividing the API into two parts: * The first part of the API is the focus of this course --basically, how to send and receive messages independent of the provider/protocol. * The second part speaks the protocol-specific languages, like SMTP, POP, IMAP, and NNTP. With the JavaMail API, in order to communicate with a server, you need a provider for a protocol. The creation of protocol-specific providers is not covered in this course because Sun provides a sufficient set for free. Fundamentals of the JavaMail API Page 3 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 3. Reviewing related protocols Introduction Before looking into the JavaMail API specifics, let's step back and take a look at the protocols used with the API. There are basically four that you'll come to know and love: * SMTP * POP * IMAP * MIME 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 Presented by developerWorks, your source for great tutorials 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. NNTP and others Because of the split of the JavaMail API between provider and everything else, you can easily add support for additional protocols. Sun maintains a list of third-party providers that take advantage of protocols for which Sun does not provide out-of-the-box support. You'll find support for NNTP (Network News Transport Protocol) [newsgroups], S/MIME (Secure Multipurpose Internet Mail Extensions), and more. Fundamentals of the JavaMail API Page 5 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 4. Installing JavaMail Introduction There are two versions of the JavaMail API commonly used today: 1.2 and 1.1.3. All the examples in this course will work with both. While 1.2 is the latest, 1.1.3 is the version included with the 1.2.1 version of the Java 2 Platform, Enterprise Edition (J2EE), so it is still commonly used. The version of the JavaMail API you want to use affects what you download and install. All will work with JDK 1.1.6+, Java 2 Platform, Standard Edition (J2SE) version 1.2.x, and J2SE version 1.3.x. Note: After installing Sun's JavaMail implementation, you can find many example programs in the demo directory. Installing JavaMail 1.2 To use the JavaMail 1.2 API, download the JavaMail 1.2 implementation, unbundle the javamail-1_2.zip file, and add the mail.jar file to your CLASSPATH. The 1.2 implementation comes with an SMTP, IMAP4, and POP3 provider besides the core classes. After installing JavaMail 1.2, install the JavaBeans Activation Framework. Installing JavaMail 1.1.3 To use the JavaMail 1.1.3 API, download the JavaMail 1.1.3 implementation, unbundle the javamail1_1_3.zip file, and add the mail.jar file to your CLASSPATH. The 1.1.3 implementation comes with an SMTP and IMAP4 provider, besides the core classes. If you want to access a POP server with JavaMail 1.1.3, download and install a POP3 provider. Sun has one available separate from the JavaMail implementation. After downloading and unbundling pop31_1_1.zip, add pop3.jar to your CLASSPATH, too. After installing JavaMail 1.1.3, install the JavaBeans Activation Framework. Installing the JavaBeans Activation Framework All versions of the JavaMail API require the JavaBeans Activation Framework. The framework adds support for typing arbitrary blocks of data and handling it accordingly. This doesn't sound like much, but it is your basic MIME-type support found in many browsers and mail tools today. After downloading the framework, unbundle the jaf1_0_1.zip file, and add the activation.jar file to your CLASSPATH. For JavaMail 1.2 users, you should now have added mail.jar and activation.jar to your CLASSPATH. For JavaMail 1.1.3 users, you should now have added mail.jar, pop3.jar, and activation.jar to your CLASSPATH. If you have no plans of using POP3, you don't Fundamentals of the JavaMail API Page 6 Presented by developerWorks, your source for great tutorials 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. Using JavaMail with the Java 2 Enterprise Edition If you use J2EE, there is nothing special you have to do to use the basic JavaMail API; it comes with the J2EE classes. Just make sure the j2ee.jar file is in your CLASSPATH and you're all set. For J2EE 1.2.1, the POP3 provider comes separately, so download and follow the steps to include the POP3 provider as shown in the previous section "Installing JavaMail 1.1.3." J2EE 1.3 users get the POP3 provider with J2EE so do not require the separate installation. Neither installation requires you to install the JavaBeans Activation Framework. Exercise Exercise 1. How to set up a JavaMail environment on page 22 Fundamentals of the JavaMail API Page 7 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 5. Reviewing the core classes Introduction Before taking a how-to approach at looking at the JavaMail classes in depth, this section walks you through the core classes that make up the API: Session, Message, Address, Authenticator, Transport, Store, and Folder. All these classes are found in the top-level package for the JavaMail API, javax.mail, though you'll frequently find yourself using subclasses found in the javax.mail.internet package. 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); Or, you can create a unique session with getInstance(): 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); Fundamentals of the JavaMail API Page 8 Presented by developerWorks, your source for great tutorials 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("president@whitehouse.gov"); 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("president@whitehouse.gov", "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: Fundamentals of the JavaMail API Page 9 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks 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: * Message.RecipientType.TO * Message.RecipientType.CC * Message.RecipientType.BCC 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 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 Presented by developerWorks, your source for great tutorials 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). Store and folder 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 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. Fundamentals of the JavaMail API Page 11 Presented by developerWorks, your source for great tutorials 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. Fundamentals of the JavaMail API Page 12 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 6. Using the JavaMail API Introduction 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 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); Fundamentals of the JavaMail API Page 13 Presented by developerWorks, your source for great tutorials 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; } } Exercise: Exercise 3. How to check for mail on page 25 Deleting messages and flags 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.Flag and are listed below: * Flags.Flag.ANSWERED * Flags.Flag.DELETED * Flags.Flag.DRAFT * Flags.Flag.FLAGGED * Flags.Flag.RECENT * Flags.Flag.SEEN * Flags.Flag.USER Fundamentals of the JavaMail API Page 14 Presented by developerWorks, your source for great tutorials 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); 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 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 Presented by developerWorks, your source for great tutorials 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("president@whitehouse.gov")); 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 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks DataHandler , 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); Working with attachments 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 can attach resources to your mail message with the JavaMail API and get those attachments when you receive the message. Sending attachments: 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 DataHandler for 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 FileDataSource . Reading from a URL, it is a URLDataSource . Once you have your DataSource, just pass it on to the DataHandler constructor, before finally attaching it to the BodyPart with setDataHandler(). 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 the setFileName() 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"); Fundamentals of the JavaMail API Page 17 Presented by developerWorks, your source for great tutorials 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); Fundamentals of the JavaMail API Page 18 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks 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, ... } ... } Processing HTML messages Sending HTML-based messages can be a little more work than sending plain text message, though it doesn't have to be that much more work. It all depends on your specific requirements. Sending HTML messages: 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 of Message, passing along the content as a String and setting the content type to text/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(); } 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 Presented by developerWorks, your source for great tutorials 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); Exercise: Exercise 6. How to send HTML messages with images on page 29 Fundamentals of the JavaMail API Page 20 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 7. Searching with SearchTerm Introduction 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 of Message objects: SearchTerm st = ...; Message[] msgs = folder.search(st); 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 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); Fundamentals of the JavaMail API Page 21 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 8. Exercises About the exercises These exercises are designed to provide help according to your needs. For example, you might simply complete the exercise given the information and the task list in the exercise body; you might want a few hints; or you may want a step-by-step guide to successfully complete a particular exercise. You can use as much or as little help as you need per exercise. Moreover, because complete solutions are also provided, you can skip a few exercises and still be able to complete future exercises requiring the skipped ones. Each exercise has a list of any prerequisite exercises, a list of skeleton code for you to start with, links to necessary API pages, and a text description of the exercise goal. In addition, there is help for each task and a solutions page with links to files that comprise a solution to the exercise. Exercise 1. How to set up a JavaMail environment In this exercise you will install Sun's JavaMail reference implementation. After installing, you will be introduced to the demonstration programs that come with the reference implementation. Task 1: Download the latest version of the JavaMail API implementation from Sun. Task 2: Download the latest version of the JavaBeans Activation Framework from Sun. Task 3: Unzip the downloaded packages. You get a ZIP file for all platforms for both packages. Help for task 3: You can use the jar tool to unzip the packages. Task 4: Add the mail.jar file from the JavaMail 1.2 download and the activation.jar file from the JavaBeans Activation Framework download to your CLASSPATH. Help for task 4: Copy the files to your extension library directory. For Microsoft Windows, using the default installation copy, the command might look like the following: cd \javamail-1.2 copy mail.jar \jdk1.3\jre\lib\ext cd \jaf-1.0.1 copy activation.jar \jdk1.3\jre\lib\ext 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 Fundamentals of the JavaMail API Page 22 Presented by developerWorks, your source for great tutorials 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, ...). Exercise 1. How to set up a JavaMail environment: Solution Upon successful completion, the JavaMail reference implementation will be in your CLASSPATH. Exercise 2. How to send your first message In the last exercise you sent a mail message using the demonstration program provided with the JavaMail implementation. In this exercise, you'll create the program yourself. For more help with exercises, see About the exercises on page 22 . Prerequisites: * Exercise 1. How to set up a JavaMail environment on page 22 Skeleton code: * MailExample.java 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. Fundamentals of the JavaMail API Page 23 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Help for task 2: props.put("mail.smtp.host", host); Task 3: Get a Session object based on the Properties. Help for task 3: Session session = Session.getDefaultInstance(props, null); Task 4: Create a MimeMessage from the session. Help for task 4: MimeMessage message = new MimeMessage(session); Task 5: Set the from field of the message. Help for task 5: message.setFrom(new InternetAddress(from)); Task 6: Set the to field of the message. Help for task 6: message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); Task 7: Set the subject of the message. Help for task 7: message.setSubject("Hello JavaMail"); Task 8: Set the content of the message. Help for task 8: message.setText("Welcome to JavaMail"); Task 9: Use a Transport to send the message. Help for task 9: Transport.send(message); Task 10: Compile and run the program, passing your SMTP server, from address, and to address on the command line. Fundamentals of the JavaMail API Page 24 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Help for task 10: java MailExample SMTP.Server from@address to@address Task 11: Check to make sure you received the message with your normal mail reader (Eudora, Outlook Express, pine, ...). Exercise 2. How to send your first message: Solution The following Java source file represents a solution to this exercise: * Solution/MailExample.java Exercise 3. How to check for mail In this exercise, create a program that displays the from address and subject for each message and prompts to display the message content. For more help with exercises, see About the exercises on page 22 . Prerequisites: * Exercise 1. How to set up a JavaMail environment on page 22 Skeleton Code * GetMessageExample.java 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. Fundamentals of the JavaMail API Page 25 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Help for task 4: store.connect(host, username, password); 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 6: Open the folder read-only. Help for task 6: folder.open(Folder.READ_ONLY); 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 Fundamentals of the JavaMail API Page 26 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Exercise 3. How to check for mail: Solution The following Java source file represents a solution to this exercise. * Solution/GetMessageExample.java Exercise 4. How to reply to mail In this exercise, create a program that creates a canned reply message and attaches the original message if it's plain text. For more help with exercises, see About the exercises on page 22 . Prerequisites: * Exercise 3. How to check for mail on page 25 Skeleton Code: * ReplyExample.java 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 Fundamentals of the JavaMail API Page 27 Presented by developerWorks, your source for great tutorials 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, ...). Exercise 4. How to reply to mail: Solution The following Java source file represents a solution to this exercise. * Solution/ReplyExample.java Exercise 5. How to send attachments In this exercise, create a program that sends a message with an attachment. For more help with exercises, see About the exercises on page 22 . Prerequisites: * Exercise 2. How to send your first message on page 23 Skeleton Code: * AttachExample.java 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); Fundamentals of the JavaMail API Page 28 Presented by developerWorks, your source for great tutorials 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, ...). Exercise 5. How to send attachments: Solution The following Java source file represents a solution to this exercise. * Solution/AttachExample.java Exercise 6. How to send HTML messages with images In this exercise, create a program that sends an HTML message with an image attachment where the image is displayed within the HTML message. Fundamentals of the JavaMail API Page 29 Presented by developerWorks, your source for great tutorials 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 Skeleton code: * logo.gif * HtmlImageExample.java 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 Presented by developerWorks, your source for great tutorials 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. Exercise 6. How to send HTML messages with images: Solution The following Java source files represent a solution to this exercise. * Solution/logo.gif * Solution/HtmlImageExample.java Fundamentals of the JavaMail API Page 31 Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Section 9. Wrapup In summary The JavaMail API is a Java package used for reading, composing, and sending e-mail messages and their attachments. It lets you build standards-based e-mail clients that employ various Internet mail protocols, including SMTP, POP, IMAP, and MIME, as well as related protocols such as NNTP, S/MIME, and others. The API divides naturally into two parts. The first focuses on sending, receiving, and managing messages independent of the protocol used, whereas the second focuses on specific use of the protocols. The purpose of this tutorial was to show how to use the first part of the API, without attempting to deal with protocol providers. The core JavaMail API consists of seven classes --Session, Message, Address, Authenticator, Transport, Store, and Folder --all of which are found in javax.mail, the top-level package for the JavaMail API. We used these classes to work through a number of common e-mail-related tasks, including sending messages, retrieving messages, deleting messages, authenticating, replying to messages, forwarding messages, managing attachments, processing HTML-based messages, and searching or filtering mail lists. Finally, we provided a number of step-by-step exercises to help illustrate the concepts presented. Hopefully, this will help you add e-mail functionality to your platform-independent Java applications. 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. Fundamentals of the JavaMail API Page 32 Presented by developerWorks, your source for great tutorials 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 ( jaz@zukowski.net ) 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. Fundamentals of the JavaMail API Page 33
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值