JavaMail入门教程之解析邮件(5)

作者:汪先森 时间:2023-11-29 08:25:13 

上一篇JavaMail入门第四篇 接收邮件中,控制台打印出的内容,我们无法阅读,其实,让我们自己来解析一封复杂的邮件是很不容易的,邮件里面格式、规范复杂得很。不过,我们所用的浏览器内置了解析各种数据类型的数据处理模块,我们只需要在把数据流传输给浏览器之前明确地指定该数据流属于哪种数据类型即可,之后一切的解析操作由浏览器自动帮我们完成。下面这张图可以很好的说明解析邮件的步骤

JavaMail入门教程之解析邮件(5)

1、调用Message对象的getFrom、getSubject等方法,可以得到邮件的发件人和主题等信息,调用getContentType方法得到邮件的类型;

2、通过Message.getContentType方法的返回值判断邮件类型,并调用Message.getContent方法得到邮件内容。如果邮件类型为"text/plain"或者"text/html",表示邮件内容为纯文本,此时调用Message对象的getContent方法得到邮件内容,然后将返回对象的类型转换成String输出给显示软件即可。如果邮件类型为"multipart/*",表示邮件内容是一个复合类型,此时需将Message.getContent方法复合的对象转换成Multipart。

3、调用Multipart对象的getCount方法检测Multipart对象中封装了多少个BodyPart对象,并通过for循环逐一取出Multipart对象中的每个BodyPart对象进行处理。

4、在处理每个BodyPart对象时,首先调用BodyPart对象的getContentType方法得到它的MIME类型,然后根据MIME类型作出如下三种情况的处理:

当MIME类型为"text/*"时,表示BodyPart对象中保存的是纯文本数据,如上图中的"text/plain",此时第一BodyPart对象的getContent方法并将返回的对象转换成String输出给显示软件显示即可。

当MIME类型表示的是图片、声音或者是附件等二进制数据时,如上图中的"image/gif"时,此时应调用BodyPart对象的getDataHandler方法得到了封装了数据的DataHanlder对象,然后调用DataHandler对象的getInputStream方法获得与数据相关联的InputStream对象,通过这个InputStream对象中即可获得原始的二进制数据内容。

当MIME类型为"multipart/mixed"时,表示BodyPart对象中保存的是一个复合MIME消息,此时应调用BodyPart对象的getContent方法得到封装复合MIME消息的对象并将它转换成Multipart类型,接着重复第3和第4个步骤操作对Multipart对象进行递归调用。

下面来编写一个接收并解析带有附件的程序

POP3Help.java


package mail;

import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Session;
import javax.mail.Store;

public class POP3Help {
public static Folder getFolder(String host, String username, String password) {
 Properties prop = new Properties();
 prop.setProperty("mail.store.protocol", "pop3");
 prop.setProperty("mail.pop3.host", host);

Session mailSession = Session.getDefaultInstance(prop, null);
 mailSession.setDebug(false);

try {
  Store store = mailSession.getStore("pop3");
  store.connect(host, username, password);
  Folder folder = store.getFolder("inbox");
  folder.open(Folder.READ_WRITE);
  return folder;
 } catch (Exception e) {
  e.printStackTrace();
 }

return null;
}
}

该类用来连接和登录POP3服务器,并返回代表邮件夹的Folder对象

 index.html


<html>
<head>
<title>login.html</title>
</head>
<body>
<form action="login.jsp" method="post">
 主机名:<input name="host" type="text"><br/>
 用户名:<input name="username" type="text"><br/>
 密码:<input name="password" type="password"><br/>
 <input type="submit" value="提交">
 <input type="reset" value="重置">
</form>
</body>
</html>

登录页面,需要用户填写邮件服务器的主机名,用户名和密码

 login.jsp


<%@ page import="javax.mail.*,mail.*"
contentType="text/html;charset=GB2312" %>
<%
String host = request.getParameter("host");  
 String username = request.getParameter("username");
 String password = request.getParameter("password");
 String from = "";
 String subject = "";
 Folder folder = POP3Help.getFolder(host,username,password);
 session.setAttribute("folder",folder);
 Message [] messages = folder.getMessages();

