春天花会开

***********

统计

留言簿(4)

阅读排行榜

评论排行榜

javamail读取完整的邮件

Javamail API虽然功能封装的比较完整,但是要写一个能正确显示复杂邮件的程序还有很多逻辑和细节要处理。下面是我最近做一个webmail时整理的Servlet,基本上可以正确的读取text,HTML,HTML中显示图片及附件。在本servlet中也简单处理了常见的中文问题,包括主题、附件、HTML图片中文、email Address中文。总体感觉有两个难点:1、附件和网页图片的抓取,需要定位数节点nodeid,光用partid是不行的;2、中文分两种情况Base64和客户端服务器端编码不一致。本程序中实现了3种displayPart()的方法,具体情况不同结合使用效率更高。本程序还有一个未处理的地方就是我在做nodeid的时候最多算10个。当然还有其他问题欢迎指正,来出是为了给后来的初学者作个参考例子,少走弯路。
  1 import  java.io.IOException;
  2 import  java.io.InputStream;
  3 import  java.io.UnsupportedEncodingException;
  4 import  java.util.HashMap;
  5 import  javax.mail.Folder;
  6 import  javax.mail.Message;
  7 import  javax.mail.MessagingException;
  8 import  javax.mail.Multipart;
  9 import  javax.mail.Part;
 10 import  javax.mail.Store;
 11 import  javax.mail.internet.InternetAddress;
 12 import  javax.mail.internet.MimeUtility;
 13 import  javax.servlet.ServletException;
 14 import  javax.servlet.ServletOutputStream;
 15 import  javax.servlet.http.HttpServletRequest;
 16 import  javax.servlet.http.HttpServletResponse;
 17 import  javax.servlet.http.HttpSession;
 18 import  chunwei.mail.Login;
 19 import  chunwei.mail.MailUserData;
 20 /**
 21 * Servlet implementation class for Servlet: MailServlet
 22 * Author: luchunwei  Email: luchunwei@gmail.com
 23 */
 24 public  class MailNode extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
 25 private  static final long serialVersionUID = 1L;
 26 protected  void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 27 nodeid="";
 28 node="0";
 29 currentnodeid=0;
 30 url=request.getRequestURL().toString();
 31 HttpSession ses=request.getSession();
 32 MailUserData mud=(MailUserData)ses.getAttribute("mud");
 33 ServletOutputStream out=response.getOutputStream();
 34 response.setContentType("text/html;charset=GB2312");
 35 int  msgid=-1,partid=-1;//msgdi:邮件编号;partid:MultiPart Message中part的编号。
 36 String  partname=null//图片或附件的文件名
 37 String  nodepara=null;//节点编号,如1-2-1-0, 他以便层层剥入
 38 if (request.getParameter("msgid")!=null)
 39 msgid=Integer.parseInt(request.getParameter("msgid"));
 40 msgidStr="msgid="+msgid;
 41 if (request.getParameter("partid")!=null)
 42 partid=Integer.parseInt(request.getParameter("partid"));
 43 if (request.getParameter("partname")!=null)
 44 partname=new String(request.getParameter("partname").getBytes("ISO-8859-1"),"GB2312");
 45 if (request.getParameter("node")!=null)
 46 nodepara=request.getParameter("node");
 47 System.out.println(nodepara);
 48 //System.out.println(msgid+":"+partid+":"+partname);
 49 if (partname!=null){
 50 //displayImages
 51 try  {
 52 displayPart(partname,response,out);
 53 }  catch (MessagingException e) {
 54 e.printStackTrace();
 55 }  catch (IOException e) {
 56 e.printStackTrace();
 57 }
 58 return;
 59 }
 60 //--------------------------
 61 if (mud==null){
 62 Login login=new Login("imap","mail.server.com",-1,"user","password");
 63 login.login();
 64 if (login.getResult()==1){
 65 HttpSession session = request.getSession();
 66 session.setMaxInactiveInterval(3600);
 67 session.setAttribute("mud",login.getMud());
 68 }
 69 mud=(MailUserData)ses.getAttribute("mud");
 70 }
 71 //---------------------------
 72 if (mud==null){
 73 out.print("<error>Login First(No Session)</error>");
 74 } else{
 75 //Folder folder=mud.getFolder();
 76 try  {
 77 //------------------------
 78 Store store=mud.getStore();
 79 Folder  folder=store.getFolder("INBOX");
 80 folder.open(Folder.READ_ONLY);
 81 //------------------------
 82 Message m=folder.getMessage(msgid);
 83 //if(partid==-1){
 84 if (nodepara==null){
 85 //if(!imgs.isEmpty())imgs.clear();
 86 messageHtml="";
 87 attachment="";
 88 recipients=getAllgetRecipients(m);
 89 out.print(displayMessage(request,m,partid));
 90 } else{
 91 displayPart(m,nodepara,response,out);
 92 }
 93 }  catch (MessagingException e) {
 94 e.printStackTrace();
 95 }  catch (IOException e) {
 96 e.printStackTrace();
 97 }  catch (Exception e) {
 98 e.printStackTrace();
 99 }
100 }
101 }       
102 protected  void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
103 doGet(request,response);
104 }  
105 String  stdUrl="";
106 String  url="";
107 String  msgidStr="";
108 String  messageHtml="";
109 String  attachment="";
110 String  recipients="";
111 String  nodeid="";
112 int  currentnodeid=0;
113 String  node="";
114 HashMap<String,Part> imgs=new HashMap<String,Part>();
115 public  String displayMessage(HttpServletRequest request,Part p,int partid) throws Exception{
116 //System.out.println("Type:"+p.getContentType());
117 if (currentnodeid==1&&!node.endsWith("0")){
118 nodeid=nodeid.substring(0,(nodeid.length()-2));
119 }
120 node=nodeid+currentnodeid;
121 System.out.println(node);
122 if (p.isMimeType("multipart/*")){
123 nodeid+=currentnodeid+"-";
124 Multipart mp=(Multipart) p.getContent();
125 int  cnt=mp.getCount();
126 String  mpct=mp.getContentType().toLowerCase();
127 for (int i=0;
128 i<cnt;
129 i++){
130 if (mpct.startsWith("multipart/alternative")&&mp.getBodyPart(i).getContentType().toLowerCase().startsWith("text/plain"))continue;
131 currentnodeid=i;
132 displayMessage(request,mp.getBodyPart(i),i);
133 }
134 }
135 if (p.isMimeType("text/plain")||p.isMimeType("text/html")){
136 if (messageHtml=="") {
137 messageHtml=(String)p.getContent();
138 //System.out.println(messageHtml);
139 }  else {
140 messageHtml=messageHtml+"<HR/>"+(String)p.getContent();
141 //System.out.println(messageHtml);
142 }
143 }  else if (p.isMimeType("message/rfc822")) {
144 //Nested Message
145 //displayMessage(request,(Part)p.getContent(),partid);
146 else{
147 if (node.length()>2)    node=node.substring(2);
148 System.out.println(node);
149 String  disposition=p.getDisposition();
150 //System.out.println("disposition:"+disposition);
151 if (disposition!=null&&disposition.equalsIgnoreCase(Part.ATTACHMENT)){
152 String  filename=getFileName(p);
153 //imgs.put(filename,p);
154 //attachment全部放入内存,会造成内存膨胀;若及时清空又造成Back回来的页面访问不到Attachment
155 //attachment+=","+"<a href='"+url+"/"+filename+"?"+msgidStr+"&partid="+partid+"'>"+filename+"</a>";
156 attachment+=","+"<a href='"+url+"/"+filename+"?"+msgidStr+"&node="+node+"'>"+filename+"</a>";
157 //attachment+=","+"<a href='"+url+"/"+filename+"?"+"&partname="+getFileName(p)+"'>"+filename+"</a>";
158 //System.out.println(attachment);
159 else{
160 //if(disposition!=null&&disposition.equalsIgnoreCase(Part.INLINE)){
161 if (getCid(p)!=null)    {
162 //System.out.println("Enter Replace");
163 imgs.put(getFileName(p),p);
164 //String uri=url+"?"+msgidStr+"&partid="+partid;
165 String  uri=url+"?"+msgidStr+"&node="+node;
166 //String uri=url+"?"+"&partname="+getFileName(p);
167 String  t=messageHtml.substring(messageHtml.indexOf(getCid(p))-1);
168 if (!(t.startsWith("\"")||t.startsWith("\'"))){
169 uri="'"+uri+"'";
170 }
171 messageHtml=messageHtml.replace(getCid(p),uri);
172 //System.out.println("cid:"+getCid(p));     
173 //System.out.println(uri);
174 }
175 }
176 }
177 return  messageHtml+"attachhncwx="+attachment+recipients;
178 }
179 public  void displayPart(Message m,String node,HttpServletResponse response,ServletOutputStream out) 
180 throws MessagingException, IOException{
181 Part part = getPart(m,node);
182 String  sct = part.getContentType();
183 response.setContentType(sct);
184 outPut(part,out);
185 }
186 private  Part getPart(Part m, String nodes) throws NumberFormatException, MessagingException, IOException {
187 if (node==null)return m;
188 String  node=nodes.substring(0,1);
189 System.out.println(nodes+" : "+node);
190 int  nid=Integer.parseInt(node);
191 if (m.getContent()==null)System.out.print("no content");
192 Part p=((Multipart)m.getContent()).getBodyPart(nid);
193 if (nodes.length()>2)nodes=nodes.substring(2);
194 else  {
195 if (nodes.length()==1)nodes="";
196 }
197 if (nodes.length()>0)p=getPart(p,nodes);
198 return  p;
199 }
200 public  void displayPart(String partname,HttpServletResponse response,    ServletOutputStream out) throws MessagingException, IOException{
201 //System.out.println(imgs.keySet()+":"+partname);
202 Part part=imgs.get(partname);
203 String  ct=part.getContentType();
204 if (ct!=null)        response.setContentType(ct);
205 //=====Start push Stream into out
206 InputStream in=part.getInputStream();
207 ByteArrayOutputStream bos=new ByteArrayOutputStream();
208 byte [] buffer=new byte[8192];
209 int  count=0;
210 while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);
211 in .close();
212 try{
213 out.write(bos.toByteArray());
214 out.flush();
215 } catch(Exception e){
216 }
217 out.close();
218 //=====End
219 }
220 public  void displayPart(Message m,int partid,HttpServletResponse response,        ServletOutputStream out) throws MessagingException, IOException{
221 Multipart mp = (Multipart)m.getContent();
222 Part part = mp.getBodyPart(partid);
223 String  sct = part.getContentType();
224 // ContentType ct = new ContentType(sct);
225 response.setContentType(sct);
226 if  (sct == null) {
227 out.println("invalid part");
228 return;
229 }
230 //=====Start push Stream into out
231 InputStream in=part.getInputStream();
232 ByteArrayOutputStream bos=new ByteArrayOutputStream();
233 byte [] buffer=new byte[8192];
234 int  count=0;
235 while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);
236 in .close();
237 try{
238 out.write(bos.toByteArray());
239 out.flush();
240 } catch(Exception e){
241 }
242 out.close();
243 //=====End
244 }
245 private  String getFileName(Part p) throws MessagingException, UnsupportedEncodingException{
246 //System.out.println("filename:");
247 String  filename=p.getFileName();
248 if (filename==null)return null;
249 filename=new String(filename.getBytes("ISO-8859-1"),"GB2312");
250 int  indexStart=filename.toUpperCase().indexOf("=?GB");
251 if (indexStart>-1){
252 filename=filename.substring(0,indexStart)+MimeUtility.decodeText(filename.substring(indexStart));
253 }
254 return  filename;
255 }
256 private  String getCid(Part p) throws MessagingException{
257 String  cidraw=null,cid=null;
258     
259 String [] headers=p.getHeader("Content-id");
260 if (headers!=null && headers.length>0) {
261 cidraw=headers[0];
262 } else{
263 return  null;
264 }
265 if (cidraw.startsWith("<")&&cidraw.endsWith(">")) {
266 cid="cid:"+cidraw.substring(1,cidraw.length()-1);
267 }  else {
268 cid="cid:"+cidraw;
269 }
270 return  cid;
271 }
272 /**
273 * 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同 "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
274 @throws Exception 
275 */
276 private  String getAllgetRecipients(Message m) throws Exception{
277 return  "mailaddrTo="    +getRecipients(m,"TO")
278 +"mailaddrCc="+getRecipients(m,"CC")
279 +"mailaddrBcc="+getRecipients(m,"BCC");
280 }
281 private  String getRecipients(Message m,String type) throws Exception {
282 StringBuffer mailaddr = new StringBuffer("");
283 String  addtype = type.toUpperCase();
284 InternetAddress[] address = null;
285 if  (addtype.equals("TO")) {
286 address = (InternetAddress[]) m.getRecipients(Message.RecipientType.TO);
287 }  else if (addtype.equals("CC")) {
288 address = (InternetAddress[]) m.getRecipients(Message.RecipientType.CC);
289 }  else {
290 address = (InternetAddress[]) m.getRecipients(Message.RecipientType.BCC);
291 }
292 if  (address != null) {
293 for  (int i = 0;
294 i < address.length;
295 i++) {
296 String  email = address[i].getAddress();
297 if  (email == null)
298 email = "";
299 else  {
300 email = MimeUtility.decodeText(email);
301 }
302 String  personal = address[i].getPersonal();
303 if  (personal == null)
304 personal = "";
305 else  {
306 personal = MimeUtility.decodeText(personal);
307 }
308 mailaddr.append("\""+personal+"\" ");
309 mailaddr.append("<");
310 mailaddr.append(email);
311 mailaddr.append(">");
312 mailaddr.append(",");
313 }
314 }
315 if (mailaddr.length()>0)mailaddr.deleteCharAt(mailaddr.length()-1);
316 return  mailaddr.toString();
317 }
318 private  void outPut(Part part,ServletOutputStream out) throws IOException, MessagingException{
319 //=====Start push Stream into out
320 InputStream in=part.getInputStream();
321 ByteArrayOutputStream bos=new ByteArrayOutputStream();
322 byte [] buffer=new byte[8192];
323 int  count=0;
324 while ((count=in.read(buffer))>=0) bos.write(buffer,0,count);
325 in .close();
326 try{
327 out.write(bos.toByteArray());
328 out.flush();
329 } catch(Exception e){
330 }
331 out.close();
332 //=====End
333 }
334 }




posted on 2006-07-02 08:17 春天花会开 阅读(9377) 评论(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

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


只有注册用户登录后才能发表评论。


网站导航: