春天花会开

***********

统计

留言簿(4)

阅读排行榜

评论排行榜

javamail读取完整的邮件

Javamail API虽然功能封装的比较完整,但是要写一个能正确显示复杂邮件的程序还有很多逻辑和细节要处理。下面是我最近做一个webmail时整理的Servlet,基本上可以正确的读取text,HTML,HTML中显示图片及附件。在本servlet中也简单处理了常见的中文问题,包括主题、附件、HTML图片中文、email Address中文。总体感觉有两个难点:1、附件和网页图片的抓取,需要定位数节点nodeid,光用partid是不行的;2、中文分两种情况Base64和客户端服务器端编码不一致。本程序中实现了3种displayPart()的方法,具体情况不同结合使用效率更高。本程序还有一个未处理的地方就是我在做nodeid的时候最多算10个。当然还有其他问题欢迎指正,来出是为了给后来的初学者作个参考例子,少走弯路。

import  java.io.IOException;

import  java.io.InputStream;

import  java.io.UnsupportedEncodingException;

import  java.util.HashMap;

import  javax.mail.Folder;

import  javax.mail.Message;

import  javax.mail.MessagingException;

import  javax.mail.Multipart;

import  javax.mail.Part;

import  javax.mail.Store;

import  javax.mail.internet.InternetAddress;

import  javax.mail.internet.MimeUtility;

import  javax.servlet.ServletException;

import  javax.servlet.ServletOutputStream;

import  javax.servlet.http.HttpServletRequest;

import  javax.servlet.http.HttpServletResponse;

import  javax.servlet.http.HttpSession;

import  chunwei.mail.Login;

import  chunwei.mail.MailUserData;

/**
* Servlet implementation class for Servlet: MailServlet
* Author: luchunwei  Email: luchunwei@gmail.com
*/

public  class MailNode extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

private  static final long serialVersionUID = 1L;

protected  void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

nodeid="";

node="0";

currentnodeid=0;

url=request.getRequestURL().toString();

HttpSession ses=request.getSession();

MailUserData mud=(MailUserData)ses.getAttribute("mud");

ServletOutputStream out=response.getOutputStream();

response.setContentType("text/html;charset=GB2312");

int  msgid=-1,partid=-1;//msgdi:邮件编号;partid:MultiPart Message中part的编号。

String  partname=null; //图片或附件的文件名

String  nodepara=null;//节点编号,如1-2-1-0, 他以便层层剥入

if (request.getParameter("msgid")!=null)

msgid=Integer.parseInt(request.getParameter("msgid"));

msgidStr="msgid="+msgid;

if (request.getParameter("partid")!=null)

partid=Integer.parseInt(request.getParameter("partid"));

if (request.getParameter("partname")!=null)

partname=new String(request.getParameter("partname").getBytes("ISO-8859-1"),"GB2312");

if (request.getParameter("node")!=null)

nodepara=request.getParameter("node");

System.out.println(nodepara);

//System.out.println(msgid+":"+partid+":"+partname);

if (partname!=null){

//displayImages

try  {

displayPart(partname,response,out);

}  catch (MessagingException e) {

e.printStackTrace();

}  catch (IOException e) {

e.printStackTrace();

}

return;

}

//--------------------------

if (mud==null){

Login login=new Login("imap","mail.server.com",-1,"user","password");

login.login();

if (login.getResult()==1){

HttpSession session = request.getSession();

session.setMaxInactiveInterval(3600);

session.setAttribute("mud",login.getMud());

}

mud=(MailUserData)ses.getAttribute("mud");

}

//---------------------------

if (mud==null){

out.print("<error>Login First(No Session)</error>");

} else{

//Folder folder=mud.getFolder();

try  {

//------------------------

Store store=mud.getStore();

Folder  folder=store.getFolder("INBOX");

folder.open(Folder.READ_ONLY);

//------------------------

Message m=folder.getMessage(msgid);

//if(partid==-1){

if (nodepara==null){

//if(!imgs.isEmpty())imgs.clear();

messageHtml="";

attachment="";

recipients=getAllgetRecipients(m);

out.print(displayMessage(request,m,partid));

} else{

displayPart(m,nodepara,response,out);

}

}  catch (MessagingException e) {

e.printStackTrace();

}  catch (IOException e) {

e.printStackTrace();

}  catch (Exception e) {

e.printStackTrace();

}

}

}       

protected  void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request,response);

}  

String  stdUrl="";

String  url="";

String  msgidStr="";

String  messageHtml="";

String  attachment="";

String  recipients="";

String  nodeid="";

int  currentnodeid=0;

String  node="";

HashMap<String,Part> imgs=new HashMap<String,Part>();

public  String displayMessage(HttpServletRequest request,Part p,int partid) throws Exception{

//System.out.println("Type:"+p.getContentType());

if (currentnodeid==1&&!node.endsWith("0")){

nodeid=nodeid.substring(0,(nodeid.length()-2));

}

node=nodeid+currentnodeid;

System.out.println(node);

if (p.isMimeType("multipart/*")){

nodeid+=currentnodeid+"-";

Multipart mp=(Multipart) p.getContent();

int  cnt=mp.getCount();

String  mpct=mp.getContentType().toLowerCase();

for (int i=0;

i<cnt;

i++){

if (mpct.startsWith("multipart/alternative")&&mp.getBodyPart(i).getContentType().toLowerCase().startsWith("text/plain"))continue;

currentnodeid=i;

displayMessage(request,mp.getBodyPart(i),i);

}

}

if (p.isMimeType("text/plain")||p.isMimeType("text/html")){

if (messageHtml=="") {

messageHtml=(String)p.getContent();

//System.out.println(messageHtml);

}  else {

messageHtml=messageHtml+"<HR/>"+(String)p.getContent();

//System.out.println(messageHtml);

}

}  else if (p.isMimeType("message/rfc822")) {

//Nested Message

//displayMessage(request,(Part)p.getContent(),partid);

} else{

if (node.length()>2)    node=node.substring(2);

System.out.println(node);

String  disposition=p.getDisposition();

//System.out.println("disposition:"+disposition);

if (disposition!=null&&disposition.equalsIgnoreCase(Part.ATTACHMENT)){

String  filename=getFileName(p);

//imgs.put(filename,p);

//attachment全部放入内存,会造成内存膨胀;若及时清空又造成Back回来的页面访问不到Attachment

//attachment+=","+"<a href='"+url+"/"+filename+"?"+msgidStr+"&partid="+partid+"'>"+filename+"</a>";

attachment+=","+"<a href='"+url+"/"+filename+"?"+msgidStr+"&node="+node+"'>"+filename+"</a>";

//attachment+=","+"<a href='"+url+"/"+filename+"?"+"&partname="+getFileName(p)+"'>"+filename+"</a>";

//System.out.println(attachment);

} else{

//if(disposition!=null&&disposition.equalsIgnoreCase(Part.INLINE)){

if (getCid(p)!=null)    {

//System.out.println("Enter Replace");

imgs.put(getFileName(p),p);

//String uri=url+"?"+msgidStr+"&partid="+partid;

String  uri=url+"?"+msgidStr+"&node="+node;

//String uri=url+"?"+"&partname="+getFileName(p);

String  t=messageHtml.substring(messageHtml.indexOf(getCid(p))-1);

if (!(t.startsWith("\"")||t.startsWith("\'"))){

uri="'"+uri+"'";

}

messageHtml=messageHtml.replace(getCid(p),uri);

//System.out.println("cid:"+getCid(p));     

//System.out.println(uri);

}

}

}

return  messageHtml+"attachhncwx="+attachment+recipients;

}

public  void displayPart(Message m,String node,HttpServletResponse response,ServletOutputStream out) 

throws MessagingException, IOException{

Part part = getPart(m,node);

String  sct = part.getContentType();

response.setContentType(sct);

outPut(part,out);

}

