Properties props = new Properties();
// fill props with any information
Session session = Session.getDefaultInstance(props, null);
Properties props = new Properties();
// fill props with any information
Session session = Session.getInstance(props, null);
MimeMessage message = new MimeMessage(session);
message.setContent("Hello", "text/plain");
message.setText("Hello");
message.setSubject("First");
Address address = new InternetAddress("[email protected]");
Address address = new InternetAddress("[email protected]", "George Bush");
message.setFrom(address);
message.setReplyTo(address);
Address address[] = ...;
message.addFrom(address);
message.addRecipient(type, address)
Address toAddress = new InternetAddress("[email protected]");
Address ccAddress = new InternetAddress("[email protected]");
message.addRecipient(Message.RecipientType.TO, toAddress);
message.addRecipient(Message.RecipientType.CC, ccAddress);
Properties props = new Properties();
// fill props with any information
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
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();
session.setDebug(true)。
// Store store = session.getStore("imap");
Store store = session.getStore("pop3");
store.connect(host, username, password);
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message message[] = folder.getMessages();
System.out.println(((MimeMessage)message).getContent());
folder.close(aBoolean);
store.close();
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);
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; iSystem.out.println(i + ": " + message[i].getFrom()[0]
+ "/t" + message[i].getSubject());
}
// Close connection
folder.close(false);
store.close();
BufferedReader reader = new BufferedReader (
new InputStreamReader(System.in));
// Get directory
Message message[] = folder.getMessages();
for (int i=0, n=message.length; iSystem.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;
}
}
message.setFlag(Flags.Flag.DELETED, true);
folder.open(Folder.READ_WRITE);
folder.close(true);
// 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();
import javax.mail.*;
import java.util.*;
public class PopupAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication(String param) {
String username, password;
StringTokenizer st = new StringTokenizer(param, ",");
username = st.nextToken();
password = st.nextToken();
return new PasswordAuthentication(username, password);
}
}
MimeMessage reply = (MimeMessage)message.reply(false);
reply.setFrom(new InternetAddress("[email protected]"));
reply.setText("Thanks");
Transport.send(reply);
// 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);
// 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);
Multipart mp = (Multipart)message.getContent();
for (int i=0, n=multipart.getCount(); iPart part = multipart.getBodyPart(i));
String disposition = part.getDisposition();
if ((disposition != null) &&
((disposition.equals(Part.ATTACHMENT) ||
(disposition.equals(Part.INLINE))) {
saveFile(part.getFileName(), part.getInputStream());
}
}
// from saveFile()
File file = new File(filename);
for (int i=0; file.exists(); i++) {
file = new File(filename+i);
}
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, ...
}
...
}
String htmlText = "Hello
" +
"";
message.setContent(htmlText, "text/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();
}
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 = "Hello
" +
"";
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","");
// Add part to multi-part
multipart.addBodyPart(messageBodyPart);
// Associate multi-part with message
message.setContent(multipart);
SearchTerm st = ...;
Message[] msgs = folder.search(st);
SearchTerm st =
new OrTerm(
new SubjectTerm("ADV:"),
new FromStringTerm("[email protected]"));
Message[] msgs = folder.search(st);
JavaMail常见问题
一般问题
什么是 JavaMail API? 我如何获得 JavaMail API 的实现? 我如何发送反馈或评论? javax.activation 在哪里? JavaMail API 需要什么 JDK? 从哪里能找到我喜欢的操作系统的 JavaMail 版本? JavaMail API 可以在浏览器中工作吗? 我可以使用 JavaMail 来从 Web 邮件账户(比如 Yahoo 或 Hotmail)中阅读邮件吗? 什么是 IMAP? 什么是 SMTP? 什么是 MIME? 什么是 POP3? 对 MAPI、NNTP、Lotus Notes 和其他服务提供程序的支持怎样? 我如何在本地磁盘上存储邮件消息? 我可以从哪里找到有关 Sun 协议提供程序的文档? JavaMail API 实现是否完全免费?我可以把它与我的产品一起发行吗? 我可以获得 JavaMail API 实现的源代码吗? JavaMail 是否符合 Y2K? 我的问题不在这里,我应该在哪里查找?安装和配置
我如何安装 JavaMail API 实现? JavaMail 是否包括所有必要的邮件服务器? 从哪里可以获得必要的邮件服务器? 我应该使用什么主机名、用户名或密码? 我如何配置 JavaMail 通过代理服务器工作? 如何在 Windows NT 中设置 CLASSPATH? 当试图在 Linux 中运行程序时,得到了非常奇怪的错误消息,而且程序运行失败了。错误在哪里? 在运行于 SecurityManager 下面的应用程序中,我如何使用 JavaMail;我必须授予应用程序和 JavaMail 什么权限? 如何配置 Web 服务器来运行 JavaMail 演示 servlet? 当在 servlet 中使用 JavaMail 时,未找到任何的 JavaMail 类。我已经在服务器的 CLASSPATH 中添加了 mail.jar? 我的 servlet 可以找到 JavaMail 类,但 JavaMail 抱怨它不能找到针对“smtp”或“imap”的服务提供程序或地址类型“rfc822”。 在哪里可以找到 jws.jar?我已经安装了 Java Web Server 2.0,并试图运行 JavaMailServlet。README 文件指示我在 CLASSPATH 中添加 jws.jar。编程
从哪里可以学习有关 Internet 邮件的基础知识,它是我高效编写 JavaMail 程序需要知道的? 如何调试使用 JavaMail API 的应用程序? 如何发送带有附件的消息? 如何阅读带有附件的消息并保存附件? 什么是“中断支持”(disconnected support)? 如何使用 JavaMail API 来支持中断操作? 我如何使用 JavaMail API 来发送安全的电子邮件? writeTo() 方法生成了消息文件,但消息中的一些行既不是数据的规范 MIME 表示(即使用 CRLF 来结束行),又没有使用我的平台的规范行分隔符(例如 UNIX 上的“/n”)。如果我需要这些表示时,如何获得它们当中的任何一种表示? 我可以使用 JavaMail API 来实现邮件服务器吗? 我可以使用 JavaMail API 在我的邮件服务器上添加新的用户账户、删除用户账户或改变用户账户的密码吗? 为什么 MimeMessage 类没有实现 Serializable,这样我就可以将消息序列化到磁盘,并在以后读回它? 我如何编写服务提供程序? 我在登录 Microsoft Exchange 服务器时碰到了麻烦,我确信正在使用的用户名和密码是正确的,我做错了什么? 在发送二进制文件前,我如何编码它?当收到它时,我又如何解码它? 如果我不需要自己编码和解码附件,我应该何时使用 MimeUtility 方法? 尽管 JavaMail 完成了所有的编码和解码工作,但我仍需要手动控制一些主体部分的编码。 为什么 JavaMail 没有在非 ASCII 字符集中正确编码和解码文件名?阅读邮件——IMAP
我尝试在我的 IMAP 服务器上运行演示程序,但我得到了错误。 当我提取带有较大附件的消息时,IMAP 提供程序似乎丢失了数据。 IMAP 提供程序是否缓存检索的数据? 我想在文件夹间移动消息。我应该使用 appendMessages() 或 copyMessages() 吗? 有时检索大消息主体似乎是低效的。 当加载这种大二进制附件时,我得到了 OutOfMemory 错误。 当在主体部分 (bodypart) 上调用 getContent() 时,我为什么会得到 UnsupportedDataTypeException? 当在包含文本数据的主体部分 (bodypart) 上调用 getContent() 时,为什么会得到 UnsupportedEncodingException?发送邮件——SMTP
我如何回复消息? 我如何转发消息? 我如何发送 HTML 邮件? 我如何发送具有不同字体和颜色的格式化文本的邮件? 我如何发送具有纯文本和 HTML 文本的邮件,让每个邮件的阅读者可以选择适合它的格式? 我如何发送包含图像的 HTML 邮件? Transport 方法 send 和 sendMessage 之间有什么区别? 我需要验证到 SMTP 服务器,因此我调用了 trans.connect(host, user, password),然后调用 trans.send(msg) 发送消息,但它却不能工作。 我修改了一条消息,但标题却没有反映修改。 我正在使用 sendMessage() 方法发送消息,但在消息中的文本前后却出现奇怪的一些行,并且我的附件也在消息体中出现。 我为新消息的 Message-ID 标题设置了特定值。但当我发送这条消息时,却重写了那个标题。 当发送创建的新消息时,为什么会得到 UnsupportedDataTypeException? 当发送消息时,如何能够显式地设置 SMTP FROM: 属性? 我想重复发送消息,并且每次发送给一组不同的收件人。但调用 Transport.send(Message) 却导致每次都创建一个新的 Transport 会话。在本例中,这是一个次优办法,我如何来解决它? 当试图发送消息时,我得到了 “MessagingException: 501 HELO requires domain address”(MessagingException: 501 HELO 要求域地址)。 如果将消息发送到错误的地址,为什么我会获得 SendFailedException 或 TransportEvent,指出地址是错误的? 当消息不能被传送时,就会返回一个失败消息。我如何检测这些“回弹”消息? 当创建 InternetAddress 对象时,如果地址是非法的,为什么不会获得异常? 当试图发送消息时,我为什么会获得 javax.mail.SendFailedException: 550 Unable to relay for 我的地址? 当试图发送消息到(例如)Yahoo时,为什么我会获得一个错误,指出“连接被拒绝”? 当 发送邮件时,为什么会失败,并得到一个异常,异常中包括像“553 To send mail, first check your mail with a valid POP account”(553 为发送邮件,首先检查邮件具有合法的 POP 账户)这样的消息?POP3
我可以从哪里找到 POP3 的支持? 我想在 POP3 服务器上删除消息。我在这些消息上设置了 DELETED 标志。然后调用 expunge() 方法,但我得到了MethodNotSupportedException。当使用 Sun 的 POP3 提供程序时,我如何删除消息? 在从 Sun POP3 提供程序获得的消息中,我如何可以检索 POP3 UIDL? 对于 POP3,我如何知道哪里消息是新的? 当使用 POP3 时,为什么 hasNewMessages() 总是返回 false? 我创建了 MessageCountListener(如 monitor 程序中所展示的),但在我的 POP3 INBOX(收件箱)中,我从未得到通知。 当使用 POP3 时,为什么 getReceivedDate() 返回 null? 当使用 POP3 时,我得到了有关 SocketFetcher 类的抱怨。 当使用 POP3 时,我得到了有关 contentStream 字段的抱怨。 除了 POP3 服务器上的 INBOX(收件箱)外,您如何访问或创建文件夹?servlet 中的 JavaMail
我可以在 servlet 中使用 JavaMail 吗?applet 中的 JavaMail
我可以在 applet 中使用 JavaMail 吗? 在 applet 中,使用 JavaMail 的安全问题是什么? OK,可能我确实不想使用 applet,那我应该怎么做?
一般问题
问. 什么是 JavaMail API?
答:JavaMail API 是一组抽象的 API,它可用于构建邮件系统。API 提供了一个平台无关以及协议无关的框架,用于构建基于 Java 技术的电子邮件客户端应用程序。JavaMail API 提供了一些工具,用于阅读和发送电子邮件。服务提供程序实现了特定的一些协议。在 JavaMail API 软件包中,包括了几个服务提供程序;另外还有其他的一些服务提供程序可供使用。JavaMail API 是作为 Java 可选包实现的,它可用在 JDK 1.1.6 中,以后还可用在任何操作系统上。JavaMail API 也是 Java 2 Platform, Enterprise Edition (J2EE) 中的必需部分。
问. 我如何获得 JavaMail API 的实现?
答: Sun 提供了无版权的参考实现(二进制形式),开发人员可以使用和发行。参考实现包括核心的 JavaMail 包 和 IMAP、POP3 和 SMTP 服务提供程序。
问. 我如何发送反馈或评论?
答:发送电子邮件到 [email protected]。也可以考虑加入我们的低容量通告邮件列表 (low-volume announce mailing list) [email protected]。在我们的 Web 页 http://java.sun.com/products/javamail 中有关于如何加入的说明。
问. javax.activation 在哪里?
答: javax.activation
是 JavaBeans Activation Framework (JAF) 的一部分。JAF 是 JavaBeans "Glasgow" 规范的一部分(参见 http://java.sun.com/beans/glasgow/jaf.html)。JavaMail API 将 JAF 用于数据内容处理。
问. JavaMail API 需要什么 JDK?
答:JavaMail API 要求 JDK/JRE 1.1.x 或更高版本。我们已经在 Sun Microsystems JDK 1.1.6 至 JDK 1.1.7 上测试过这个实现,而这些 JDK 运行于 Solaris SPARC、Microsoft Windows 95/NT 和 RedHat Linux 4.2。我们也已经在 Java 2 SDK, Standard Edition (J2SE SDK) 版本 1.2、1.3 和 1.4 上做过测试,而这些 JDK 运行于 Solaris SPARC。JavaMail API 是 Java 的可选包,它们不是核心 J2SE 的一部分,但在 J2EE 中却包括了它。参见 http://java.sun.com/j2se,获取关于 JDK 1.1 和 J2SE 的进一步信息。
问. 从哪里能找到我喜欢的操作系统的 JavaMail 版本?
答:JavaMail 是完全用 Java 编写的,并将运行在特定的操作系统上,该操作系统支持所需版本的 JDK。对于不同的操作系统,不需要任何特殊的版本。
问. JavaMail API 可以在浏览器中工作吗?
答:在 Netscape 和 Internet Explorer 中,我们已经成功运行过 JavaMail 1.3。
问. 我可以使用 JavaMail 来从 Web 邮件账户(比如 Yahoo 或 Hotmail)中阅读邮件吗?
答:不 一定。许多基于 Web 的电子邮件服务只提供在浏览器中用 HTTP 进行访问。这些服务不能使用 JavaMail 来访问。如果服务也提供 POP3 或 IMAP 访问,可能不可以使用 JavaMail 来访问它。 联系你的 Web 电子邮件服务提供商,获取更详细的信息。也可参阅 JHTTPMail 项目,获得 JavaMail 的开放源代码提供程序,它提供了对 Hotmail 的访问。另一个有用的工具是 MrPostman——提供到 Hotmail 和 Yahoo! Mail 的 POP3 访问的代理服务器,这个工具可从如下站点获得:http://mrbook.org/mrpostman/。
问. 什么是 IMAP?
答:IMAP 是 Internet 消息访问协议 (Internet Message Access Protocol)。它是访问电子邮件消息的一种方法,而这些消息存储在(可能是共享的)邮件服务器上。换句话说,它允许“客户端”电子邮件程序访问远程 的消息存储,并且在访问时,就像它们就在本地一样。IMAP 由 RFC2060 定义。有关进一步信息,请参阅 http://www.imap.org/。
问. 什么是 SMTP?
答:SMTP 就是简单邮件传输协议 (Simple Mail Transfer Protocol)。它可用于不同邮件主机间 RFC822 样式的消息的传输,以及用于将新消息提交给一台主机,然后由它来传送该消息。SMTP 在广泛使用中(起源于 1982 年),并由 RFC821 定义。
问. 什么是 MIME?
答:MIME 和 RFC822 是一些标准,它们用于描述电子邮件消息,而这些消息是跨 Internet 进行发送的。javax.mail.internet 子包(它是 JavaMail API 的一部分)提供了这两个包的完整实现。MIME 是由下述 RFC 指定的:RFC2045、RFC2046 和 RFC2047。
问. 什么是 POP3?
答:POP3 是邮局协议 (Post Office Protocol V3)。POP3 是一个非常有限的协议,用于访问单个邮箱。它在功能上比 IMAP 差了许多。POP3 应用非常广泛,并由 RFC1939 定义。
问. 对 MAPI、NNTP、Lotus Notes 和其他服务提供程序的支持怎样?
答:目前我们还没有计划实现这些提供程序中的任何一个。不过,JavaMail API 的体系结构提供一些功能,可以容易地插入第三方服务提供程序。我们的希望是第三方将通过编写针对其他标准和专有协议的提供程序来包括 JavaMail API。 参阅 第三方产品 页面,获取这些提供程序的最新列表。
问. 我如何在本地磁盘上存储邮件消息?
答:“本地存储提供程序”可用于将邮件消息存储在本地磁盘中。JavaMail API 不包括这一提供程序,但有几个提供程序可从第三方获得,它们针对不同的本地存储格式,比如 MH 和 Mbox。参阅我们的 第三方产品 页面,获取这些提供程序的最新列表。
问. 我可以从哪里找到有关 Sun 协议提供程序的文档?
答:针对 IMAP、POP3 和 SMTP 的 Sun 协议提供程序支持许多特性,它们不是 JavaMail API 规范的一部分。在 JavaMail 1.3 下载包中包括了这些协议提供程序的文档,这些文档是以 javadoc 格式包括的,并位于 docs/javadocs
目录。针对每个协议提供程序包的包级文档描述了一些属性,这些属性由协议提供程序支持。此外,协议提供程序包括了一些类和方法,应用程序可以使用它们来利用特定于提供程序的特性。注意,这些属性、类和方法的使用使得程序不可移植;它可能只与 Sun 的 JavaMail API 实现一起工作。
问. JavaMail API 实现是否完全免费?我可以把它与我的产品一起发行吗?
答:可以。当前版本的 JavaMail API 实现是完全免费的,你可以在产品中包括它。这一版本也包括 IMAP、POP3 和 SMTP 提供程序。请一定阅读 许可,并保证理解它。JavaBeans Activation Framework 也是在类似的许可下免费使用的。
问. 我可以获得 JavaMail API 实现的源代码吗?
答:在 SCSL 许可下,现在 JavaMail API 参考实现源代码可作为 J2EE 的一部分获得。可从 这里 下载它。
问. JavaMail 是否符合 Y2K?
答:是的。 Sun 的 JavaMail 实现是符合 Option-3 Y2K 的。请参看 JavaMail 包中的 NOTES.txt 文件,获取进一步信息。
问. 我的问题不在这里,我应该在哪里查找?
答:除 JavaMail API 规范和 javadocs 外(可从 我们的 Web 主页 获得并且是包括在下载包中的),不要忘记查阅 JavaMail API 包中包括的 README.txt 和 NOTES.txt 文件,获取其他的重要信息。
javamail-interest mailing list 是另一个信息来源。参阅 我们的 Web 主页,获取有关如何订阅的说明以及指向文档的链接。
Java Developer Connection 维护 JavaMail 论坛,请参阅 http://forum.java.sun.com。注意,JavaMail 团队管理 javamail-interest 邮件列表,但不管理 JavaMail 论坛。
jGuru 也维护 JavaMail FAQ,可在如下地址找到它:http://www.jguru.com/faq/JavaMail。
安装和配置
问. 我如何安装 JavaMail API 实现?
答:解 压缩分发的 zip 文件,并编辑 CLASSPATH 环境变量以包含 mail.jar 文件,该文件包括在 JavaMail API 分发中。你也需要 JavaBeans Activation Framework(参见下面)的实现。参阅 README 文件(在分发中),获得其他细节和例子。
问. JavaMail 是否包括所有必要的邮件服务器?
答:不 是,JavaMail API 包不包括任何邮件服务器。为了使用 JavaMail API 包,你将需要访问 IMAP 或 POP3 邮件服务器(用于阅读邮件)和/或 SMTP 邮件服务器(用于发送邮件)。这些邮件服务器通常由 Internet 服务提供商提供,或者作为组织网络基础结构的一部分。如果你不必访问这样的邮件服务器,请往下看。
问. 从哪里可以获得必要的邮件服务器?
答:Sun Java System Messaging Server 可用于 Solaris 和 Windows 平台。华盛顿大学的 IMAP 服务器支持多种平台 (UNIX、32 位 Windows 等)。可从如下地址获取源代码:ftp://ftp.cac.washington.edu/imap/imap.tar.Z。其他的许多供应商提供了支持 Internet 标准的邮件服务器。可以从 IMAP Connection 和 Internet Mail Consortium 获得更多信息。
问. 我应该使用什么主机名、用户名或密码?
答:我们不提供邮件服务器让你使用。你必须使用自己的邮件服务器,或者使用 Internet 服务提供商或你所工作的公司提供的邮件服务器。网络管理员可能给你一些必要的信息用于配置 JavaMail,以便同邮件服务器一起工作。
问. 我如何配置 JavaMail 通过代理服务器工作?
答:大 多数代理服务器只支持 HTTP 协议。JavaMail 没有使用 HTTP 协议来阅读或发送邮件。使用代理服务器的一个主要原因是为了允许企业网络中的 HTTP 请求通过企业防火墙。防火墙通常会阻止对 Internet 的大多数访问,但允许来自代理服务器的请求通过。此外,企业网络内部的邮件服务器将为邮件执行类似的功能,通过 SMTP 接收消息,然后将它们转发到 Internet 上的最终目的地,以及接收传入的消息,然后将它们发送到合适的内部邮件服务器。
如果你的代理服务器支持 SOCKS V4 或 V5 协议 (http://www.socks.nec.com/aboutsocks.html, RFC1928),并允许匿名连接,可以告诉 Java 运行时把所有的 TCP socket 直接连接到 SOCKS 服务器。参阅 http://java.sun.com/j2se/1.4/docs/guide/net/properties.html,获取 socksProxyHost
和 socksProxyPort
属性的最新文档。这些是系统级属性,而不是 JavaMail 会话属性。当调用应用程序时,它们可以从命令行中设置,例如:java -DsocksProxyHost=myproxy ...
。这个工具可用于指出从 JavaMail 到 SOCKS 代理服务器进行 SMTP、IMAP 和 POP3 通信。注意,设置这些属性将告诉 所有 TCP socket 连接到 SOCKS 代理,在应用程序的其他方面上,这可能会带来负面影响。
假如没有这样的 SOCKS 服务器,如果想使用 JavaMail 来直接访问防火墙外部的邮件服务器,那将需要配置防火墙来允许这一访问。一个简单的 HTTP 代理 Web 服务器是足够的。
问. 如何在 Windows NT 中设置 CLASSPATH?
答:详细说明可从 这里 获得。
问. 当试图在 Linux 中运行程序时,得到了非常奇怪的错误消息,而且程序运行失败了。错误在哪里?
答:通常,错误消息看起来像下面这样:
Exception in thread "main"
java.lang.VerifyError:(Class:com/sun/mail/pop3/POP3Store,
method: finalize Signature :()V)
Illegal use of nonvirtual function call
问题是由于在 Linux 上,使用的 unzip 命令是有 bug 的版本,这样解压缩 JavaMail 下载包时,unzip 命令破坏了 mail.jar 文件。获取更新版本的 unzip 命令或使用 JDK 的 jar 命令来解压缩下载包。
问. 在运行于 SecurityManager 下面的应用程序中,我如何使用 JavaMail;我必须授予应用程序和 JavaMail 什么权限?
答:在 具有 SecurityManager 的 JDK 1.2(或更新版本)中,当使用 JavaMail 时,JavaMail 读取 mail.jar 文件中的配置文件有时会失败。在从 activation.jar 文件中读取配置文件时,JavaBeans Activation Framework 可能也有相同的问题。这些默认配置文件是作为“资源”文件存储的,并且存储在 jar 文件的 META-INF 目录中。
有许多调试技术可用于决定这是否是个问题。设置 Session 属性“mail.debug”为 true(或调用 session.setDebug(true)
), 将导致 JavaMail 在试图加载各个配置文件时打印调试消息。形如“DEBUG: can't load default providers file”(DEBUG: 不能加载默认提供程序文件) 的消息指出这个问题可能存在。同样,设置 System 属性“javax.activation.debug”为“true”(例如,通过使用 "java -Djavax.activation.debug=true ..." 来运行程序),将导致 JAF 在试图加载各个资源文件时打印调试消息。最后,通过设置 system 属性“java.security.debug” 为“access:failure”(例如,通过使用“java -Djava.security.debug=access:failure ...”来运行程序),JDK 可以产生有用的调试输出。
除了读取配置文件的必要权限外,应用程序(和 JavaMail)也将需要一定的权限才可以连接到它使用的邮件服务器。如果应用程序使用 System 属性来配置 JavaMail(例如,像许多 JavaMail 演示程序所做的那样,通过传递从 System.getProperties()
中返回的 Properties 对象到 Session 构造函数),它也将需要一定的权限才可以使用 System Properties 对象。另外,应用程序可以使用自己的 Properties 对象,以及确信设置 "mail.from" 属性 或 "mail.user" 和 "mail.host" 属性(参见 InternetAddress.getLocalAddress() 方法)。
在 JDK 1.2 SecurityManager 中,为了使应用程序能够使用 JavaMail,应用程序、JavaMail 和 JAF 将需要某些权限,比如下面的一些权限(一定要使用适当的值替换主机名和路径名);把这些权限添加到应用程序使用的安全策略文件中。
grant { |
问. 如何配置 Web 服务器来运行 JavaMail 演示 servlet?
答:针对以下 Web 服务器的指导说明可从这里获得:
问. 当在 servlet 中使用 JavaMail 时,未找到任何的 JavaMail 类。我已经在服务器的 CLASSPATH 中添加了 mail.jar?
答:当改变 CLASSPATH 时,通常有必要完全重启 Web 服务器。
问. 我的 servlet 可以找到 JavaMail 类,但 JavaMail 抱怨它不能找到针对“smtp”或“imap”的服务提供程序或地址类型“rfc822”。
答:通常这是因为 JavaMail 无法访问 mail.jar 中的配置文件,而这可能是由于安全权限问题造成的;参见 本条目,获取更多的细节。也保证你没有提取 mail.jar 内容;在服务器的 CLASSPATH 中,应该包括未更改的 mail.jar 文件。
问. 在哪里可以找到 jws.jar?我已经安装了 Java Web Server 2.0,并试图运行 JavaMailServlet。README 文件指示我在 CLASSPATH 中添加 jws.jar。
答:jws.jar 不再与 Java Web Server 一起发行(在以前版本中,它们是一起发行的),因此不需要在 CLASSPATH 中添加它。只要在 CLASSPATH 中添加 mail.jar 和 activation.jar,然后重启 Java Web Server。
编程
问. 从哪里可以学习有关 Internet 邮件的基础知识,它是我高效编写 JavaMail 程序需要知道的?
答:参见我们的 Web 页中提及的 参考图书 中的一本,获得有关 Internet 电子邮件、MIME、SMTP、IMAP 和 POP3 等的背景信息。
问. 如何调试使用 JavaMail API 的应用程序?
答:可通过在代码中调用 Session 对象上的 setDebug(true)
方法来打开调试模式。这将造成在控制台中打印调试消息,包括协议跟踪信息。如果您认为在 JavaMail 中发现了 bug,就将这个跟踪及以下信息发送给我们:重生成问题的测试用例、使用的平台、使用的 JDK 的版本和使用的邮件服务器 (IMAP, SMTP) 的名称和版本。
问. 如何发送带有附件的消息?
答:带有附件的消息采用 MIME 多部分消息来表示,其中第一部分是消息的主体,其他的部分是附件。有大量的例子,它们展示了如何在演示程序中构建这种消息,JavaMail 下载包包含了这些演示程序。
问. 如何阅读带有附件的消息并保存附件?
答:如前面描述,在 MIME 中,带有附件的消息是作为多部分消息表示的。在简单的例子中,Message
对象的 getContent
方法的结果将是一个 MimeMultipart
对象。多部分对象的第一个主体部分将是消息的主文本。其他的主体部分将是附件。msgshow.java
演示程序展示了如何在消息中遍历所有的多部分对象,并提取各个主体部分数据。getDisposition
方法将给你一个提示,指出主体部分是否应该内嵌显示,或者应该将其考虑成附件(但请注意,不是所有的发件人都提供这一信息)。
为了将主体部分中的数据保存到文件(比如),请使用 getInputStream
方法来访问附件内容,并将数据复制到 FileOutputStream
。
注意,也有一些更复杂的情形也要处理。例如,一些发件人把主体作为纯文本和 html 发送。通常,这将作为 multipart/alternative
内容(和 MimeMultipart
对象)出现在简单的文本主体部分的位置中。经过数字签名或加密的消息甚至会更复杂。处理所有的这些情形可能具有挑战性。请参考各种 MIME 规范和我们主页上列出的其他 参考资料。
问. 什么是“中断支持”(disconnected support)?
答:支 持中断操作的邮件客户端将允许用户访问远程消息存储(比如 IMAP)中消息,缓存这些消息中的一些消息的(部分)到本地,然后断开到服务器的连接。当处在断开连接状态中,邮件客户端可以访问已经缓存的消息,可能 也可以删除它们或将它们保存到其他文件夹。当邮件客户端下一次连接到远程消息存储时,本地所做变更会与远程存储同步。同样,中断支持可以允许客户端在断开 与服务器连接时“发送”消息,在到服务器的连接可用前,消息会进行排队。也请参阅 RFC1733。
问. 如何使用 JavaMail API 来支持中断操作?
答:JavaMail API 规范定义了一些接口,邮件客户端可以使用这些接口来支持中断操作。我们的 IMAP 提供程序实现了这些接口(UIDFolder 接口)。
问. 我如何使用 JavaMail API 来发送安全的电子邮件?
答:JavaMail API 目前不支持发送或接收安全电子邮件。JavaMail API 的体系结构使得可以在以后很容易地添加这一支持,我们可以添加支持,第三方也可以添加支持。有关当前电子邮件安全标准(S/MIME 和 PGP)的信息,可以从如下站点找到: http://www.imc.org/smime-pgpmime.html。 请浏览我们的 第三方产品 页,获取来自其他供应商的解决方案。
问. writeTo() 方法生成了消息文件,但消息中的一些行既不是数据的规范 MIME 表示(即使用 CRLF 来结束行),又没有使用我的平台的规范行分隔符(例如 UNIX 上的“/n”)。如果我需要这些表示时,如何获得它们当中的任何一种表示?
答:不管是哪种情形,你都将需要创建合适的 FilterOutputStream 对象来传递给 writeTo()
。FilterOutputStream 将需要接受特定的一些行,它们具有任何常见终止符,然后写出另外的一些特定行,它们只具有期望的行终止符。下面是这种过滤器的一些例子。NewlineOutputStream
转换到本地平台的行终止符,当将消息写到文件时,它是有用的。CRLFOutputStream
转换到 MIME 规范 CRLF 终止符,当需要规范 MIME 格式时(比如计算数字签名),它是有用的。
问. 我可以使用 JavaMail API 来实现邮件服务器吗?
答:JavaMail API 设计目的不是帮你实现邮件服务器。但是,对你来说,一些实用工具类,比如 MIME 消息解析类,可能是有用的。通常您会发现,JavaMail API 是在“简单”而不是在“强有力”方面出错。对于邮件客户端,那是合适的,但对于邮件服务器,结果可能是不同的。
问. 我可以使用 JavaMail API 在我的邮件服务器上添加新的用户账户、删除用户账户或改变用户账户的密码吗?
答:JavaMail API 不包括任何工具,用于添加、删除或修改用户账户。在这一方面是没有标准的,每个邮件服务器对它的处理是不同的。
问. 为什么 MimeMessage 类没有实现 Serializable,这样我就可以将消息序列化到磁盘,并在以后读回它?
答:JavaMail API 是在现有电子邮件系统上面设计的,并使用了现有的消息格式。对于这样的一些实现,使用 Java 序列化能力既不是必要的,也不是有用的,因此,不能将它作为 JavaMail API 的目标来考虑。
有关序列化 Message 的困难部分是保留某些指针,它们指向 Folder(文件夹)、Store(存储)和 Session(会话)。如果只想保存消息的内容,而不是对象本身,消息的 writeTo
方法将为你完成这一切。如果想根据序列化消息创建整个电子邮件系统,您应该能够编写 Message 等的子类,并在子类中实现 Serializable。
如果想序列化自己的引用了 MimeMessages的其他对象,那么你的对象的 writeObject
方法可以使用 MimeMessage 的 writeTo
方法,对象的 readObject
方法可以使用 MimeMessage 构造函数,该构造函数会得到 InputStream。在构造 MimeMessage 时,你的类将需要提供一个 Session。
问. 我如何编写服务提供程序?
答:请阅读服务提供程序文档,获取一些细节信息。通常,如果想编写 Store 提供程序,那就编写 javax.mail.Store
和 javax.mail.Folder
的子类,也可能要编写 javax.mail.Message
及其他一些类的子类。对于 Transport 提供程序,编写 javax.mail.Transport
的子类,也可能需要编写 javax.mail.Message
及其他的一些类的子类。然后在 javamail.providers
注册表中,添加描述提供程序的条目。如果对编写特别的服务提供程序感兴趣,并且它所针对的协议或邮件系统目前没有得到 JavaMail API 实现的支持,请通过 [email protected] 联系我们。
问. 我在登录 Microsoft Exchange 服务器时碰到了麻烦,我确信正在使用的用户名和密码是正确的,我做错了什么?
答:当登录 Exchange 时,需要使用比简单登录名更多的用户名。例如,如果你的电子邮件地址是“[email protected]”,Windows NT 登录名是“juser”,NT 域名是“dom”,而且 Exahange 邮箱名是“Joe User”,那么在使用 JavaMail 登录时,你将需要使用用户名 “dom/juser/J.User”。
问. 在发送二进制文件前,我如何编码它?当收到它时,我又如何解码它?
答:你不必这样的做!JavaMail 将自动决定合适的编码用于消息部分,然后才发送消息。而且当读取它们时,将自动解码消息部分。getInputStream
方法将返回解码数据。
问. 如果我不需要自己编码和解码附件,我应该何时使用 MimeUtility 方法?
答:在 JavaMail 没有自动处理的情况下,MimeUtility
方法是有用的。经常发生的这样的一种情形是文件名的编码。基本的 MIME spec(规范)不允许按某种方式编码标题参数值(比如文件名参数),该方式与(比如)编码 Subject(主题)标题相同。这限制了参数值,从而限制了文件名到 ASCII。但一些发件人却实际使用 MIME 文本编码来做非 ASCII 文件名的编码工作。想与这种非标准发件人互操作的应用程序可以使用 encodeText
方法来编码文件名,然后调用 MimeBodyPart
setFileName
方法,而且可以使用 decodeText
方法来解码返回的文件名。
问. 尽管 JavaMail 完成了所有的编码和解码工作,但我仍需要手动控制一些主体部分的编码。
答:在少数的场合需要控制编码,这里有几个方法来重写 JavaMail 的默认行为。下面是一个简单的方法。在创建整个消息后,调用 msg.saveChanges(),
然后使用像 mbp.setHeader("Content-Transfer-Encoding", "base64")
的语句来强制对指定主体部分做 base64 编码。
另一种办法是编写 MimeBodyPart
的子类,并重写 updateHeaders
方法,让它首先调用 super.updateHeaders()
,然后像上面那样设置 Content-Transfer-Encoding
标题。
问. 为什么 JavaMail 没有在非 ASCII 字符集中正确编码和解码文件名?
答:文件名是作为参数存储在 MIME 标题中的。形如 =?ISO-8859-15?B?5OTkLUluZm8ucGRm?=
的编码文件名不是 MIME spec(规范)的一部分。形如 =?A?B?C?=
的文件名是一个完全有效的文件名,而不是一个不正确编码的文件名。JavaMail 没有编码和解码文件名,因为这样做会违反 MIME 规范。
基本的 MIME 规范不允许编码参数。RFC 2231 定义了一种新的方式,使得可以在 MIME 标题中包括编码参数,包括文件名。它与下面的事实方式不兼容:许多应用程序非法编码文件名。支持 RFC 2231 将不允许 JavaMail 与这些现有的程序互操作。据我所知,很少现有的程序支持 RFC 2231。
如果你选择违反 MIME 规范是为了与其他也违反了 MIME的程序互操作,那么 JavaMail 会给您所有需要的工具来完成这件事。
编码文件名的解决方法是简单的:
mbp.setFileName(MimeUtility.encodeText(filename));
解码文件名的解决方法同样简单:
String filename = MimeUtility.decodeText(part.getFileName());
转自:http://hailan1987.blog.ccidnet.com/blog-htm-do-showone-uid-42621-type-blog-itemid-833373.html 本文仅限于发送文本。有附件的以后再出。 Copy codeimport java.util.*; |