package com.skycn.pop3; import java.io.File; import java.util.Properties; /*** * 收邮件基本信息 * @author tianzhw * */ public class MailReceiverInfo { //邮件服务器IP和端口和协议 private String mailServerHost; private String mailServerPost; private String protpcal = "pop3"; //登录邮件服务器的用户名和密码 private String userName; private String passWord; //保存邮件的路径 private String attchmentDir = ""; private String emailDir = ""; private String emailFileSuffix = ".eml"; //是否要确认身份 private boolean vaildate = true; //获得邮件的属性初始化 public Properties getProperties() { Properties properties = new Properties(); properties.put("mail.pop3.host", mailServerHost); properties.put("mail.pop3.port", mailServerPost); properties.put("mail.pop3.auth", vaildate ? "true" : "false"); return properties; } public String getMailServerHost() { return mailServerHost; } public void setMailServerHost(String mailServerHost) { this.mailServerHost = mailServerHost; } public String getMailServerPost() { return mailServerPost; } public void setMailServerPost(String mailServerPost) { this.mailServerPost = mailServerPost; } public String getProtpcal() { return protpcal; } public void setProtpcal(String protpcal) { this.protpcal = protpcal; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String getAttchmentDir() { return attchmentDir; } public void setAttchmentDir(String attchmentDir) { if (!attchmentDir.endsWith(File.separator)) { attchmentDir = attchmentDir + File.separator; } this.attchmentDir = attchmentDir; } public String getEmailDir() { return emailDir; } public void setEmailDir(String emailDir) { if (!emailDir.endsWith(File.separator)) { emailDir = emailDir + File.separator; } this.emailDir = emailDir; } public String getEmailFileSuffix() { return emailFileSuffix; } public void setEmailFileSuffix(String emailFileSuffix) { if (!emailFileSuffix.endsWith(File.separator)) { emailFileSuffix = emailFileSuffix + File.separator; } this.emailFileSuffix = emailFileSuffix; } public boolean isVaildate() { return vaildate; } public void setVaildate(boolean vaildate) { this.vaildate = vaildate; } } package com.skycn.pop3; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.io.UnsupportedEncodingException; import javax.mail.BodyPart; import javax.mail.Flags; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.NoSuchProviderException; import javax.mail.Part; import javax.mail.Session; import javax.mail.Store; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import javax.xml.crypto.Data; import com.skycn.helper.MyAuthenticator; /******************************************************************************* * 邮件接收器,目前支持pop3协议 能够接受文本,html和带有福建的邮件 * * @author tianzhw */ @SuppressWarnings("unused") public class MailReceiver { private MailReceiverInfo receiverInfo;// 邮件的参数配置 private Store store;// 以邮件服务器连接后得到的邮箱 private Folder folder;// 收件箱 private Message[] messages;// 收件箱中的邮件消息 private Message currentMessage;// 正在处理的邮件消息 private String currentEmailFileName; public MailReceiver(MailReceiverInfo receiverInfo) { this.receiverInfo = receiverInfo; } /*************************************************************************** * 收邮件 */ public void receiveAllMail() throws Exception { if (this.receiverInfo == null) { throw new Exception("必须提供收邮件的参数"); } // 打开连接 if (this.connectToServer()) { // 打开收件箱 if (this.openInBoxFolder()) { // 收件箱里面的邮件信息输出 this.getAllMail(); this.closeConnection(); } else { throw new Exception("打开连接失败"); } } else { throw new Exception("打开连接失败"); } } /*************************************************************************** * 登录服务器,登录服务器,通过Session对象创建store对象。同时讲session对象中认证名和密码,协议描述,等信息通知服务器。 */ @SuppressWarnings("unused") private boolean connectToServer() { // 判断是否需要身份认证 MyAuthenticator authenticator = null; if (this.receiverInfo.isVaildate()) { // 如果需要身份认证,则创建一个密码验证器 authenticator = new MyAuthenticator( this.receiverInfo.getUserName(), this.receiverInfo .getPassWord()); } // 创建一个session Session mailSession = Session.getInstance(this.receiverInfo .getProperties()); try { // 创建store,建立连接,通过Session对象是可以创建一个store对象的。 this.store = mailSession.getStore(this.receiverInfo.getProtpcal()); } catch (NoSuchProviderException e) { System.out.println("链接服务器失败"); return false; } System.out.println("connecting"); try { this.store.connect(); } catch (MessagingException e) { // TODO Auto-generated catch block System.out.println("链接服务器失败"); return false; } return true; } /*************************************************************************** * 打开收件箱 * stroe是一个邮箱的整体,如果连接上以后,我们有很多抽屉,Inbox是国际默认的收件箱(抽屉的)标示。但是也有不是这样的,这取决于什么邮件服务器 */ private boolean openInBoxFolder() { try { this.folder = this.store.getFolder("inbox"); folder.open(Folder.READ_ONLY); return true; } catch (MessagingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } /*************************************************************************** * 关闭链接 * * @return */ private boolean closeConnection() { try { if (this.folder.isOpen()) { this.folder.close(true); } this.store.close(); System.out.println("关闭链接成功 "); return true; } catch (MessagingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } private void getAllMail() throws Exception { // 文件夹下获取邮件信息 this.messages = this.folder.getMessages(); System.out.println("总邮件数目:" + messages.length); System.out.println("新邮件数目:" + this.getNewMessageCount()); System.out.println("未读邮件数目:" + this.getUnreadMessageConunt()); // 将要下载的邮件数量 int mailArrayLength = this.getMessageCount(); System.out.println("一共有邮件" + mailArrayLength + "封"); int errorCounter = 0; int successCounter = 0; for (int index = 0; index < mailArrayLength; index++) { this.currentMessage = messages[index]; System.out.println("正在获取第" + index + "封邮件~~~~~~~~~~~~~~"); this.showMailBasicInfo(); } } private void showMailBasicInfo() throws Exception { // TODO Auto-generated method stub showMailBasicInfo(this.currentMessage); } /*************************************************************************** * 显示邮件的基本信息 * * @param message * @throws Exception */ private void showMailBasicInfo(Message message) throws Exception { // TODO Auto-generated method stub System.out.println("~~~~~~~~~~~邮件ID:" + this.getMessageId() + "~~~~~~~~~~~~~~~~~~~~~~~ "); System.out.println("From:" + this.getFrom()); System.out.println("To:" + this.getToAddress()); System.out.println("CC:" + this.getCCAddress()); System.out.println("BCC:" + this.getBCCAddress()); System.out.println("Subject:" + this.getSubject()); System.out.println("发送时间:" + this.getSentDate()); System.out.println("是新邮件?:" + this.isNew()); System.out.println("是否回执:" + this.getReplySign()); System.out.println("包涵附件:" + this.isContainAttch()); System.out .println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } private boolean isContainAttch() throws Exception { // TODO Auto-generated method stub return isContainAttch(this.currentMessage); } /*************************************************************************** * 判断邮件是否是包含附件 * * @param part * @return * @throws Exception */ private boolean isContainAttch(Part part) throws Exception { boolean attachflag = false; if (part.isMimeType("multipart/*")) { // 如果邮件体包含多部分 Multipart mp = (Multipart) part.getContent(); for (int i = 0; i < mp.getCount(); i++) { BodyPart bodyPart = mp.getBodyPart(i); String disposition = bodyPart.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition .equals(Part.INLINE))))) { attachflag = true; } else if (bodyPart.isMimeType("Multipart/*")) { attachflag = isContainAttch((Part) bodyPart); } else { String contype = bodyPart.getContentType(); if (contype.toLowerCase().indexOf("applcation") != -1) { attachflag = true; } if (contype.toLowerCase().indexOf("name") != -1) { attachflag = true; } } } } else if (part.isMimeType("message/rfc822")) { attachflag = isContainAttch((Part) part.getContent()); } return attachflag; } private String getMessageId() throws Exception { // TODO Auto-generated method stub return getMessageId(this.currentMessage); } /*************************************************************************** * 获得Message - Id * * @param mimeMessage * @return * @throws Exception */ private String getMessageId(Message mimeMessage) throws Exception { MimeMessage message = (MimeMessage) mimeMessage; return message.getMessageID(); } private boolean getReplySign() throws Exception { // TODO Auto-generated method stub return getReplySign(this.currentMessage); } /*************************************************************************** * 判断邮件是否需要回执。 * * @param mimeMessage * @return * @throws Exception */ private boolean getReplySign(Message mimeMessage) throws Exception { // TODO Auto-generated method stub boolean replaysign = false; String[] needreply = (String[]) mimeMessage .getHeader("Disposition-Notification-To"); if (needreply != null) { replaysign = true; } return replaysign; } private boolean isNew() throws Exception { // TODO Auto-generated method stub return isNew(this.currentMessage); } /*************************************************************************** * 获得邮件是否是已经读过了 * * @param mimeMessage * @return * @throws Exception */ private boolean isNew(Message mimeMessage) throws Exception { // TODO Auto-generated method stub boolean isnew = false; Flags flags = mimeMessage.getFlags(); Flags.Flag[] flag = flags.getSystemFlags(); for (int i = 0; i < flag.length; i++) { if (flag[i] == Flags.Flag.SEEN) { isnew = true; break; } } return false; } private Data getSentDate() throws Exception { // TODO Auto-generated method stub return getSetDate(this.currentMessage); } /** * 获得邮件的发送日期 * * @param mimeMessage * @return * @throws Exception */ private Data getSetDate(Message mimeMessage) throws Exception { // TODO Auto-generated method stub return (Data) mimeMessage.getSentDate(); } /** * 获得邮件的发送主题 * * @return * @throws Exception */ private String getSubject() throws Exception { return getSubject(this.currentMessage); } private String getSubject(Message mimeMessage) throws Exception { // TODO Auto-generated method stub String subject = ""; try { subject = MimeUtility.decodeText(mimeMessage.getSubject()); if (subject == null) { subject = ""; } } catch (Exception e) { } return subject; } /*************************************************************************** * 获得发件人的地址和姓名 * * @return * @throws Exception */ private String getFrom() throws Exception { return getFrom(this.currentMessage); } /*************************************************************************** * 获得发件人的地址和姓名 * * @return * @throws Exception */ private String getFrom(Message mimeMessage) throws Exception { InternetAddress[] address = (InternetAddress[]) mimeMessage.getFrom(); // 获得发件人的邮件地址 String from = address[0].getAddress(); if (from == null) { from = ""; } // 获得发件人的描述 String personal = address[0].getPersonal(); if (personal == null) { personal = ""; } String fromaddr = personal + "<" + from + ">"; return fromaddr; } /** * 根据传递的参数的不同,获得邮件收件人、抄送、密送的地址和姓名 to---收件人 cc----抄送人 bcc----密送人 * * @return * @throws Exception */ private String getBCCAddress() throws Exception { // TODO Auto-generated method stub return getMailAddress("BCC", this.currentMessage); } private String getCCAddress() throws Exception { // TODO Auto-generated method stub return getMailAddress("CC", this.currentMessage); } private String getToAddress() throws Exception { // TODO Auto-generated method stub return getMailAddress("TO", this.currentMessage); } /*************************************************************************** * 获得邮件地址 * * @param type * 类型 如 收件人 抄送人 密送人 * @param mimeMessage * 邮件消息 * @return * @throws Exception */ private String getMailAddress(String type, Message mimeMessage) throws Exception { String mailaddr = ""; String addtype = type.toUpperCase(); InternetAddress[] address = null; if (addtype.equals("TO") || addtype.equals("CC") || addtype.equals("BCC")) { if (addtype.equals("TO")) { address = (InternetAddress[]) mimeMessage .getRecipients(Message.RecipientType.TO); } if (addtype.equals("CC")) { address = (InternetAddress[]) mimeMessage .getRecipients(Message.RecipientType.CC); } if (addtype.equals("BCC")) { address = (InternetAddress[]) mimeMessage .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); } // 讲个人描述信息与邮件地址连接起来 String compostiteto = personal + "<" + email + ">"; // 多个地址用,号分隔 mailaddr += "," + compostiteto; } mailaddr = mailaddr.substring(1); } } else { throw new Exception("错误的地址类型"); } return mailaddr; } /*************************************************************************** * 获得messages中Message的个数 * * @return */ private int getMessageCount() { // TODO Auto-generated method stub return this.messages.length; } /** * 获得邮件里面未读的邮件个数 * * @return * @throws MessagingException */ private int getUnreadMessageConunt() throws MessagingException { // TODO Auto-generated method stub return this.folder.getUnreadMessageCount(); } /** * 获得邮件里面新邮件的个数 * * @return * @throws MessagingException */ private int getNewMessageCount() throws MessagingException { // TODO Auto-generated method stub return this.folder.getNewMessageCount(); } /*************************************************************************** * 获得当前邮件 * * @throws MessagingException * @throws IOException */ private void getMail() throws Exception { this.saveMessageAsFile(this.currentMessage); this.parseMessage(this.currentMessage); } /*************************************************************************** * 解析邮件 * * @param currentMessage2 * @throws MessagingException * @throws IOException */ private void parseMessage(Message message) throws IOException, MessagingException { Object content = message.getContent(); if (content instanceof Multipart) { handleMultipart((Multipart) content); } else { handlePart(message); } } /*************************************************************************** * 解析Multipart * * @param content * @throws MessagingException * @throws IOException */ private void handleMultipart(Multipart multipart) throws MessagingException, IOException { for (int i = 0, n = multipart.getCount(); i < n; i++) { handlePart(multipart.getBodyPart(i)); } } /*************************************************************************** * * @param bodyPart * @throws MessagingException * @throws IOException */ private void handlePart(Part part) throws MessagingException, IOException { String dispostion = part.getDisposition(); String contentType = part.getContentType(); String fileNameWidthExtension = ""; // 获得邮件的内容输入流 InputStreamReader sbis = new InputStreamReader(part.getInputStream()); // 在没有附件的情况 if (dispostion == null) { if ((contentType.length() >= 10) && (contentType.toLowerCase().substring(0, 10) .equals("text/plain"))) { fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + this.currentEmailFileName + ".txt"; } else if ((contentType.length() >= 9) && (contentType.toLowerCase().substring(0, 9) .equals("text/html"))) { fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + this.currentEmailFileName + ".html"; } else if ((contentType.length() >= 9) && (contentType.toLowerCase().substring(0, 9) .equals("text/gif"))) { fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + this.currentEmailFileName + ".gif"; } else if ((contentType.length() >= 9) && (contentType.toLowerCase().substring(0, 9) .equals("multipart/*"))) { handleMultipart((Multipart) part.getContent()); } else { fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + this.currentEmailFileName + ".txt"; } System.out.println("保存邮件内容到:" + fileNameWidthExtension); saveFile(fileNameWidthExtension, sbis); return; } // 各种有附件的情况 String name = ""; if (dispostion.equalsIgnoreCase(Part.ATTACHMENT)) { name = getFileName(part); fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + name; } else if (dispostion.equalsIgnoreCase(Part.INLINE)) { name = getFileName(part); fileNameWidthExtension = this.receiverInfo.getAttchmentDir() + name; } else { } // 储存各类附件 if (!fileNameWidthExtension.equals("")) { System.out.println("保存邮件附件到:" + fileNameWidthExtension); saveFile(fileNameWidthExtension, sbis); } } private String getFileName(Part part) throws UnsupportedEncodingException, MessagingException { String fileName = part.getFileName(); fileName = MimeUtility.decodeText(fileName); String name = fileName; if (fileName != null) { int index = fileName.lastIndexOf("/"); if (index != -1) { name = fileName.substring(index + 1); } } return name; } /*************************************************************************** * 保存邮件源文件 * * @param currentMessage2 */ private void saveMessageAsFile(Message message) { try { // 将邮件ID中尖括号中的部分作为邮件的文件名 String oriFileName = getInfoBetweenBrackets(this.getMessageId( message).toString()); // 设置文件后缀名,如是附件则设法取得其文件后缀名作为将要保存文件的后缀名。如是正文不封则用。html作为后缀名 String emlName = oriFileName; String fileNameWidthExtension = this.receiverInfo.getEmailDir() + oriFileName + this.receiverInfo.getEmailFileSuffix(); File storeFile = new File(fileNameWidthExtension); for (int i = 0; storeFile.exists(); i++) { emlName = oriFileName + i; fileNameWidthExtension = this.receiverInfo.getEmailDir() + emlName + this.receiverInfo.getEmailFileSuffix(); storeFile = new File(fileNameWidthExtension); } this.currentEmailFileName = emlName; System.out.println("邮件消息的存储路径:" + fileNameWidthExtension); // 将邮件消息的内容写入ByteArrayOutputStram流中 ByteArrayOutputStream baos = new ByteArrayOutputStream(); message.writeTo(baos); StringReader in = new StringReader(baos.toString()); saveFile(fileNameWidthExtension, in); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 保存文件内容 * * @param fileName * @param in * @throws IOException */ private void saveFile(String fileName, Reader in) throws IOException { // 为了防止文件名重名,在重名的文件后面添加上数字 File file = new File(fileName); // 先取得文件名的后缀 int lastDot = fileName.lastIndexOf("."); String extension = fileName.substring(lastDot); fileName = fileName.substring(0, lastDot); for (int i = 0; file.exists(); i++) { file = new File(fileName + i + extension); } // 从输入流中读取数据,写入文件的输入流 FileWriter fos = new FileWriter(file); BufferedWriter bos = new BufferedWriter(fos); BufferedReader bis = new BufferedReader(in); int aByte; while ((aByte = bis.read()) != -1) { bos.write(aByte); } bos.flush(); bos.close(); bis.close(); } /** * 获得尖括号之间的字符串 如 tianzhw <tianzhw@vip.qq.com> ----- tianzhw@vip.qq.cpm * * @param string * @return */ private String getInfoBetweenBrackets(String str) { int i, j; if (str == null) { str = "error"; return str; } i = str.lastIndexOf("<"); j = str.lastIndexOf(">"); if (i != 1 && j != -1) { str = str.substring(i + 1, j); } return str; } public static void main(String[] args) throws Exception { MailReceiverInfo info = new MailReceiverInfo(); info.setMailServerHost("pop.163.com"); info.setMailServerPost("110"); info.setVaildate(true); info.setUserName("*************"); info.setPassWord("*************"); info.setAttchmentDir("F:/mails"); info.setEmailDir("F:/mails"); MailReceiver receiver = new MailReceiver(info); receiver.receiveAllMail(); } }