private  Part getPart(Part m, String nodes) throws NumberFormatException, MessagingException, IOException {

if (node==null)return m;

String  node=nodes.substring(0,1);

System.out.println(nodes+" : "+node);

int  nid=Integer.parseInt(node);

if (m.getContent()==null)System.out.print("no content");

Part p=((Multipart)m.getContent()).getBodyPart(nid);

if (nodes.length()>2)nodes=nodes.substring(2);

else  {

if (nodes.length()==1)nodes="";

}

if (nodes.length()>0)p=getPart(p,nodes);

return  p;

}

public  void displayPart(String partname,HttpServletResponse response,    ServletOutputStream out) throws MessagingException, IOException{

//System.out.println(imgs.keySet()+":"+partname);

Part part=imgs.get(partname);

String  ct=part.getContentType();

if (ct!=null)        response.setContentType(ct);

//=====Start push Stream into out

InputStream in=part.getInputStream();

ByteArrayOutputStream bos=new ByteArrayOutputStream();

byte [] buffer=new byte[8192];

int  count=0;

while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);

in .close();

try{

out.write(bos.toByteArray());

out.flush();

} catch(Exception e){

}

out.close();

//=====End

}

public  void displayPart(Message m,int partid,HttpServletResponse response,        ServletOutputStream out) throws MessagingException, IOException{

Multipart mp = (Multipart)m.getContent();

Part part = mp.getBodyPart(partid);

String  sct = part.getContentType();

// ContentType ct = new ContentType(sct);

response.setContentType(sct);

if  (sct == null) {

out.println("invalid part");

return;

}

//=====Start push Stream into out

InputStream in=part.getInputStream();

ByteArrayOutputStream bos=new ByteArrayOutputStream();

byte [] buffer=new byte[8192];

int  count=0;

while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);

in .close();

try{

out.write(bos.toByteArray());

out.flush();

} catch(Exception e){

}

out.close();

//=====End

}

private  String getFileName(Part p) throws MessagingException, UnsupportedEncodingException{

//System.out.println("filename:");

String  filename=p.getFileName();

if (filename==null)return null;

filename=new String(filename.getBytes("ISO-8859-1"),"GB2312");

int  indexStart=filename.toUpperCase().indexOf("=?GB");

if (indexStart>-1){

filename=filename.substring(0,indexStart)+MimeUtility.decodeText(filename.substring(indexStart));

}

return  filename;

}

private  String getCid(Part p) throws MessagingException{

String  cidraw=null,cid=null;

    

String [] headers=p.getHeader("Content-id");

if (headers!=null && headers.length>0) {

cidraw=headers[0];

} else{

return  null;

}

if (cidraw.startsWith("<")&&cidraw.endsWith(">")) {

cid="cid:"+cidraw.substring(1,cidraw.length()-1);

}  else {

cid="cid:"+cidraw;

}

return  cid;

}

/**
* 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同 "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
* @throws Exception 
*/

private  String getAllgetRecipients(Message m) throws Exception{

return  "mailaddrTo="    +getRecipients(m,"TO")

+"mailaddrCc="+getRecipients(m,"CC")

+"mailaddrBcc="+getRecipients(m,"BCC");

}

private  String getRecipients(Message m,String type) throws Exception {

StringBuffer mailaddr = new StringBuffer("");

String  addtype = type.toUpperCase();

InternetAddress[] address = null;

if  (addtype.equals("TO")) {

address = (InternetAddress[]) m.getRecipients(Message.RecipientType.TO);

}  else if (addtype.equals("CC")) {

address = (InternetAddress[]) m.getRecipients(Message.RecipientType.CC);

}  else {

address = (InternetAddress[]) m.getRecipients(Message.RecipientType.BCC);

}

if  (address != null) {

for  (int i = 0;

i < address.length;

i++) {

String  email = address[i].getAddress();

if  (email == null)

email = "";

else  {

email = MimeUtility.decodeText(email);

}

String  personal = address[i].getPersonal();

if  (personal == null)

personal = "";

else  {

personal = MimeUtility.decodeText(personal);

}

mailaddr.append("\""+personal+"\" ");

mailaddr.append("<");

mailaddr.append(email);

mailaddr.append(">");

mailaddr.append(",");

}

}

if (mailaddr.length()>0)mailaddr.deleteCharAt(mailaddr.length()-1);

return  mailaddr.toString();

}

