package red.sea.email.common; import java.io.File; import java.security.GeneralSecurityException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.mail.AuthenticationFailedException; import javax.mail.Flags; import javax.mail.Flags.Flag; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.Part; import javax.mail.Session; import javax.mail.Store; import javax.mail.Transport; import javax.mail.internet.MimeMessage; import javax.mail.search.AndTerm; import javax.mail.search.ComparisonTerm; import javax.mail.search.FlagTerm; import javax.mail.search.SearchTerm; import javax.mail.search.SentDateTerm; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.sun.mail.imap.IMAPFolder; import com.sun.mail.pop3.POP3Folder; import com.sun.mail.smtp.SMTPMessage; import com.sun.mail.util.MailSSLSocketFactory; import red.sea.commons.util.BeanTool; import red.sea.commons.util.FileUtil; import red.sea.email.data.MailAccount; import red.sea.email.data.MailOwner; import red.sea.email.service.IMailListService; import red.sea.email.service.IMailOwnerService; import red.sea.email.service.impl.MailListServiceImpl; import red.sea.email.view.MailListView; import red.sea.email.view.MailOwnerView; import red.sea.platform.fjk.service.IPtFjkService; import red.sea.platform.fjk.view.PtFjkView; /** * 获取邮件工具类 * 1.通过邮箱账户表获取当前用户关联邮箱 * 2.通过邮箱账户协议获取邮箱登录 * 3.读取邮箱详细内容 * @author redsea * */ public class MailReciveTool { private static Log log = LogFactory.getLog(MailReciveTool.class); //时间格式化 private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 邮件帐户 private MailAccount mailAccount = null; //是否接收全部邮件 public boolean isRecieveAllMail = true; // private Store store = null; // private Folder folder = null; //自定义构造方法 public MailReciveTool(MailAccount mailAccount) { this.mailAccount = mailAccount; } /** * @Description 验证发送服务 * @author zhujq * @return */ public String checkSendServer() { Properties properties = new Properties(); properties.setProperty("mail.smtp.host", mailAccount.getSmtpServer()); properties.put("mail.smtp.auth", "true"); // 允许smtp校验 //如果启用ssl邮箱发送服务 if (mailAccount.getIsSendSsl().equals("1")) { properties.setProperty("mail.smtp.port", mailAccount.getSendPort()); MailSSLSocketFactory sf = null; try { sf = new MailSSLSocketFactory(); } catch(GeneralSecurityException e) { // logger.fatal("error", e); } sf.setTrustAllHosts(true); properties.put("mail.smtp.ssl.enable", "true"); //关键 //properties.put("mail.smtp.starttls.enable","true"); properties.put("mail.smtp.ssl.socketFactory", sf); properties.put("mail.smtp.socketFactory.fallback", "false"); properties.put("mail.smtp.socketFactory.port", mailAccount.getSendPort()); } Session session = Session.getInstance(properties, null); Transport transport = null; try { transport = session.getTransport("smtp"); transport.connect(mailAccount.getSmtpServer(), mailAccount.getEmail(), mailAccount.getPwd()); } catch(NoSuchProviderException e) { e.printStackTrace(); return "错误代码005(" + mailAccount.getEmail() + "):发送服务器不支持此协议"; } catch(AuthenticationFailedException e) { e.printStackTrace(); return "错误代码006(" + mailAccount.getEmail() + "):发送服务验证失败,1.邮箱用户名或密码错误;2.确认邮箱服务器是否需要加密"; } catch(MessagingException e) { e.printStackTrace(); return "错误代码007(" + mailAccount.getEmail() + "):发送服务器不支持此协议"; } catch(Exception e) { e.printStackTrace(); return "错误代码008(" + mailAccount.getEmail() + "):其它未知异常,发送服务验证失败"; } finally { if (transport != null) { try { transport.close(); } catch(Exception e) { e.printStackTrace(); } } } return ""; } /** * 验证接收服务 * 连接邮件服务器 0:成功 1:由于邮件服务器错误接收邮件失败! 2:由于用户名或密码错误接收邮件失败! * 3:在连接邮件服务器过程中出错,收邮件失败! 4:由于不明错误接收邮件失败! 5:没有为该用户配置邮件账户! * 6:在接收邮件过程中处理邮件失败,请重试! * * @return */ public String checkMailServer() { if (mailAccount == null) return "没有为该用户配置邮件账户!"; // 如果文件夹没有被打开 if (folder == null || !folder.isOpen()) { Properties props = new Properties(); //默认端口,pop3端口 String port = mailAccount.getRePort(); //默认pop3服务 String Server = mailAccount.getPop3Addr(); //用户、密码 String mailUserId = mailAccount.getEmail(); String mailPassword = mailAccount.getPwd(); //协议类型 String protocolType = "pop3"; final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; //是否开启SSL服务,1开启 if (mailAccount.getIsReSsl().equals("1")) { //imap服务 if (mailAccount.getRevProtocol().equals("2")) { Server = mailAccount.getPop3Addr(); //port="993"; protocolType = "imap"; // IMAP provider props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY); props.setProperty("mail.imap.socketFactory.fallback", "false"); props.setProperty("mail.imap.port", port); props.setProperty("mail.imap.socketFactory.port", port); props.setProperty("mail.imap.partialfetch", "false"); } else { //pop3服务 props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY); props.setProperty("mail.pop3.socketFactory.fallback", "false"); props.setProperty("mail.pop3.port", port); props.setProperty("mail.pop3.socketFactory.port", port); props.setProperty("mail.pop3.partialfetch", "false"); } } //properties.put("mail.pop3.host", Server); Session session = Session.getInstance(props); try { // 如果还没有连接上邮件服务器 if (store == null || !store.isConnected()) { store = session.getStore(protocolType); store.connect(Server, mailUserId, mailPassword); } folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); if (folder != null) // folder.close(true); if (store != null) // store.close(); return ""; } catch(NoSuchProviderException e) { e.printStackTrace(); return "错误代码001(" + mailAccount.getEmail() + "):服务器不支持此协议"; } catch(AuthenticationFailedException e) { e.printStackTrace(); return "错误代码002(" + mailAccount.getEmail() + "):1.邮箱用户名或密码错误;2.确认邮箱服务器是否需要加密"; } catch(MessagingException e) { e.printStackTrace(); return "错误代码003(" + mailAccount.getEmail() + "):服务器不支持此协议"; } catch(Exception e) { e.printStackTrace(); return "错误代码004(" + mailAccount.getEmail() + "):其它未知异常"; } } return ""; } /** * 连接邮件服务器 0:成功 1:由于邮件服务器错误接收邮件失败! 2:由于用户名或密码错误接收邮件失败! * 3:在连接邮件服务器过程中出错,收邮件失败! 4:由于不明错误接收邮件失败! 5:没有为该用户配置邮件账户! * 6:在接收邮件过程中处理邮件失败,请重试! * * @return */ public String connectMailServer() { if (mailAccount == null) return "没有为该用户配置邮件账户!"; // 如果文件夹没有被打开 if (folder == null || !folder.isOpen()) { Properties props = new Properties(); //默认端口,pop3端口 String port = mailAccount.getRePort(); //默认pop3服务 String Server = mailAccount.getPop3Addr(); //用户、密码 String mailUserId = mailAccount.getEmail(); String mailPassword = mailAccount.getPwd(); //协议类型 String protocolType = "pop3"; final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; //是否开启SSL服务,1开启 if (mailAccount.getIsReSsl().equals("1")) { //imap服务 if (mailAccount.getRevProtocol().equals("2")) { Server = mailAccount.getPop3Addr(); //port="993"; protocolType = "imap"; // IMAP provider props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY); props.setProperty("mail.imap.socketFactory.fallback", "false"); props.setProperty("mail.imap.port", port); props.setProperty("mail.imap.socketFactory.port", port); props.setProperty("mail.imap.partialfetch", "false"); } else { //pop3服务 props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY); props.setProperty("mail.pop3.socketFactory.fallback", "false"); props.setProperty("mail.pop3.port", port); props.setProperty("mail.pop3.socketFactory.port", port); props.setProperty("mail.pop3.partialfetch", "false"); } } //properties.put("mail.pop3.host", Server); Session session = Session.getInstance(props); try { // 如果还没有连接上邮件服务器 if (store == null || !store.isConnected()) { store = session.getStore(protocolType); store.connect(Server, mailUserId, mailPassword); } folder = store.getFolder("INBOX"); return ""; } catch(NoSuchProviderException e) { e.printStackTrace(); return "错误代码001(" + mailAccount.getEmail() + "):服务器不支持此协议"; } catch(AuthenticationFailedException e) { e.printStackTrace(); return "错误代码002(" + mailAccount.getEmail() + "):1.邮箱用户名或密码错误;2.确认邮箱服务器是否需要加密"; } catch(MessagingException e) { e.printStackTrace(); return "错误代码003(" + mailAccount.getEmail() + "):服务器不支持此协议"; } catch(Exception e) { e.printStackTrace(); return "错误代码004(" + mailAccount.getEmail() + "):其它未知异常"; } } return ""; } /** * 邮箱收取 * 1.获取数据库中第三方邮件配置 * 2.获取当前邮箱基本信息保存到数据库 * @param host 主机 * @param username 邮箱账户 * @param password 邮箱密码 * @param port 端口 * @return 邮箱对象 * @throws MessagingException */ public Map < Object, Object > receiveMail() { Map < Object, Object > mps = new HashMap < Object, Object > (); //邮件列表 List < MailListView > omrList = new ArrayList < MailListView > (); //邮箱服务器 String isConn = connectMailServer(); if (isConn == "") { try { folder.open(Folder.READ_ONLY); //获取已读,未读,全部邮件 System.out.println("新邮件个数:" + folder.getNewMessageCount()); System.out.println("未读邮件个数:" + folder.getUnreadMessageCount()); System.out.println("所有邮件个数:" + folder.getMessageCount()); } catch(NoSuchProviderException e1) { e1.printStackTrace(); } catch(MessagingException e) { e.printStackTrace(); } try { //保存实体对象 omrList = getMailInfo(); } finally { System.out.println("关闭"); /*try { // 释放资源 // if (folder != null) //folder.close(true); // if (store != null) //store.close(); } catch (MessagingException e) { e.printStackTrace(); } */ } //设置结果 mps.put("flag", true); mps.put("results", omrList); } else { mps.put("flag", false); mps.put("results", isConn); } return mps; } /** * 1.获取邮件uid * 2.如果数据库存在邮件则不重复添加。 * 3.添加新邮件到数据库并设置邮件为未读。 * Flag 类型列举如下 * Flags.Flag.ANSWERED 邮件回复标记,标识邮件是否已回复。 * Flags.Flag.DELETED 邮件删除标记,标识邮件是否需要删除。 * Flags.Flag.DRAFT 草稿邮件标记,标识邮件是否为草稿。 * Flags.Flag.FLAGGED 表示邮件是否为回收站中的邮件。 * Flags.Flag.RECENT 新邮件标记,表示邮件是否为新邮件。 * Flags.Flag.SEEN 邮件阅读标记,标识邮件是否已被阅读。 * Flags.Flag.USER 底层系统是否支持用户自定义标记,只读。 * * @return * @throws MessagingException */ public List < MailListView > getMailInfo() { //邮件数据信息 List < MailListView > omrList = new ArrayList < MailListView > (); //邮件 Message[] messages = null; //建立搜索条件FlagTerm,这里FlagTerm继承自SearchTerm,也就是说除了获取未读邮 //件的条件还有很多其他条件同样继承了SearchTerm的条件类,像根据发件人,主题搜索等, // 还有复杂的逻辑搜索类似: // 收取未读邮件。 FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false); //false代表未读,true代表已读 //按时间收取 获取7天前时间 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -7); Date mondayDate = calendar.getTime(); // System.out.println(mondayDate); SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GE, mondayDate); SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, new Date()); SearchTerm time = new AndTerm(comparisonTermGe, comparisonTermLe); //不接收 在controller已做了判断 int reviceDay = mailAccount.getReceiveDays(); //-1:不接收,0:全部,7:7天 //pop3 if (folder instanceof POP3Folder) { POP3Folder inbox = (POP3Folder) folder; if (reviceDay == 0) { //pop3 取得全部邮件再做分析 try { messages = inbox.getMessages(); } catch(MessagingException e) { // 获取信息失败 log.debug("获取message失败"); e.printStackTrace(); } } else { //收取7天内的邮件 try { messages = inbox.search(time); } catch(MessagingException e) { log.debug("获取message2失败"); e.printStackTrace(); } } log.debug("POP3Folder共收到" + messages.length + "封邮件"); //imap } else if (folder instanceof IMAPFolder) { IMAPFolder inbox = (IMAPFolder) folder; if (reviceDay == 0) { //第一次收取全部邮件,包括已读、未读 try { messages = inbox.getMessages(); } catch(MessagingException e) { log.debug("第一次读取邮件message失败"); e.printStackTrace(); } } else { //收取7天内未读邮件 try { messages = inbox.search(time); } catch(MessagingException e) { log.debug("读取7天内邮件message失败"); e.printStackTrace(); } } log.debug("IMAPFolder共收到" + messages.length + "封邮件"); } IMailListService mailListService = (IMailListService) BeanTool.getBean("mailListService"); //先取得数据的邮件 Map < Object, Object > map = mailListService.getMailListByEmail(mailAccount.getEmail()); //循环总个数邮件。 int _totals = 0; int _count = 0; if (messages != null && messages.length > 0) { //总邮件数 _totals = messages.length; //设置邮件总个数 MailListServiceImpl.mailMaps.put("total", _totals); for (int i = 0; i < messages.length; i++) { log.debug("当前收取第" + (i + 1) + "封邮件"); //当前收取邮件 _count = i + 1; Map < Object, Object > objs = new HashMap < Object, Object > (); objs.put("total", _totals); objs.put("count", _count); MailListServiceImpl.mailMaps.put(mailAccount.getOperator(), objs); MimeMessage mimeMessage = (MimeMessage) messages[i]; String mailId = null; try { //取得邮件ID mailId = mimeMessage.getMessageID(); if (mailId == null) { continue; } mailId = mailId.toString(); } catch(MessagingException e1) { log.error("获取邮件ID失败"); e1.printStackTrace(); } //判断mailId是否已存在(存在表示该数据已经保存过了) if (!map.containsKey(mailId)) { //保存接收的邮件 MailListView oa; try { oa = getBaseMailInfo(mimeMessage, mimeMessage.getMessageID() + "", mimeMessage.getSize()); if (oa != null) { omrList.add(oa); } } catch(MessagingException e) { //e.printStackTrace(); log.error("捕获处理异常MessagingException,继续执行.."); continue; } catch(Exception e) { //e.printStackTrace(); log.error("捕获处理异常Exception,继续执行.."); continue; } //否则只插入MAIL_OWNER(邮件拥有者)的数据 } else { try { String mId = (String) map.get(mailId); //得到邮件主键ID String email = mailAccount.getEmail(); IMailOwnerService mailOwnerService = (IMailOwnerService) BeanTool.getBean("mailOwnerService"); List < MailOwner > list = mailOwnerService.queryListByCondition(" and ACCOUNT='" + email + "' and M_ID='" + mId + " '"); if (list.size() == 0) { //如果没有时才插入 log.debug("邮件" + mId + "已存在----只执行插入拥有者表数据"); BaseReviceMail re = new BaseReviceMail((MimeMessage) mimeMessage); String reciveType = "1"; //收件状态 1 : 收件, 2 : 抄送, 3 : 密抄 //String isTo=re.getMailAddress("to");//是否是收件 String isCc = re.getMailAddress("cc"); String isBcc = re.getMailAddress("bcc"); //是否是密抄 if (isCc != null && !isCc.equals("") && isCc.indexOf(email) != -1) { reciveType = "2"; //收件状态 1 : 收件, 2 : 抄送, 3 : 密抄 } else if (isBcc != null && !isBcc.equals("") && isBcc.indexOf(email) != -1) { reciveType = "3"; //收件状态 1 : 收件, 2 : 抄送, 3 : 密抄 } mailOwnerService.insertOwner(reciveType, mId, mailAccount); } // if(list.size()==0){//如果没有时才插入 } catch(Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //else } //for循环,读取邮件 //设置为已读取。 //inbox.setFlags(messages, new Flags(Flags.Flag.SEEN),true); } return omrList; } /*** * 获取邮件信息并保存到模型 * @param message 邮件信息 * @param uid 邮件id * @throws Exception */ private MailListView getBaseMailInfo(Message message, String uid, int size) throws Exception { //邮件接收 BaseReviceMail re = new BaseReviceMail((MimeMessage) message); //清空附件 re.fkjList.clear(); //OaMailResource MailListView or = new MailListView(); //1.判断当前uid的邮件id是否存在数据库表 //主题 or.setMTitle(re.getSubject().toString()); //发送时间 or.setSendTime(re.getSentDate()); //是否需要回复:false不需要;true需要 //or.setIsReturnReceipt(re.getReplySign()==false?"0":"1"); //邮件类型,收件 or.setMType("2"); //是否已读,0未读,1已读 //or.setExt1(re.isNew()==false?"0":"1"); //是否包含附件 //or.setIsFjk(re.isContainAttach((Part) message[i])==false?"0":"1"); //发件人地址 or.setMSender(re.getFrom()); or.setMSenderName(re.getFromName()); String to = re.getMailAddress("TO"); String cc = re.getMailAddress("CC"); String bcc = re.getMailAddress("BCC"); /*//收件人 or.setResAllTo(to); //抄送 or.setResAllCc(cc); //密送 or.setResAllBcc(bcc);*/ //收件人email or.setMRev(to); //抄送email or.setMCc(cc); //密送email or.setMBcc(bcc); //收件人名称 or.setMRevName(re.getMailName("TO")); //抄送人名称 or.setMCcName(re.getMailName("CC")); //密抄人名称 or.setMBccName(re.getMailName("BCC")); //邮件内容 re.getMailContent((Part) message); or.setMContent(re.getBodyText()); //邮件uid(服务器上的uid) or.setMailId(uid); //String mid = POP3Folder.getUID(message[i]); //邮件附件大小 //or.setMailSize(size/1024); //判断是否存在附件 boolean has = re.isContainAttach((Part) message); or.setHasFjk(has == true ? "1": "0"); //是否新邮件,0不是 1 是。 //or.setExt3(1); //此处保存附件 //FileUtil.getPathUrl() re.setAttachPath(FileUtil.getRealpath()); if (has) { re.saveAttachMent((Part) message, uid); } or.setImpLevel("1"); //1:一般邮件,2:重要邮件,3:非常重要 or.setMType("2"); //1:内部邮件,2:外部邮件 or.setInUse("1"); //使用标志 1:使用中,0:停用 or.setCreateTime(new Date()); or.setCreator(mailAccount.getCreator()); or.setCreatorId(mailAccount.getCreatorId()); or.setOperateTime(new Date()); or.setOperator(mailAccount.getOperator()); or.setOperatorId(mailAccount.getOperatorId()); or.setBelongUnitOrgName(mailAccount.getBelongUnitOrgName()); or.setBelongUnitStruId(mailAccount.getBelongUnitStruId()); or.setIsPc(mailAccount.getChar4()); //邮件标识 1:PC端,2:手机端 or.setRootId(mailAccount.getRootId()); //获取附件 or.setFjList(re.getFkjList()); //获取一封,插入一封到数据库。 IMailListService mailListService = (IMailListService) BeanTool.getBean("mailListService"); mailListService.insertReciveMailList(or, mailAccount); //insertMailList(or); return or; } /** * 判断邮件数量是否一致 * @param count * @return */ public boolean getMailCount(int count) { boolean isrecieve = true; /*IOaMailResourceService oaMailResourceService = (IOaMailResourceService) BeanTool.getBean( "oaMailResourceService" ); List<OaMailResource> mailList=oaMailResourceService. queryListByCondition(String.format(" and account_id='%s'",mailAccount.getAId())); //如果相等则不收取 if(mailList!=null){ if(mailList.size()==count){ isrecieve=false; } }*/ return isrecieve; } /** * 验证当前邮件是否存在用户表OaMailResource * @param uid * @return */ private boolean isExist(String uid, String accountId) { /*IOaMailResourceService oaMailResourceService = (IOaMailResourceService) BeanTool.getBean( "oaMailResourceService" ); List<OaMailResource> mailList=oaMailResourceService.queryListByCondition(String.format(" and mail_id='%s' and account_id='%s'",uid,accountId)); if(mailList==null) return false; return mailList.size()>0;*/ return false; } /** * 是否在7天之内 * @param date * @return * @throws ParseException */ private boolean isInSenven(Date mailDate) { //获取当前服务器时间,计算出7天之前日期 Calendar c = Calendar.getInstance(); c.add(Calendar.DATE, -7); Date monday = c.getTime(); //当前时间日期是否在7天之内 Long nowDate = monday.getTime(); Long mailDates = mailDate.getTime(); // System.out.println(nowDate+"-"+mailDates); if (mailDates < nowDate) { return false; } return true; } /** * 是否在上次收件之后 * @param mailDate * @param loadDate * @return * @throws ParseException */ public boolean compareDate(Date mailDate, Date loadDate) { boolean flag = false; try { // Date loadDates = df.parse(loadDate); if (mailDate.getTime() > loadDate.getTime()) { flag = true; } } catch(Exception exception) { exception.printStackTrace(); } return flag; } /*** * 判断邮件已读/未读。 * @param message * @return * @throws MessagingException */ private boolean isRead(Message message) throws MessagingException { Flag[] flags = message.getFlags().getSystemFlags(); for (Flag f: flags) { if (f.equals(Flag.SEEN)) return true; } return false; } } ----------------------------------------------------定时接收类---------------------------------------- package red.sea.email.common; import Java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import red.sea.commons.util.BeanTool; import red.sea.mail.data.OaMailAccount; import red.sea.mail.service.IOaMailAccountService; import red.sea.mail.service.IOaMailResourceService; /*** * 定时接收邮件。 * @author honghai * */ public class MailReciveSchedule implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { Timer timer = new Timer(); System.out.println("第一次进入到contextInitialized"); //final MailInfoService service = SpringContextUtil.getBean("mailInfoService");//(MailInfoService)context.getBean("mailInfoService"); timer.schedule(new TimerTask() { //设置任务定时器,每隔15分钟读取一次。 //IOaMailAccountService oaMailAccountService =(IOaMailAccountService) // BeanTool.getBean( "oaMailAccountService" ); //次数 int count = 0;@Override public void run() { IOaMailResourceService oaMailResourceService = (IOaMailResourceService) BeanTool.getBean("oaMailResourceService"); count++; System.out.println("启动定时接收邮件服务,第" + count + "次。"); System.out.println("收取中。。。"); oaMailResourceService.updateAutoReceiveMail(); System.out.println("收取结束。。。"); System.out.println("结束定时接收邮件服务"); } }, 1000 * 60 * 1, 1000 * 60 * 1); //5分钟之后,每隔15分组读取一次。 //查询全部 } @Override public void contextDestroyed(ServletContextEvent sce) { } }