`
tcl1122
  • 浏览: 28759 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

JavaMail实现具体的邮件发送功能代码示例(三)

阅读更多
作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)
原文:http://www.matrix.org.cn/resource/article/44/44101_JavaMail.html

五、使用JavaMail API
在明确了JavaMail API的核心部分如何工作后,本人将带领大家学习一些使用Java Mail API任务案例。
1.发送邮件
在获得了Session后,建立并填入邮件信息,然后发送它到邮件服务器。这便是使用Java Mail API发送邮件的过程,在发送邮件之前,我们需要设置SMTP服务器:通过设置Properties的mail.smtp.host属性。

String host = ...;String from = ...;String to = ...;// Get system propertiesProperties props = System.getProperties();// Setup mail serverprops.put("mail.smtp.host", host);// Get sessionSession session = Session.getDefaultInstance(props, null);// Define messageMimeMessage 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 messageTransport.send(message);
由于建立邮件信息和发送邮件的过程中可能会抛出异常,所以我们需要将上面的代码放入到try-catch结构块中。

2.接收邮件
为了在读取邮件,我们获得了session,并且连接到了邮箱的相应store,打开相应的Folder,然后得到我们想要的邮件,当然别忘记了在结束时关闭连接。

String host = ...;String username = ...;String password = ...;// Create empty propertiesProperties props = new Properties();// Get sessionSession session = Session.getDefaultInstance(props, null);// Get the storeStore store = session.getStore("pop3");store.connect(host, username, password);// Get folderFolder folder = store.getFolder("INBOX");folder.open(Folder.READ_ONLY);// Get directoryMessage 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]将抛出异常。

下面的代码片断有效的说明了如何读取邮件内容,在显示每个邮件发信人和主题后,将出现用户提示从而得到用户是否读取该邮件的确认,如果输入YES的话,我们可用Message.writeTo(java.io.OutputStream os)方法将邮件内容输出到控制台上,关于Message.writeTo()的具体用法请看JavaMail API。

BufferedReader reader = new BufferedReader (  new InputStreamReader(System.in));// Get directoryMessage 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;  }}

3.删除邮件和标志
设置与message相关的Flags是删除邮件的常用方法。这些Flags表示了一些系统定义和用户定义的不同状态。在Flags类的内部类Flag中预定义了一些标志:
Flags.Flag.ANSWERED
Flags.Flag.DELETED
Flags.Flag.DRAFT
Flags.Flag.FLAGGED
Flags.Flag.RECENT
Flags.Flag.SEEN
Flags.Flag.USER
但需要在使用时注意的:标志存在并非意味着这个标志被所有的邮件服务器所支持。例如,对于删除邮件的操作,POP协议不支持上面的任何一个。所以要确定哪些标志是被支持的——通过访问一个已经打开的Folder对象的getPermanetFlags()方法,它将返回当前被支持的Flags类对象。
删除邮件时,我们可以设置邮件的DELETED标志:

message.setFlag(Flags.Flag.DELETED, true);
但是首先要采用READ_WRITE的方式打开Folder:

folder.open(Folder.READ_WRITE);
在对邮件进行删除操作后关闭Folder时,需要传递一个true作为对删除邮件的擦除确认。

folder.close(true);
Folder类中另一种用于删除邮件的方法expunge()也同样可删除邮件,但是它并不为sun提供的POP3实现支持,而其它第三方提供的POP3实现支持或者并不支持这种方法。
另外,介绍一种检查某个标志是否被设置的方法:Message.isSet(Flags.Flag flag)方法,其中参数为被检查的标志。

4.邮件认证
我们在前面已经学会了如何使用Authenticator类来代替直接使用用户名和密码这两字符串作为Session.getDefaultInstance()或者Session.getInstance()方法的参数。在前面的小试牛刀后,现在我们将了解到全面认识一下邮件认证。
我们在此取代了直接使用邮件服务器主机名、用户名、密码这三个字符串作为连接到POP3 Store的方式,使用存储了邮件服务器主机名信息的属性文件,并在获得Session时传入自定义的Authenticator实例:

// Setup propertiesProperties props = System.getProperties();props.put("mail.pop3.host", host);// Setup authentication, get sessionAuthenticator auth = new PopupAuthenticator();Session session = Session.getDefaultInstance(props, auth);// Get the storeStore store = session.getStore("pop3");store.connect();

PopupAuthenticator类继承了抽象类Authenticator,并且通过重载Authenticator类的getPasswordAuthentication()方法返回PasswordAuthentication类对象。而getPasswordAuthentication()方法的参数param是以逗号分割的用户名、密码组成的字符串。

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);  }}

5.回复邮件
回复邮件的方法很简单:使用Message类的reply()方法,通过配置回复邮件的收件人地址和主题(如果没有提供主题的话,系统将默认将“Re:”作为邮件的主体),这里不需要设置任何的邮件内容,只要复制发信人或者reply-to到新的收件人。而reply()方法中的boolean参数表示是否将邮件回复给发送者(参数值为false),或是恢复给所有人(参数值为true)。
补充一下,reply-to地址需要在发信时使用setReplyTo()方法设置。

MimeMessage reply = (MimeMessage)message.reply(false);reply.setFrom(new InternetAddress("president@whitehouse.gov"));reply.setText("Thanks");Transport.send(reply);

6.转发邮件
转发邮件的过程不如前面的回复邮件那样简单,它将建立一个转发邮件,这并非一个方法就能做到。
每个邮件是由多个部分组成,每个部分称为一个邮件体部分,是一个BodyPart类对象,对于MIME类型邮件来讲就是MimeBodyPart类对象。这些邮件体包含在成为Multipart的容器中对于MIME类型邮件来讲就是MimeMultiPart类对象。在转发邮件时,我们建立一个文字邮件体部分和一个被转发的文字邮件体部分,然后将这两个邮件体放到一个Multipart中。说明一下,复制一个邮件内容到另一个邮件的方法是仅复制它的DataHandler(数据处理者)即可。这是由JavaBeans Activation Framework定义的一个类,它提供了对邮件内容的操作命令的访问、管理了邮件内容操作,是不同的数据源和数据格式之间的一致性接口。

// Create the message to forwardMessage forward = new MimeMessage(session);// Fill in headerforward.setSubject("Fwd: " + message.getSubject());forward.setFrom(new InternetAddress(from));forward.addRecipient(Message.RecipientType.TO,   new InternetAddress(to));// Create your new message partBodyPart messageBodyPart = new MimeBodyPart();messageBodyPart.setText(  "Here you go with the original message:\n\n");// Create a multi-part to combine the partsMultipart multipart = new MimeMultipart();multipart.addBodyPart(messageBodyPart);// Create and fill part for the forwarded contentmessageBodyPart = new MimeBodyPart();messageBodyPart.setDataHandler(message.getDataHandler());// Add part to multi partmultipart.addBodyPart(messageBodyPart);// Associate multi-part with messageforward.setContent(multipart);// Send messageTransport.send(forward);

7.使用附件
附件作为与邮件相关的资源经常以文本、表格、图片等格式出现,如流行的邮件客户端一样,我们可以用JavaMail API从邮件中获取附件或是发送带有附件的邮件。

A.发送带有附件的邮件
发送带有附件的邮件的过程有些类似转发邮件,我们需要建立一个完整邮件的各个邮件体部分,在第一个部分(即我们的邮件内容文字)后,增加一个具有DataHandler的附件而不是在转发邮件时那样复制第一个部分的DataHandler。

如果我们将文件作为附件发送,那么要建立FileDataSource类型的对象作为附件数据源;如果从URL读取数据作为附件发送,那么将要建立URLDataSource类型的对象作为附件数据源。

然后将这个数据源(FileDataSource或是URLDataSource)对象作为DataHandler类构造方法的参数传入,从而建立一个DataHandler对象作为数据源的DataHandler。

接着将这个DataHandler设置为邮件体部分的DataHandler。这样就完成了邮件体与附件之间的关联工作,下面的工作就是BodyPart的setFileName()方法设置附件名为原文件名。

最后将两个邮件体放入到Multipart中,设置邮件内容为这个容器Multipart,发送邮件。

// Define messageMessage 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 messagemessageBodyPart.setText("Pardon Ideas");Multipart multipart = new MimeMultipart();multipart.addBodyPart(messageBodyPart);// Part two is attachmentmessageBodyPart = new MimeBodyPart();DataSource source = new FileDataSource(filename);messageBodyPart.setDataHandler(new DataHandler(source));messageBodyPart.setFileName(filename);multipart.addBodyPart(messageBodyPart);// Put parts in messagemessage.setContent(multipart);// Send the messageTransport.send(message);
如果我们使用servlet实现发送带有附件的邮件,则必须上传附件给servlet,这时需要注意提交页面form中对编码类型的设置应为multipart/form-data。

<FORM ENCTYPE="multipart/form-data"     method=post action="/myservlet">   <INPUT TYPE="file" NAME="thefile">  <INPUT TYPE="submit" VALUE="Upload"></FORM>

B.读取邮件中的附件
读取邮件中的附件的过程要比发送它的过程复杂一点。因为带有附件的邮件是多部分组成的,我们必须处理每一个部分获得邮件的内容和附件。
但是如何辨别邮件信息内容和附件呢?Sun在Part类(BodyPart类实现的接口类)中提供了getDisposition()方法让开发者获得邮件体部分的部署类型,当该部分是附件时,其返回之将是Part.ATTACHMENT。但附件也可以没有部署类型的方式存在或者部署类型为Part.INLINE,无论部署类型为Part.ATTACHMENT还是Part.INLINE,我们都能把该邮件体部分导出保存。

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);}
以上是邮件体部分被正确设置的简单例子,如果邮件体部分的部署类型为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, ...  }...}

8.处理HTML邮件
前面的例子中发送的邮件都是以文本为内容的(除了附件),下面将介绍如何接收和发送基于HTML的邮件。
A.发送HTML邮件
假如我们需要发送一个HTML文件作为邮件内容,并使邮件客户端在读取邮件时获取相关的图片或者文字的话,只要设置邮件内容为html代码,并设置内容类型为text/html即可:

String htmlText = "<H1>Hello</H1>" +   "<img src=\"/pic/2006/1/5/1549001.gif\">";message.setContent(htmlText, "text/html"));
请注意:这里的图片并不是在邮件中内嵌的,而是在URL中定义的。邮件接收者只有在线时才能看到。
在接收邮件时,如果我们使用JavaMail API接收邮件的话是无法实现以HTML方式显示邮件内容的。因为JavaMail API邮件内容视为二进制流。所以要显示HTML内容的邮件,我们必须使用JEditorPane或者第三方HTML展现组件。

以下代码显示了如何使用JEditorPane显示邮件内容:

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();}

B.在邮件中包含图片
如果我们在邮件中使用HTML作为内容,那么最好将HTML中使用的图片作为邮件的一部分,这样无论是否在线都会正确的显示HTML中的图片。处理方法就是将HTML中用到的图片作为邮件附件并使用特殊的cid URL作为图片的引用,这个cid就是对图片附件的Content-ID头的引用。
处理内嵌图片就像向邮件中添加附件一样,不同之处在于我们必须通过设置图片附件所在的邮件体部分的header中Content-ID为一个随机字符串,并在HTML中img的src标记中设置为该字符串。这样就完成了图片附件与HTML的关联。

String file = ...;// Create the messageMessage message = new MimeMessage(session);// Fill its headersmessage.setSubject("Embedded Image");message.setFrom(new InternetAddress(from));message.addRecipient(Message.RecipientType.TO,   new InternetAddress(to));// Create your new message partBodyPart 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 partsMimeMultipart multipart = new MimeMultipart("related");multipart.addBodyPart(messageBodyPart);// Create part for the imagemessageBodyPart = new MimeBodyPart();// Fetch the image and associate to partDataSource fds = new FileDataSource(file);messageBodyPart.setDataHandler(new DataHandler(fds));messageBodyPart.setHeader("Content-ID","<memememe>");// Add part to multi-partmultipart.addBodyPart(messageBodyPart);// Associate multi-part with messagemessage.setContent(multipart);

9.在邮件中搜索短语
JavaMail API提供了过滤器机制,它被用来建立搜索短语。这个短语由javax.mail.search包中的SearchTerm抽象类来定义,在定义后我们便可以使用Folder的Search()方法在Folder中查找邮件:

SearchTerm st = ...;Message[] msgs = folder.search(st);
下面有22个不同的类(继承了SearchTerm类)供我们使用:
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.)
使用这些类定义的断语集合,我们可以构造一个逻辑表达式,并在Folder中进行搜索。下面是一个实例:在Folder中搜索邮件主题含有“ADV”字符串或者发信人地址为friend@public.com的邮件。

SearchTerm st =   new OrTerm(    new SubjectTerm("ADV:"),     new FromStringTerm("friend@public.com"));Message[] msgs = folder.search(st);

六、参考资源
JavaMail API Home
Sun’s JavaMail API基础
JavaBeans Activation Framework Home
javamail-interest mailing list
Sun's JavaMail FAQ
jGuru's JavaMail FAQ
Third Party Products List

七、代码下载
http://java.sun.com/developer/onlineTraining/JavaMail/exercises.html
分享到:
评论

相关推荐

    基于javamail的发送邮件示例文档

    基于javamail的发送邮件示例文档!包含有基于javamail的发送端java源代码!

    基于javamail接收邮件源代码

    基于javamail的接收邮件示例!!!可以作为参考!!!

    JavaMail(1)——使用SMTP协议发送简单邮件

    介绍了使用javamail发送电子邮件时所需要使用的类,还有代码示例

    Java使用JavaMail API发送和接收邮件的代码示例

    JavaMail是Oracle甲骨文开发的Java邮件类API,支持多种邮件协议,这里我们就来看一下Java使用JavaMail API发送和接收邮件的代码示例

    JavaMail邮件发送机制详解

    主要介绍了JavaMail邮件发送机制详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    JavaMail使用实例

    包含javaMail所需资源文件、邮件发送服务配置以及代码示例

    Java 通过代码发送邮件示例源码

    Java 通过代码发送邮件示例源码

    Spring邮件发送源码

    Spring 封装的JavaMail,使邮件发送变的相当简单,我通过Spring的邮件发送实现了发纯文本形的内容,HTMl,带附件,带图片等示例代码,并自行测试过.希望对初学者有帮助

    JavaMail写的示例程序

    用JavaMail写的示例程序,已经打包为jar 使用前在jar同目录下建立三个文本文件 addr.txt这个是收信人的地址,可以无限多,建议不超过50,否则面临smtp退信,格式 :一行一个地址,后面不要加空行! login.txt这个是...

    JSP网络编程从基础到实践的实例代码

    JSP网络编程从基础到实践的实例代码 《JSP网络编程从基础到实践》光盘说明 光盘的实例代码目录中包含了前10章的... 实例67 发送文本格式的邮件 实例68 发送 HTML邮件 实例69 发送带有附件的邮件 实例70 接收EMAIL

    JSP网络编程从基础到实践 实例代码

    光盘的实例代码目录中包含了前10章的所有实例的源代码,实例名称及其所处章节如下: 第1章 JSP技术概述 实例1 第一个JSP页面 第3章 Web开发基础 实例2 HTML与JavaScript交互示例 第4章 JSP语法 实例3 JSP程序的...

    J2EE 6.0 中文版API(exe文件) --声明不怎么好用

    发送纯文本消息的代码可以非常简单,如下所示: Properties props = new Properties(); props.put("mail.smtp.host", "my-mail-server"); props.put("mail.from", "me@example.com"); Session session = Session....

    Java网络编程(第三版)中文版.part11.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part06.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)高清中文版.part01.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part07.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part09.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part01.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part03.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

    Java网络编程(第三版)中文版.part02.rar

    本书有很多示例,包含了几千行可以实际工作的代码(所有代码都可以在线获得),实现了功能完整的网络客户端和服务器。无论是希望编写特殊用途的web服务器、安全的在线订单接收程序、简单的组播代理还是电子邮件...

Global site tag (gtag.js) - Google Analytics