private  void outPut(Part part,ServletOutputStream out) throws IOException, MessagingException{

//=====Start push Stream into out

InputStream in=part.getInputStream();

ByteArrayOutputStream bos=new ByteArrayOutputStream();

byte [] buffer=new byte[8192];

int  count=0;

while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);

in .close();

try{

out.write(bos.toByteArray());

out.flush();

} catch(Exception e){

}

out.close();

//=====End

}

}

posted on 2006-07-02 08:17 春天花会开 阅读(5100) 评论(14)  编辑  收藏

评论

# re: javamail读取完整的邮件 2006-07-06 18:55 纯净水

如果同时收取100封这样的邮件速度怎样?  回复  更多评论   

# re: javamail读取完整的邮件 2006-07-07 08:16 luchunwei

我没有试过100封,一般作为网络邮件(servlet)都是一封接一封的读,速度还可以。我前端用Ajax异步处理也没有发现什么问题。

注:最近发现接收.eml时出现ClassCase Exception.
  回复  更多评论   

# re: javamail读取完整的邮件 2006-08-25 09:47 wbw

能解释一下文中的从页面获得的变量都代表什么吗?  回复  更多评论   

# re: javamail读取完整的邮件 2006-08-25 10:14 春天花会开

我在旁边追加了注释,你看看清楚了吗  回复  更多评论   

# re: javamail读取完整的邮件 2006-09-26 21:39 holy

这样一个Servlet完成所有的功能感觉结构不好,如果能做一些封装,比如使得业务代码和MUA无关就好了,这样以后不用javamail,换其他的也方便。  回复  更多评论   

# re: javamail读取完整的邮件 2008-02-28 08:58 armysky

楼主:
能不能把你做好的给我发一份!
  回复  更多评论   

# re: javamail读取完整的邮件 2008-05-28 12:05 紫凝

MailUserData以及Login代码能否给我一份。我是初学者。不能根据您的程序自己写出这两个类、麻烦您了。我的QQ:16211803 MSN:27091497@163.com  回复  更多评论   

# re: javamail读取完整的邮件 2008-06-02 21:06 luchunwei

》@紫凝 你的QQ需要暗号
请看我的另一篇文章《 LuEmail 客户端+服务器代码全部开放 》
  回复  更多评论   

# re: javamail读取完整的邮件 2008-07-14 12:03 shcuo

import chunwei.mail.Login;


import chunwei.mail.MailUserData;
这个2类是自己写的什么类?  回复  更多评论   

# re: javamail读取完整的邮件 2008-07-15 16:36 luchunwei

Login、MailUserData是自己写的类,主要负责登录和保持用户信息。  回复  更多评论   

# re: javamail读取完整的邮件 2008-07-27 00:28 shuo

不导入这个类型可以用吧。。。注释不太清楚。。。
新手看不懂  回复  更多评论   

# re: javamail读取完整的邮件 2008-07-27 00:33 xuchao

楼主可以发一份完整的给我吗,可以最好有测试的。。。
你的这个我不还是看得不大懂
我的邮箱shcuo@163.com
  回复  更多评论   

# re: javamail读取完整的邮件 2008-07-28 18:54 luchunwei

@shuo
>>>
可以的,过不你需要指定用户名和密码,并且自己处理邮箱登陆的过程,因为这是servlet,我在登陆后把相关的信息保存到session里,以便在整个回话过程中都可以方便使用。
  回复  更多评论   

# re: javamail读取完整的邮件 2012-05-17 10:55 philosoft

楼主,我是新手,我觉得注释应该多一点,要不然看不太明白。  回复  更多评论   


博问 - 解决您的IT难题
博客园  博问  IT新闻  Java程序员招聘
标题  
姓名  
主页
验证码 *  
内容(请不要发表任何与政治相关的内容)  
  登录      


网站导航: