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;
String partname=null;
String nodepara=null;
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
}
}
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;
String partname=null;
String nodepara=null;
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
}
}