for(int i=0;i<messages.length;i++)
 {
  try
  {
   from = messages[i].getFrom()[0].toString();
  subject = messages[i].getSubject();
  out.print(i + 1);
%>
  发件人地址:<%=from %> 邮件主题:<%=subject %>    
  <a href="displayMsg.jsp?msgnum=<%=i+1%>">查看邮件</a><br/>
<%
 }
  catch(Exception e){}
  }
%>

获取邮件夹中的所有邮件

 displayMsg.jsp


<frameset rows="25%,*">
<frame src="/mailDemo/DisplayHead?msgnum=<%=request.getParameter("msgnum")%>" scrolling="no">
<frame src="/mailDemo/DisplayContent?msgnum=<%=request.getParameter("msgnum")%>" scrolling="no">
</frameset>

用于展示邮件的信息

 DisplayHead.java


package mail;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.internet.MimeUtility;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class DisplayHead extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 response.setContentType("text/html;charset=gb2312");
 PrintWriter out = response.getWriter();
 HttpSession session = request.getSession();
 int msgnum = Integer.parseInt(request.getParameter("msgnum"));
 Folder folder = (Folder) session.getAttribute("folder");

try {
  Message msg = folder.getMessage(msgnum);
  String from = msg.getFrom()[0].toString();
  String subject = msg.getSubject();
  String sendDate = DateFormat.getInstance().format(msg.getSentDate());

out.println("邮件主题:" + subject + "<br/>");
  out.println("发件人:" + from + "<br/>");
  out.println("发送日期:" + sendDate + "<br/><br/>");

System.out.println("contentType:" + msg.getContentType());

// 如果该邮件是组合型"multipart/*"则可能包含附件等
  if (msg.isMimeType("multipart/*")) {
   Multipart mp = (Multipart) msg.getContent();

for (int i = 0; i < mp.getCount(); i++) {
    BodyPart bp = mp.getBodyPart(i);

// 如果该BodyPart对象包含附件,则应该解析出来
    if (bp.getDisposition() != null) {
     String filename = bp.getFileName();
     System.out.println("filename:" + filename);

if (filename.startsWith("=?")) {
      // 把文件名编码成符合RFC822规范
      filename = MimeUtility.decodeText(filename);
     }

// 生成打开附件的超链接
     out.print("附件:");
     out.print("<a href=HandleAttach?msgnum=" + msgnum + "&&bodynum=" + i + "&&filename=" + filename
       + ">" + filename + "</a><br/>");
    }
   }
  }
 } catch (Exception e) {
  e.printStackTrace();
 }
}
}

用于显示邮件头内容

 DisplayContent.java


package mail;

import java.io.IOException;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class DisplayContent extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 ServletOutputStream sos = response.getOutputStream();
 HttpSession session = request.getSession();
 int msgnum = Integer.parseInt(request.getParameter("msgnum"));
 Folder folder = (Folder) session.getAttribute("folder");

try {
  Message msg = folder.getMessage(msgnum);
  // 邮件类型不是mixed时,表示邮件中不包含附件,直接输出邮件内容
  if (!msg.isMimeType("multipart/mixed")) {
   response.setContentType("message/rfc822");
   msg.writeTo(sos);
  } else {
   // 查找并输出邮件中的邮件正文
   Multipart mp = (Multipart) msg.getContent();
   int bodynum = mp.getCount();
   for (int i = 0; i < bodynum; i++) {
    BodyPart bp = mp.getBodyPart(i);
    /*
     * MIME消息头中不包含disposition字段, 并且MIME消息类型不为mixed时,
     * 表示当前获得的MIME消息为邮件正文
     */
    if (!bp.isMimeType("multipart/mixed") && bp.getDisposition() == null) {
     response.setContentType("message/rfc822");
     bp.writeTo(sos);
    }
   }
  }
 } catch (Exception e) {
  e.printStackTrace();
 }
}
}

用于显示邮件正文

 HandleAttact.java


package mail;

import java.io.IOException;
import java.io.InputStream;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class HandleAttach extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 response.setContentType("text/html");
 HttpSession session = request.getSession();
 ServletOutputStream out = response.getOutputStream();

int msgnum = Integer.parseInt(request.getParameter("msgnum"));
 int bodynum = Integer.parseInt(request.getParameter("bodynum"));
 String filename = request.getParameter("filename");
 Folder folder = (Folder) session.getAttribute("folder");

