JavaMail:在Web应用下完整接收、解析复杂邮件

简介:

其实,让我们自己来解析一封复杂的邮件是很不容易的,邮件里面格式、规范复杂得很。幸运的是,我们所用的浏览器一定内置了解析各种数据类型的数据处理模块,我们只需要在把数据流传输给浏览器之前明确地指定该数据流属于哪种数据类型即可,之后一切的解析操作由浏览器自动帮我们完成。

现在我们想要像 Outlook 客户端或者登录网页邮箱那样子接收、查看邮件,而这些邮件中可能包含附件、正文中可能内嵌图片、音频等等。好吧,我们来实现一下吧。

程序结构:

1、mailboxLogin.html 文件用于提供一个用户登录界面,由用户填写 POP3 服务器主机名、用户名和密码;

2、connectServer.jsp 文件用于获取登录界面中的登录信息,并连接到 POP3 服务器,还要读取显示出邮箱中的所有邮件列表,再提供一个查看邮件详细内容的超链接;

3、showMails.jsp 文件用于将一个 Web 页面分成两帧,目的在上一篇文章中讲过,就是分别指定不同的 MIME 消息头类型来让浏览器解析、显示出邮件头内容和邮件正文内容;

4、ShowHeader.java 文件是处理邮件头内容的 Servlet 程序;

5、ShowContent.java 文件时处理邮件正文内容的 Servlet 程序;

6、HandleAttachments.java 文件是当从 ShowHeader.java 程序处理邮件头内容时,若发现该邮件包含附件,则交给 HandleAttachments.java 这个 Servlet 程序进行处理,它能够在邮件头中给出附件的文件名、超链接,所以用户可以点击下载。这是上篇文章中所缺乏的,也是这个程序实现中的重点!

7、web.xml 文件用于根据前面的 Servlet 程序来部署、配置相关的映射信息。

好吧,讲了那么多让人不知所云的东西,来点截图啊、代码啊最让我兴奋的了,因为截图、所有代码我保证都是完整的(或许自己尝试一下可以弄出更多的截图),嘻嘻…

我们依然需要 Tomcat 这个服务器,关于 JSP 、Servlet 编程技术、部署配置映射信息等方面的内容就不能多讲了。这里先说明,我们要登录的邮箱时 testhao@126.com ,用户名为 testhao ,密码为 123456,里面的邮件跟上篇文章重点截图一样,不过我自己多发送了一封包含3封附件的邮件哦,如下:(更多精彩截图,请继续看下文)

WebMail01

WebMail02

WebMail04

程序代码: 

mailboxLogin.html

 
  1. <hmtl> 
  2.     <head> 
  3.         <title>邮箱登录页面</title> 
  4.     </head> 
  5.     <body> 
  6.         <form action="connectServer.jsp" method="post"> 
  7.             POP3服务器主机名:<input name="pop3Server" type="text"></br> 
  8.             邮箱用户名:<input name="user" type="text"></br> 
  9.             邮箱密码:<input name="pwd" type="password"></br> 
  10.             <input type="submit" value="登录"> 
  11.             <input type="reset" value="重置"></br> 
  12.         </form> 
  13.     </body> 
  14. </html> 

