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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介:

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

现在我们想要像 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,如需转载请自行联系原作者

相关文章
|
9天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
20 2
|
14天前
|
移动开发 开发者 HTML5
构建响应式Web界面:Flexbox与Grid的实战应用
【10月更文挑战第22天】随着互联网的普及,用户对Web界面的要求越来越高,不仅需要美观,还要具备良好的响应性和兼容性。为了满足这些需求,Web开发者需要掌握一些高级的布局技术。Flexbox和Grid是现代Web布局的两大法宝,它们分别由CSS3和HTML5引入,能够帮助开发者构建出更加灵活和易于维护的响应式Web界面。本文将深入探讨Flexbox和Grid的实战应用,并通过具体实例来展示它们在构建响应式Web界面中的强大能力。
32 3
|
3天前
|
JSON JavaScript 前端开发
蓝桥杯web组赛题解析和杯赛技巧
本文作者是一位自学前端两年半的大一学生,在第十五届蓝桥杯Web组比赛中获得省一和国三。文章详细解析了比赛题纲,涵盖HTML、CSS、JavaScript、Echarts和Vue等技术要点,并分享了备赛技巧和比赛经验。作者强调了多写代码和解题思路的重要性,同时提供了省赛和国赛的具体流程及注意事项。希望对参赛者有所帮助。
|
10天前
|
安全 前端开发 Java
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第26天】Web安全是现代软件开发的重要领域,本文深入探讨了XSS和CSRF两种常见攻击的原理及防御策略。针对XSS,介绍了输入验证与转义、使用CSP、WAF、HTTP-only Cookie和代码审查等方法。对于CSRF,提出了启用CSRF保护、设置CSRF Token、使用HTTPS、二次验证和用户教育等措施。通过这些策略,开发者可以构建更安全的Web应用。
41 4
|
9天前
|
安全 Go PHP
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第27天】本文深入解析了Web安全中的XSS和CSRF攻击防御策略。针对XSS,介绍了输入验证与净化、内容安全策略(CSP)和HTTP头部安全配置;针对CSRF,提出了使用CSRF令牌、验证HTTP请求头、限制同源策略和双重提交Cookie等方法,帮助开发者有效保护网站和用户数据安全。
34 2
|
10天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
16 3
|
10天前
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
26 2
|
10天前
|
测试技术 持续交付 PHP
PHP在Web开发中的应用与最佳实践###
【10月更文挑战第25天】 本文将深入探讨PHP在现代Web开发中的应用及其优势,并分享一些最佳实践来帮助开发者更有效地使用PHP。无论是初学者还是有经验的开发者,都能从中受益。 ###
28 1
|
11天前
|
负载均衡 监控 算法
论负载均衡技术在Web系统中的应用
【11月更文挑战第4天】在当今高并发的互联网环境中,负载均衡技术已经成为提升Web系统性能不可或缺的一环。通过有效地将请求分发到多个服务器上,负载均衡不仅能够提高系统的响应速度和处理能力,还能增强系统的可扩展性和稳定性。本文将结合我参与的一个实际软件项目,从项目概述、负载均衡算法原理以及实际应用三个方面,深入探讨负载均衡技术在Web系统中的应用。
41 2
|
14天前
|
JavaScript 前端开发 持续交付
构建现代Web应用:Vue.js与Node.js的完美结合
【10月更文挑战第22天】随着互联网技术的快速发展,Web应用已经成为了人们日常生活和工作的重要组成部分。前端技术和后端技术的不断创新,为Web应用的构建提供了更多可能。在本篇文章中,我们将探讨Vue.js和Node.js这两大热门技术如何完美结合,构建现代Web应用。
17 4

推荐镜像

更多
下一篇
无影云桌面