try {
  Message msg = folder.getMessage(msgnum);

// 将消息头类型设置为附件类型
  response.setHeader("Content-Disposition", "attachment;filename=" + filename);

Multipart multi = (Multipart) msg.getContent();
  BodyPart bodyPart = multi.getBodyPart(bodynum);

InputStream is = bodyPart.getInputStream();
  int c = 0;
  while ((c = is.read()) != -1) {
   out.write(c);
  }
 } catch (Exception e) {
  e.printStackTrace();
 }
}
}

用于处理附件

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
 <display-name>mailDemo</display-name>
 <welcome-file-list>
 <welcome-file>index.html</welcome-file>
 <welcome-file>index.htm</welcome-file>
 <welcome-file>index.jsp</welcome-file>
 <welcome-file>default.html</welcome-file>
 <welcome-file>default.htm</welcome-file>
 <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>

<servlet>
 <servlet-name>DisplayHead</servlet-name>
 <servlet-class>mail.DisplayHead</servlet-class>
</servlet>  
<servlet-mapping>
 <servlet-name>DisplayHead</servlet-name>
 <url-pattern>/DisplayHead</url-pattern>
</servlet-mapping>

<servlet>
 <servlet-name>DisplayContent</servlet-name>
 <servlet-class>mail.DisplayContent</servlet-class>
</servlet>  
<servlet-mapping>
 <servlet-name>DisplayContent</servlet-name>
 <url-pattern>/DisplayContent</url-pattern>
</servlet-mapping>  

<servlet>
 <servlet-name>HandleAttach</servlet-name>
 <servlet-class>mail.HandleAttach</servlet-class>
</servlet>  
<servlet-mapping>
 <servlet-name>HandleAttach</servlet-name>
 <url-pattern>/HandleAttach</url-pattern>
</servlet-mapping>
</web-app>

首先启动tomcat服务器,然后在浏览器中输入http://localhost:8080/mailDemo/index.html

JavaMail入门教程之解析邮件(5)

输入用户名跟密码(这里需要填写授权码,什么是授权码,它又是如何设置?)

JavaMail入门教程之解析邮件(5)

列出了邮件夹中所有的邮件

点击查看邮件链接

JavaMail入门教程之解析邮件(5)

点击附件后面的文件名称即可下载对应附件。

标签:JavaMail,解析邮件
0
投稿

猜你喜欢

  • Java实现几种常见排序算法代码

    2022-10-10 20:42:19
  • Android Intent传递大量数据出现问题解决

    2021-11-07 10:16:13
  • Spring Boot中配置定时任务、线程池与多线程池执行的方法

    2021-08-08 13:31:30
  • 通过代码快速理解Java的三种代理模式

    2023-03-28 01:13:57
  • 深入了解C#设计模式之订阅发布模式

    2021-08-14 05:31:39
  • Android实现图像灰度化、线性灰度变化和二值化处理方法

    2021-10-17 15:49:10
  • Unity实现简单的虚拟摇杆

    2023-01-26 11:38:14
  • 如何通过指针突破C++类的访问权限

    2022-01-26 14:14:58
  • Android利用LitePal操作数据库存取图片

    2021-06-14 14:57:45
  • Unity Shader实现线框效果的制作步骤

    2023-10-10 06:14:54
  • JSON.toJSONString()空字段不忽略修改的问题

    2023-06-16 03:12:37
  • Java递归算法遍历部门代码示例

    2021-08-03 20:59:20
  • Spring Boot 自动配置的实现

    2023-07-21 18:18:55
  • Java背包问题求解实例代码

    2023-10-05 06:20:33
  • Java实现RSA加密工具类

    2023-08-23 08:41:02
  • C/C++ Qt 基本文件读写的基本使用(2种实现)

    2021-09-17 05:15:36
  • Android从源码的角度彻底理解事件分发机制的解析(下)

    2023-09-21 11:23:59
  • 带你了解Java数据结构和算法之前缀,中缀和后缀表达式

    2023-03-15 10:22:46
  • C#使用listView增删操作实例

    2023-03-25 12:34:52
  • SpringBoot文件分片上传的示例代码

    2023-06-18 11:30:15
  • asp之家 软件编程 m.aspxhome.com