使用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" /> <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);
用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);
分享到:
相关推荐
### JavaMail API详解 #### 一、概述与背景 JavaMail API是用于处理电子邮件的一组标准接口,它为开发人员提供了强大的邮件收发能力。JavaMail API不仅支持常见的邮件协议如SMTP(简单邮件传输协议)、POP3(邮局...
JavaMail API 详解 JavaMail API 是一款功能强大且灵活的电子邮件处理API,允许开发者建立电子邮件客户端程序,例如Eudora、Foxmail、MS Outlook Express等。JavaMail API 的主要特点是它可以与各种电子邮件协议...
一、JavaMail API简介 JavaMail API是读取、撰写、发送电子信息的可选包。我们可用它来建立如Eudora、Foxmail、MS Outlook Express一般的邮件用户代理程序(Mail User Agent,简称MUA)。而不是像sendmail或者其它的...
提供的“javamail源码详解”和“开发手册”是理解JavaMail API的重要参考资料。通过阅读源码,可以深入了解其实现原理;开发手册则提供了详尽的API使用示例和教程,帮助开发者快速上手。 总结,JavaMail API是Java...
JavaMail API详解.chm文件可能是一个帮助文档,详细介绍了如何使用JavaMail API进行邮件操作。它可能涵盖了如何设置邮件服务器连接,创建邮件消息,添加附件,处理邮件头信息,以及使用MIME多部分消息等内容。这个...
JavaMail API是读取、撰写、发送电子信息的可选包。我们可用它来建立如Eudora、Foxmail、MS Outlook Express一般的邮件用户代理程序(Mail User Agent,简称MUA)。而不是像sendmail或者其它的邮件传输代理(Mail ...
在JavaMail API详解的资源中,我们可以深入理解这一强大的工具。 首先,JavaMail API简介部分会讲解JavaMail的基本概念,包括其设计目标、核心组件以及与SMTP(简单邮件传输协议)、POP3(邮局协议版本3)和IMAP...
《JavaMail API设计规范详解》 JavaMail API是Java平台上的一个强大工具,它为开发者提供了处理邮件系统交互的能力,包括发送、接收、管理邮件等。这篇博文将深入探讨JavaMail API的设计规范,帮助读者理解其核心...
JavaMail API 是一个Java编程语言中的库,用于处理电子邮件的创建、发送和接收。这个API提供了与邮件协议无关的抽象层,使得开发人员能够在不直接处理底层协议细节的情况下,实现邮件功能。JavaMail API 主要分为两...
JavaMail API是Java平台上用于处理电子邮件的一套强大的库,它为开发者提供了丰富的功能,使得在应用程序中发送和接收邮件变得简单。本文将深入探讨JavaMail API的各个方面,帮助你理解和掌握这一关键工具。 首先,...
### JavaMail API 知识点详解 #### 一、JavaMail API 概述 JavaMail API 是一个可选的标准扩展,用于读取、编写和发送电子邮件。它允许开发者创建类似于 Eudora、Pine 或 Microsoft Outlook 的邮件用户代理 (Mail ...
### JavaMail API中文文档知识点详解 #### 一、概述 JavaMail API是Java平台上的电子邮件解决方案,它提供了一组用于发送、接收、管理和处理电子邮件消息的API。JavaMail API主要包含以下几个核心概念:会话...
JavaMail API详解将深入探讨这些关键概念和技术。 1. **JavaMail API概述**: JavaMail API是Java平台上的标准邮件服务接口,由Java Community Process(JCP)定义为JSR 54。它允许开发者在应用程序中发送、接收和...
### JavaMail API基础知识详解 #### 一、教程提示 ##### 是否应该参加此教程? 如果你希望在平台独立的Java解决方案中集成邮件功能,那么JavaMail API将是你不可或缺的选择。该API提供了一个与协议无关的模型,...
### JavaMail邮件开发详解 #### 一、JavaMail API简介 JavaMail API 是一个用于读取、撰写和发送电子邮件的强大工具包。它主要用于构建邮件用户代理程序(Mail User Agent,简称 MUA),这类程序通常包括像 Eudora...