connectServer.jsp

 
  1. <%@ page  
  2.     import="javax.mail.*,java.util.Properties" 
  3.     contentType="text/html;charset=gbk" %>  
  4.  
  5. <%  
  6.     String pop3Server = request.getParameter("pop3Server");  
  7.     String user = request.getParameter("user");  
  8.     String pwd = request.getParameter("pwd");  
  9.  
  10.     // 创建一个有具体连接信息的Properties对象  
  11.     Properties props = new Properties();  
  12.     props.setProperty("mail.store.protocol""pop3");  
  13.     props.setProperty("mail.pop3.host", pop3Server);  
  14.       
  15.     // 使用Properties对象获得Session对象  
  16.     Session mailSession = Session.getDefaultInstance(props);  
  17.     //mailSession.setDebug(true);  
  18.  
  19.     Folder folder = null;  
  20.     try{          
  21.         // 利用Session对象获得Store对象,并连接pop3服务器  
  22.         Store store = mailSession.getStore();  
  23.         store.connect(pop3Server, user, pwd);  
  24.           
  25.         // 获得邮箱内的邮件夹Folder对象,以"读-写"打开  
  26.         folder = store.getFolder("inbox");  
  27.         folder.open(Folder.READ_WRITE);  
  28.  
  29.     }catch(Exception e){  
  30.         e.printStackTrace();  
  31.     }  
  32. //  Folder folder = POP3Connect.getFolder(pop3Server,user,pwd);  
  33.     session.setAttribute("folder", folder);  
  34.  
  35.     String from = null;  
  36.     String subject = null;  
  37.     Message [] messages = folder.getMessages();  
  38.     int messageCounts = messages.length;  
  39.     for(int i = 0; i < messageCounts; i++)  
  40.     {  
  41.         try{  
  42.             from = messages[i].getFrom()[0].toString();  
  43.             subject = messages[i].getSubject();  
  44.             out.println("<B>邮件 " + (i+1) + "</B>");  
  45. %>  
  46.         </br>发件人地址:<%=from %></br>  
  47.         邮件主题:<%=subject %></br>  
  48.         <a href="showMails.jsp?msgnum=<%=i+1 %>">  
  49.         >> 查看邮件!!!</a></br></br>  
  50. <%  
  51.         }catch(Exception e){  
  52.             e.printStackTrace();  
  53.         }  
  54.     }  
  55. %> 

showMails.jsp

 
  1. <frameset rows="25%,*"> 
  2.     <frame src="/JavaMail/ShowHeader?msgnum=  
  3.             <%=request.getParameter("msgnum")%>scrolling="yes"> 
  4.     <frame src="/JavaMail/ShowContent?msgnum=  
  5.             <%=request.getParameter("msgnum")%>scrolling="yes"> 
  6. </frameset> 

