package com.royzhou.mail; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.Authenticator; 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.Part; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Store; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; public class MailUtil { private Properties props = null; //系统属性 private String hostName = null; //邮件主机 private String userName = null; //邮箱用户名 private String password = null; //邮箱密码 private String from = null; //发件人地址 private String fromName = null; //发件人名字 private String to = null; //收件人地址 private String copyTo = null; //抄送人地址,使用分号分割 private boolean debug = true; //在发送邮件的过程中在console处显示过程信息,供调试使用 private String dateformat = "yy-MM-dd HH:mm:ss"; //默认的日前显示格式 private String attachPath = null; //附件下载后的存放目录 public MailUtil(String smtpHost) { this.hostName = smtpHost; props = System.getProperties(); props.put("mail.smtp.host", smtpHost); //设置SMTP主机 /* * 需要经过授权,也就是有户名和密码的校验,这样才能通过验证 * 如果没有设置成true可能会抛出异常:553 authentication is required */ props.put("mail.smtp.auth", "true"); } /** * 文本邮件 * @param subject * @param content * @return */ public boolean sendTextMail(String subject, String content) { boolean flag = false; MyAuthenticator myAuthenticator = new MyAuthenticator(userName, password); //邮箱认证类 Session session = Session.getInstance(props, myAuthenticator); //邮件会话对象 session.setDebug(debug); MimeMessage message = new MimeMessage(session); //定义消息对象 try { if(fromName!=null) { message.setFrom(new InternetAddress(from,fromName)); } else { message.setFrom(new InternetAddress(from)); } message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); if(copyTo!=null) { message.addRecipients(Message.RecipientType.CC, InternetAddress.parse(copyTo)); } message.setSubject(subject); message.setText(content); message.saveChanges(); Transport.send(message); flag = true; System.out.println("发送邮件成功!"); } catch (Exception e) { System.out.println("发送文本邮件发生异常.............."); e.printStackTrace(); } return flag; } /** * html邮件 * 支持多附件 * @param subject * @param bodyContent * @param attachFiles * @return */ public boolean sendHTMLMail(String subject, String bodyContent, List attachFiles) { boolean flag = false; try { MyAuthenticator myAuthenticator = new MyAuthenticator(userName, password); //邮箱认证类 Session session = Session.getInstance(props, myAuthenticator); session.setDebug(debug); MimeMessage mimeMessage = new MimeMessage(session); Multipart multiPart = new MimeMultipart(); //设置标题 mimeMessage.setSubject(subject); //设置正文 BodyPart bodyPart = new MimeBodyPart(); bodyPart.setContent("" + bodyContent, "text/html;charset=GB2312"); multiPart.addBodyPart(bodyPart); //设置附件,下面定义的enc对象用来处理中文附件名,否则名称是中文的附件在邮箱里面显示的会是乱码, sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder(); for(int i=0; i<attachFiles.size(); i++) { bodyPart = new MimeBodyPart(); FileDataSource filed = new FileDataSource(attachFiles.get(i).toString()); bodyPart.setDataHandler(new DataHandler(filed)); bodyPart.setFileName("=?GBK?B?"+enc.encode(filed.getName().getBytes())+"?="); multiPart.addBodyPart(bodyPart); } if(fromName!=null) { mimeMessage.setFrom(new InternetAddress(from,fromName)); } else { mimeMessage.setFrom(new InternetAddress(from)); } mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); if(copyTo!=null) { mimeMessage.addRecipients(Message.RecipientType.CC, InternetAddress.parse(copyTo)); } mimeMessage.setContent(multiPart); mimeMessage.saveChanges(); /** * 如果没有使用认证类, * 即Session session = Session.getInstance(props,null); * 则可以通过下面方式来认证 * Transport transport = session.getTransport("smtp"); * transport.connect((String) props.get("mail.smtp.host"), userName, password); * transport.sendMessage(mimeMessage, mimeMessage.getRecipients((Message.RecipientType.TO))); * transport.close(); */ Transport.send(mimeMessage); flag = true; System.out.println("发送邮件成功!"); } catch (Exception e) { System.out.println("发送HTML邮件发生异常.............."); e.printStackTrace(); } return flag; } /** * 获取邮件对象数组 * @return */ public Message[] receiveMails(){ Session session = Session.getInstance(props, null); Message[] messages = null; Store store = null; Folder folder = null; try { store = session.getStore("pop3"); store.connect(hostName,userName,password); System.out.println("链接成功........."); folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); messages = folder.getMessages(); folder.close(true); store.close(); } catch (Exception e) { System.out.println("获取邮件列表发生错误..........."); e.printStackTrace(); } return messages; } /** * 获取邮件详细信息集合 * @return * @throws Exception */ public List getMailInfos() throws Exception { Session session = Session.getInstance(props, null); Message[] messages = null; Store store = null; Folder folder = null; List mailInfos = new ArrayList(); try { store = session.getStore("pop3"); store.connect(hostName,userName,password); System.out.println("链接成功........."); folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); messages = folder.getMessages(); MimeMessage mimeMessage = null; for(int i=0; i<messages.length; i++) { mimeMessage = (MimeMessage)messages[i]; Part part = (Part) mimeMessage; Map<String,String> mailInfo = new HashMap<String,String>(); mailInfo.put("from", getFrom(mimeMessage)); mailInfo.put("to", getMailAddress(mimeMessage, "to")); mailInfo.put("cc", getMailAddress(mimeMessage, "cc")); mailInfo.put("bcc", getMailAddress(mimeMessage, "bcc")); mailInfo.put("subject", getSubject(mimeMessage)); mailInfo.put("bodyContent", getMailContent(part)); mailInfo.put("messageId", getMessageId(mimeMessage)); mailInfo.put("sendDate", getSentDate(mimeMessage)); mailInfo.put("replySign", String.valueOf(getReplySign(mimeMessage))); mailInfo.put("isNew", String.valueOf(isNew(mimeMessage))); mailInfo.put("isContainAttach", String.valueOf(isContainAttach(part))); mailInfo.put("fileNames", saveAttachMent(part)); } folder.close(true); store.close(); } catch (Exception e) { System.out.println("获取邮件详细信息发生错误..........."); e.printStackTrace(); } return mailInfos; } /** * 获得发件人的地址和姓名 */ public String getFrom(MimeMessage 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"---密送人地址 */ public String getMailAddress(MimeMessage mimeMessage, String type) 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); } else if (addtype.equals("CC")) { address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC); } else { 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 compositeto = personal + "<" + email + ">"; mailaddr += "," + compositeto; } mailaddr = mailaddr.substring(1); } } else { throw new Exception("Error emailaddr type!"); } return mailaddr; } /** * 获得邮件主题 */ public String getSubject(MimeMessage mimeMessage) throws MessagingException { String subject = ""; try { subject = MimeUtility.decodeText(mimeMessage.getSubject()); if (subject == null) subject = ""; } catch (Exception exce) {} return subject; } /** * 解析邮件,把得到的邮件内容保存到一个StringBuffer对象中, * 解析邮件 主要是根据MimeType类型的不同执行不同的操作,一步一步的解析 */ public String getMailContent(Part part) throws Exception { StringBuffer bodyText = new StringBuffer(); String contenttype = part.getContentType(); int nameindex = contenttype.indexOf("name"); boolean conname = false; if (nameindex != -1) conname = true; System.out.println("CONTENTTYPE: " + contenttype); if (part.isMimeType("text/plain") && !conname) { bodyText.append((String) part.getContent()); } else if (part.isMimeType("text/html") && !conname) { bodyText.append((String) part.getContent()); } else if (part.isMimeType("multipart/*")) { Multipart multipart = (Multipart) part.getContent(); int counts = multipart.getCount(); for (int i = 0; i < counts; i++) { getMailContent(multipart.getBodyPart(i)); } } else if (part.isMimeType("message/rfc822")) { getMailContent((Part) part.getContent()); } return bodyText.toString(); } /** * 获得邮件发送日期 */ public String getSentDate(MimeMessage mimeMessage) throws Exception { Date sentdate = mimeMessage.getSentDate(); SimpleDateFormat format = new SimpleDateFormat(dateformat); return format.format(sentdate); } /** * 判断此邮件是否需要回执, * 如果需要回执返回"true",否则返回"false" */ public boolean getReplySign(MimeMessage mimeMessage) throws MessagingException { boolean replysign = false; String needreply[] = mimeMessage .getHeader("Disposition-Notification-To"); if (needreply != null) { replysign = true; } return replysign; } /** * 获得此邮件的Message-ID */ public String getMessageId(MimeMessage mimeMessage) throws MessagingException { return mimeMessage.getMessageID(); } /** * 【判断此邮件是否已读,如果未读返回返回false,反之返回true】 */ public boolean isNew(MimeMessage mimeMessage) throws MessagingException { boolean isnew = false; Flags flags = ((Message) mimeMessage).getFlags(); Flags.Flag[] flag = flags.getSystemFlags(); for (int i = 0; i < flag.length; i++) { if (flag[i] == Flags.Flag.SEEN) { isnew = true; System.out.println("seen Message......."); break; } } return isnew; } /** * 判断此邮件是否包含附件 */ public boolean isContainAttach(Part part) throws Exception { boolean attachflag = false; String contentType = part.getContentType(); if (part.isMimeType("multipart/*")) { Multipart mp = (Multipart) part.getContent(); for (int i = 0; i < mp.getCount(); i++) { BodyPart mpart = mp.getBodyPart(i); String disposition = mpart.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition .equals(Part.INLINE)))) attachflag = true; else if (mpart.isMimeType("multipart/*")) { attachflag = isContainAttach((Part) mpart); } else { String contype = mpart.getContentType(); if (contype.toLowerCase().indexOf("application") != -1) attachflag = true; if (contype.toLowerCase().indexOf("name") != -1) attachflag = true; } } } else if (part.isMimeType("message/rfc822")) { attachflag = isContainAttach((Part) part.getContent()); } return attachflag; } /** * 【保存附件】 */ public String saveAttachMent(Part part) throws Exception { String fileNames = ""; String fileName = ""; if (part.isMimeType("multipart/*")) { Multipart mp = (Multipart) part.getContent(); for (int i = 0; i < mp.getCount(); i++) { BodyPart mpart = mp.getBodyPart(i); String disposition = mpart.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition .equals(Part.INLINE)))) { fileName = mpart.getFileName(); //编码转换 ?gb2312或者?gbk的情况 if (fileName.toLowerCase().indexOf("gb") != -1) { fileName = MimeUtility.decodeText(fileName); } saveFile(fileName, mpart.getInputStream()); } else if (mpart.isMimeType("multipart/*")) { saveAttachMent(mpart); } else { fileName = mpart.getFileName(); if ((fileName != null) && (fileName.toLowerCase().indexOf("gb") != -1)) { fileName = MimeUtility.decodeText(fileName); saveFile(fileName, mpart.getInputStream()); } } fileNames += fileName + ","; } } else if (part.isMimeType("message/rfc822")) { saveAttachMent((Part) part.getContent()); } if(fileNames !=null && !"".equals(fileNames)) { fileNames = fileNames.substring(0,fileNames.length()-1); } return fileNames; } /** * 【真正的保存附件到指定目录里】 */ private void saveFile(String fileName, InputStream in) throws Exception { String osName = System.getProperty("os.name"); String storedir = getSaveAttachPath(); String separator = ""; if (osName == null) osName = ""; if (osName.toLowerCase().indexOf("win") != -1) { separator = "\\"; if (storedir == null || storedir.equals("")) storedir = "c:\\tmp"; } else { separator = "/"; storedir = "/tmp"; } File storefile = new File(storedir + separator + fileName); BufferedOutputStream bos = null; BufferedInputStream bis = null; try { bos = new BufferedOutputStream(new FileOutputStream(storefile)); bis = new BufferedInputStream(in); int c; while ((c = bis.read()) != -1) { bos.write(c); bos.flush(); } } catch (Exception exception) { exception.printStackTrace(); throw new Exception("文件保存失败!"); } finally { bos.close(); bis.close(); } } 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 getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getCopyTo() { return copyTo; } public void setCopyTo(String copyTo) { this.copyTo = copyTo; } public String getFromName() { return fromName; } public void setFromName(String fromName) { this.fromName = fromName; } public boolean isDebug() { return debug; } public void setDebug(boolean debug) { this.debug = debug; } public String getDateformat() { return dateformat; } public void setDateformat(String dateformat) { this.dateformat = dateformat; } public String getSaveAttachPath() { return attachPath; } public void setSaveAttachPath(String saveAttachPath) { this.attachPath = saveAttachPath; } } /** * 邮箱认证类 * @author Administrator * */ class MyAuthenticator extends Authenticator { private String strUser; private String strPwd; public MyAuthenticator(String user, String password) { this.strUser = user; this.strPwd = password; } protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(strUser, strPwd); } }