ShowHeader.java

 
  1. import java.io.*;  
  2. import java.text.DateFormat;  
  3. import javax.mail.internet.MimeUtility;  
  4. import javax.mail.*;  
  5. import javax.servlet.*;  
  6. import javax.servlet.http.*;  
  7.  
  8. // 解析邮件头消息,包括判断是否有附件  
  9. public class ShowHeader extends HttpServlet  
  10. {  
  11.     public void doGet(HttpServletRequest request,  
  12.         HttpServletResponse response) throws ServletException, IOException  
  13.     {  
  14.         response.setContentType("text/html;charset=gbk");  
  15.         PrintWriter out = response.getWriter();  
  16.         HttpSession session = request.getSession();  
  17.  
  18.         Folder folder = (Folder)session.getAttribute("folder");  
  19.         int msgnum = Integer.parseInt(request.getParameter("msgnum"));  
  20.  
  21.         try{                      
  22.             Message message = folder.getMessage(msgnum);  
  23.             String from = (message.getFrom()[0]).toString();  
  24.             String subject = message.getSubject();  
  25.             String sentDate = DateFormat.getInstance().format(message.getSentDate());  
  26.  
  27.             out.println("邮件主题:" + subject + "<br/>");  
  28.             out.println("发件人地址:" + from + "<br/>");  
  29.             out.println("发送日期:" + sentDate + "<br/>");  
  30.               
  31.             // 如果该邮件是组合型"multipart/*"则可能包含附件等  
  32.             if(message.isMimeType("multipart/*"))  
  33.             {  
  34.                 Multipart multipart = (Multipart)message.getContent();  
  35.                 int bodyCounts = multipart.getCount();  
  36.                 for(int i = 0; i < bodyCounts; i++)  
  37.                 {  
  38.                     BodyPart bodypart = multipart.getBodyPart(i);  
  39.                     // 如果该BodyPart对象包含附件,则应该解析出来  
  40.                     if(bodypart.getDisposition() != null)  
  41.                     {  
  42.                         String filename = bodypart.getFileName();  
  43.                         if(filename.startsWith("=?"))  
  44.                         {  
  45.                             // 把文件名编码成符合RFC822规范  
  46.                             filename = MimeUtility.decodeText(filename);  
  47.                         }  
  48.                         // 生成打开附件的超链接  
  49.                         out.print("<B>附件 " + (i+1) + ":</B>");  
  50.                         out.println("<a href=HandleAttachments?msgnum="   
  51.                             + msgnum + "&&bodynum=" + i + "&&filename=" 
  52.                             + filename + ">" + filename + "</a></br>");  
  53.                     }  
  54.                 }  
  55.             }  
  56.         }catch(Exception e){  
  57.             e.printStackTrace();  
  58.         }  
  59.     }  

ShowContent.java

 
  1. import java.io.*;  
  2. import javax.mail.*;  
  3. import javax.servlet.*;  
  4. import javax.servlet.http.*;  
  5.  
  6. // 处理邮件的正文部分  
  7. public class ShowContent extends HttpServlet  
  8. {  
  9.     public void doGet(HttpServletRequest request,  
  10.         HttpServletResponse response) throws ServletException, IOException  
  11.     {  
  12.         // 获取输出流、Session 会话对象、邮件夹 Folder 对象  
  13.         ServletOutputStream out = response.getOutputStream();  
  14.         HttpSession session = request.getSession();  
  15.         Folder folder = (Folder)session.getAttribute("folder");  
  16.         int msgnum = Integer.parseInt(request.getParameter("msgnum"));  
  17.  
  18.         try{  
  19.             Message message = folder.getMessage(msgnum);  
  20.             if(!message.isMimeType("multipart/mixed"))  
  21.             {  
  22.                 // 若邮件类型不是"mixed"则表明不包含附件,  
  23.                 // 并设置类型让浏览器直接输出正文  
  24.                 response.setContentType("message/rfc822");  
  25.                 message.writeTo(out);  
  26.             }else{  
  27.                 // 如果是"mixed"型,则遍历所有BodyPart对象,  
  28.                 // 把不包含附件的邮件正文打印出来。  
  29.                 // 这是为了不让该程序既输出正文又传输附件大量的数据  
  30.                 Multipart multipart = (Multipart)message.getContent();  
  31.                 int bodyCounts = multipart.getCount();  
  32.                 for(int i = 0; i < bodyCounts; i++)  
  33.                 {  
  34.                     BodyPart bodypart = multipart.getBodyPart(i);  
  35.                     // 不是"mixed"型且不包含附件  
  36.                     if(!bodypart.isMimeType("multipart/mixed")   
  37.                         && bodypart.getDisposition() == null)  
  38.                     {  
  39.                         response.setContentType("message/rfc822");  
  40.                         bodypart.writeTo(out);                        
  41.                     }  
  42.                 }  
  43.             }  
  44.         }catch(Exception e){  
  45.             e.printStackTrace();  
  46.         }  
  47.     }  

HandleAttachments.java

 
  1. import java.io.*;  
  2. import javax.mail.*;  
  3. import javax.servlet.*;  
  4. import javax.servlet.http.*;  
  5.  
  6. // 处理邮件中的附件  
  7. public class HandleAttachments extends HttpServlet  
  8. {  
  9.     public void doGet(HttpServletRequest request,  
  10.         HttpServletResponse response) throws ServletException, IOException  
  11.     {  
  12.         response.setContentType("text/html;charset=gbk");  
  13.         PrintWriter out = response.getWriter();  
  14.         HttpSession session = request.getSession();  
  15.  
  16.         int msgnum = Integer.parseInt(request.getParameter("msgnum"));  
  17.         int bodynum = Integer.parseInt(request.getParameter("bodynum"));          
  18.         Folder folder = (Folder)session.getAttribute("folder");  
  19.         String filename = request.getParameter("filename");  
  20.  
  21.         try{  
  22.             Message message = folder.getMessage(msgnum);  
  23.             // 将消息头类型设置为附件类型  
  24.             response.setHeader("Content-Disposition",   
  25.                 "attachment;filename=" + filename);  
  26.  
  27.             Multipart multipart = (Multipart)message.getContent();  
  28.             BodyPart bodypart = multipart.getBodyPart(bodynum);  
  29.  
  30.             InputStream input = bodypart.getInputStream();  
  31.             int temp = 0;  
  32.             while((temp = input.read()) != -1)  
  33.             {  
  34.                 out.write(temp);  
  35.             }  
  36.         }catch(Exception e){  
  37.             e.printStackTrace();  
  38.         }  
  39.     }  

web.xml

 
  1. <?xml version="1.0" encoding="gb2312"?> 
  2.  
  3. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
  6.     version="2.4"> 
  7.       
  8.     <servlet> 
  9.         <servlet-name>ShowHeader</servlet-name> 
  10.         <servlet-class>ShowHeader</servlet-class> 
  11.     </servlet>      
  12.     <servlet-mapping> 
  13.         <servlet-name>ShowHeader</servlet-name> 
  14.         <url-pattern>/ShowHeader</url-pattern> 
  15.     </servlet-mapping> 
  16.        
  17.     <servlet> 
  18.         <servlet-name>ShowContent</servlet-name> 
  19.         <servlet-class>ShowContent</servlet-class> 
  20.     </servlet>      
  21.     <servlet-mapping> 
  22.         <servlet-name>ShowContent</servlet-name> 
  23.         <url-pattern>/ShowContent</url-pattern> 
  24.     </servlet-mapping>      
  25.        
  26.     <servlet> 
  27.         <servlet-name>HandleAttachments</servlet-name> 
  28.         <servlet-class>HandleAttachments</servlet-class> 
  29.     </servlet>      
  30.     <servlet-mapping> 
  31.         <servlet-name>HandleAttachments</servlet-name> 
  32.         <url-pattern>/HandleAttachments</url-pattern> 
  33.     </servlet-mapping> 
  34.       
  35. </web-app> 

测试过程:(其实就是精彩的截图啦)

WebMail03

 

WebMail05

WebMail06

WebMail07

WebMail08

好了,精彩截图没了吗?不是的,我们还要与 126 邮箱中的解析、显示效果比对一下,如下:

WebMail09

又是这个问题:

为什么我们明明才上传了 3 个附件啊(见最上面的图),这里显示为 4 个了。我猜测的原因在前面的文章中也说过了,它把邮件正文中的图片也解析为附件了,不同的邮件服务器在解析发送、接收、解析邮件时都有自己的方式、策略,这个不理了。不过话说回来,我们自己写的程序好像更加合理一点哦,直接显示 3 个附件,真好!

小结:

1、在这个基于 Tomcat 的 Web 应用中,只用解析邮件中的附件是新的知识,其他的都讲过了;

2、关于程序代码结构、内容是否高效的问题,在这些文章中都没有太多注意,原因是比较注重实现想要的功能,这个不足要意识到并且逐步改过来;

3、关于 JavaMail 邮件开发的学习似乎就到此告一段落了,从最原始的用 Windows 下的 telnet 程序连接服务器手工一条一条命令地发送、接收邮件,到自己写了个 GUI 程序封装这些邮件发送命令以达到真正的纯文本邮件发送的功能,再到学习 JavaMail API 更轻松的创建邮件内容、邮件发送、邮件接收、运用 Tomcat 和浏览器实现邮件的解析…

噢,好像是学习完了。但是,编程学习要达到卖油翁的“无他, 唯手熟尔”绝对是一条漫长艰苦的道路,在此源于大家互相交流、共同学习、一起进步!加油!!!

其实,有时间的话我们也可以扩展上面的程序,综合前面所有文章中的内容,实现一个能够发送邮件,上传图片、附件,以及接收、解析、查看邮件的综合应用…



本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/357204,如需转载请自行联系原作者

相关文章
|
6天前
|
XML 存储 Java
11:Servlet中初始化参数的获取与应用-Java Web
11:Servlet中初始化参数的获取与应用-Java Web
20 3
|
1天前
|
供应链 搜索推荐 API
API在电子商务中的应用与优势:深入解析
API是电子商务成功的关键,它们不仅促进了技术创新,还提高了用户体验和运营效率。随着技术的不断进步,API将继续在电子商务领域发挥更加重要的作用。电子商务平台通过利用API,可以更加灵活地适应市场变化,提供更加丰富和个性化的购物体验,最终实现业务的增长和扩展。
|
6天前
|
设计模式 存储 前端开发
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
23 4
|
6天前
|
存储 前端开发 安全
13:会话跟踪技术Session的深度应用与实践-Java Web
13:会话跟踪技术Session的深度应用与实践-Java Web
21 3
|
6天前
|
存储 前端开发 搜索推荐
12:会话跟踪技术Cookie的深度应用与实践-Java Web
12:会话跟踪技术Cookie的深度应用与实践-Java Web
20 4
|
6天前
|
安全 前端开发 Java
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
20 3
|
7天前
|
缓存 移动开发 前端开发
【专栏:HTML与CSS前端技术趋势篇】HTML与CSS在PWA(Progressive Web Apps)中的应用
【4月更文挑战第30天】PWA(Progressive Web Apps)结合现代Web技术,提供接近原生应用的体验。HTML在PWA中构建页面结构和内容,响应式设计、语义化标签、Manifest文件和离线页面的创建都离不开HTML。CSS则用于定制主题样式、实现动画效果、响应式布局和管理字体图标。两者协同工作,保证PWA在不同设备和网络环境下的快速、可靠和一致性体验。随着前端技术进步,HTML与CSS在PWA中的应用将更广泛。
|
7天前
|
前端开发 JavaScript 搜索推荐
【专栏:HTML 与 CSS 前端技术趋势篇】HTML 与 CSS 在 Web 组件化中的应用
【4月更文挑战第30天】本文探讨了HTML和CSS在Web组件化中的应用及其在前端趋势中的重要性。组件化提高了代码复用、维护性和扩展性。HTML提供组件结构,语义化标签增进可读性,支持用户交互;CSS实现样式封装、布局控制和主题定制。案例展示了导航栏、卡片和模态框组件的创建。响应式设计、动态样式、CSS预处理器和Web组件标准等趋势影响HTML/CSS在组件化中的应用。面对兼容性、代码复杂度和性能优化挑战,需采取相应策略。未来,持续发掘HTML和CSS潜力,推动组件化开发创新,提升Web应用体验。
|
7天前
|
供应链 Java API
Java 8新特性解析及应用区块链技术在供应链管理中的应用与挑战
【4月更文挑战第30天】本文将深入探讨Java 8的新特性,包括Lambda表达式、Stream API和Optional类等。通过对这些新特性的详细解析和应用实例,帮助读者更好地理解和掌握Java 8的新技术。
|
7天前
|
缓存 前端开发 JavaScript
探索现代Web应用的性能优化策略移动应用开发的未来之路:跨平台与原生之争
【4月更文挑战第30天】随着互联网技术的迅猛发展,Web应用已成为信息交流和商业活动的重要平台。用户对Web应用的响应速度和稳定性有着极高的期望,这促使开发者不断寻求提升应用性能的有效途径。本文将深入探讨针对现代Web应用进行性能优化的关键策略,包括前端优化、后端优化以及数据库层面的调优技巧,旨在为开发者提供一套全面的优化工具箱,帮助他们构建更快速、更高效的Web应用。

推荐镜像

更多