spring boot定时任务接收邮件并且存储附件的方法讲解

在spring boot中写定时任务很简单,两个注解就可以实现。在启动类中加@EnableScheduling ,然后在你需要定时的方法上加上@Scheduled(cron="0 10 8 * * ?");括号内为cron表达式。如下图:

接收邮件及其判断是否有附件,并且存储附件。

public class TimerTaskServiceImpl implements TimerTaskService {
  @Autowired
  private ParseTxtServiceImpl parseTxtService;
  /**
   * 接收邮件
   */
  @Override
  @Scheduled(cron="0 10 8 * * ?")
  public void timerTaskInfo(){
    //邮件配置信息
    String host=Constants.MAIL_HOST;
    String userName=Constants.MAIL_USER_NAME;
    String passWord=Constants.MAIL_PASS_WORD;
    //邮件配置类
    Properties properties=new Properties();
    //邮件配置缓存
    Session session=Session.getDefaultInstance(properties);
    session.setDebug(true);
    String fileName=null;
    try {
      //邮件服务器的类型
      Store store = session.getStore("pop3");
      //连接邮箱服务器
      store.connect(host,userName,passWord);
      // 获得用户的邮件帐户
      Folder folder=store.getFolder("INBOX");
      if (folder == null) {
        logger.info("获取邮箱文件信息为空");
      }
      // 设置对邮件帐户的访问权限可以读写
      folder.open(Folder.READ_WRITE);
      Calendar calendar=Calendar.getInstance();
      calendar.add(Calendar.DATE,-1);
      Date mondayDate = calendar.getTime();
      SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.GT, mondayDate);
      SearchTerm address=new SubjectTerm( "MU Report");
      SearchTerm comparisonAndTerm = new AndTerm(address, comparisonTermLe);
      Message[] messages = folder.search(comparisonAndTerm);
      for(int i = 0 ; i < messages.length ; i++){
        MimeMessage msg = (MimeMessage) messages[i];
        //判断是否有附件
        boolean isContainerAttachment = isContainAttachment(msg);
        if (isContainerAttachment) {
          //保存附件
          fileName=saveAttachment(msg,Constants.STORAGE_FILE);
          //保存接收到的邮件并且收件箱删除邮件
         msg.setFlag(Flags.Flag.DELETED, true);
        }
        if(!isContainerAttachment) {
          continue;
        }
      }
      folder.close(true);
      store.close();
      parseTxtService.readTxt(fileName);
    }catch (NoSuchProviderException e){
      loggerError.error("接收邮箱信息异常:{}",e);
    }catch (MessagingException e){
      loggerError.error("连接邮箱服务器信息异常:{}",e);
    }catch (IOException e){
      loggerError.error("接收邮箱信息解析异常:{}",e);
    }catch (IllegalStateException e){
      loggerError.error("接收邮箱信息为空:{}",e);
    }
  }
  /**
   * 判断邮件中是否包含附件
   * @return 邮件中存在附件返回true,不存在返回false
   * @throws MessagingException
   * @throws IOException
   */
  public static boolean isContainAttachment(Part part) throws MessagingException, IOException {
    boolean flag = false;
    if (part.isMimeType(Constants.MULTI_PART)) {
      MimeMultipart multipart = (MimeMultipart) part.getContent();
      int partCount = multipart.getCount();
      for (int i = 0; i < partCount; i++) {
        BodyPart bodyPart = multipart.getBodyPart(i);
        String disp = bodyPart.getDisposition();
        if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) ||
            disp.equalsIgnoreCase(Part.INLINE))) {
          flag = true;
        } else if (bodyPart.isMimeType(Constants.MULTI_PART)) {
          flag = isContainAttachment(bodyPart);
        } else {
          String contentType = bodyPart.getContentType();
          if (contentType.indexOf(Constants.APPLICATION_CONTEXT) != -1) {
            flag = true;
          }
          if (contentType.indexOf(Constants.NAME_CONTEXT) != -1) {
            flag = true;
          }
        }
        if (flag){
          break;
        }
      }
    } else if (part.isMimeType(Constants.MESSAGE_RFC)) {
      flag = isContainAttachment((Part)part.getContent());
    }
    return flag;
  }
  /**
   * 保存附件
   * @param part 邮件中多个组合体中的其中一个组合体
   * @param destDir 附件保存目录
   * @throws UnsupportedEncodingException
   * @throws MessagingException
   * @throws FileNotFoundException
   * @throws IOException
   */
  public String saveAttachment(Part part, String destDir) throws UnsupportedEncodingException,
      MessagingException, FileNotFoundException, IOException {
    String fileName=null;
    if (part.isMimeType(Constants.MULTI_PART)) {
      Multipart multipart = (Multipart) part.getContent();  //复杂体邮件
      //复杂体邮件包含多个邮件体
      int partCount = multipart.getCount();
      for (int i = 0; i < partCount; i++) {
        //获得复杂体邮件中其中一个邮件体
        BodyPart bodyPart = multipart.getBodyPart(i);
        //某一个邮件体也有可能是由多个邮件体组成的复杂体
        String disp = bodyPart.getDisposition();
        if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase
            (Part.INLINE))) {
          InputStream is = bodyPart.getInputStream();
          saveFile(is, destDir, decodeText(bodyPart.getFileName()));
          fileName=decodeText(bodyPart.getFileName());
        } else if (bodyPart.isMimeType(Constants.MULTI_PART)) {
          saveAttachment(bodyPart,destDir);
        } else {
          String contentType = bodyPart.getContentType();
          if (contentType.indexOf(Constants.NAME_CONTEXT) != -1 || contentType.indexOf
              (Constants.APPLICATION_CONTEXT) != -1) {
            saveFile(bodyPart.getInputStream(), destDir, decodeText(bodyPart.getFileName()));
            fileName=decodeText(bodyPart.getFileName());
          }
        }
      }
    } else if (part.isMimeType(Constants.MESSAGE_RFC)) {
      saveAttachment((Part) part.getContent(),destDir);
    }
    return fileName;
  }
  /**
   * 读取输入流中的数据保存至指定目录
   * @param is 输入流
   * @param fileName 文件名
   * @param destDir 文件存储目录
   * @throws FileNotFoundException
   * @throws IOException
   */
  private void saveFile(InputStream is, String destDir, String fileName)
      throws FileNotFoundException, IOException {
    BufferedInputStream bis = new BufferedInputStream(is);
    if(fileName.contains(Constants.TXT_SUFIXX)) {
      BufferedOutputStream bos = new BufferedOutputStream(
          new FileOutputStream(new File(destDir + fileName)));
      int len = -1;
      while ((len = bis.read()) != -1) {
        bos.write(len);
        bos.flush();
      }
      bos.close();
      bis.close();
    }
  }
}

其中查询邮件的条件,你可以自行更改。

接收邮件服务器的配置

可能出现的bug

说说用模板可能会碰到的bug。

怎么回事呢?代码写了,看了好几遍也没错,就是运行就报错,在网上看了别人的代码拿过来还是报错,报错如下:

这个错误大概意思就是我的模板的html中每个标签都要是闭标签,要这种类型的<a></a>,假如是<img xxx>这种标签就会报错。

如下所示,最坑的方法就是修改的,而且以后html的标签都要是一对一对的,坑啊、

后来有找了很多资料,原来发现是这里,themeleaf默认应该是2.xx版本,这个版本解析标签都要是一对一对的,到了3.xx之后,就不需要这么麻烦了!

都是版本问题

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Springboot项目打war包docker包找不到resource下静态资源的解决方案

    前一段时间遇到一个问题,是关于读取项目中文件资源的问题.我是一个maven工程 我把一张照片放到resource下面,然后在本地读取的时候可以读取到,但是一旦打成WAR包以后就总是包找不到文件资源错误.我的war包是springboot打的war包,是内嵌的tomcat所以不解压,然后系统去找路径的时候会发现是个WAR包,而图片在WAR包内,所以找不到. 为了解决这个问题,我走了好多弯路,一直在路径上花费时间. 一开始使用修改配置文件的方式: # 配置静态资源访问前缀 spring.mvc.st

  • Spring自带的校验框架Validation的使用实例

    1.首先来一个项目结构图以及所需jar包 可以看到,没有添加除了日志和jstl相关的jar包外,没有其他spring以外的第三方jar包(即使用的是spring自带的校验框架). 2.从前台页面开始,首先是接收用户信息的表单loginForm.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@

  • 详解Spring框架下向异步线程传递HttpServletRequest参数的坑

    在spring的注解 @RequestMapping 之下可以直接获取 HttpServletRequest 来获得诸如request header等重要的请求信息: @Slf4j @RestController @RequestMapping("/test") public class TestController { private static final String HEADER = "app-version"; @RequestMapping(value

  • spring @Transactional 无效的解决方案

    关于@Transactional注解 一般都认为要注意以下三点 1 .在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上 . 2 . @Transactional 注解只能应用到 public 可见度的方法上 . 如果你在 protected.private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展

  • Spring 中优雅的获取泛型信息的方法

    简介 Spring 源码是个大宝库,我们能遇到的大部分工具在源码里都能找到,所以笔者开源的 mica 完全基于 Spring 进行基础增强,不重复造轮子.今天我要分享的是在 Spring 中优雅的获取泛型. 获取泛型 自己解析 我们之前的处理方式,代码来源 vjtools(江南白衣). /** * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. * * 注意泛型必须定义在父类处. 这是唯一可以通过反射从泛型获得Class实例的地方. * * 如无法找到, 返回Object.clas

  • activemq整合springboot使用方法(个人微信小程序用)

    主题 ActiveMQ Spring Boot 小程序开发 1.引入依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath /> <!-- lookup

  • 详解spring-boot下如何满足多生产环境中个性化定制功能

    在项目的开发中,我们很难做到开发一套标准的流程来解决所有客户的需求.比如,我们当前的计量项目,分别运行于赤峰市和河北省.虽然两个区域处理的业务相同,但是对细节的实现要求却不同.前面也学习过计量检定软件,其为了解决各个定制者使用的功能需求,最后采取的方案是:将基础项目复制多份,进而满足不同的客户需求.优点当然是有的,但比起缺点来,优点便不值一提.缺点很明显,总结为一句话就是:项目变得难以维护.所以,当前让我们看到的就是,几个开发人员,每天处于解决问题当中.本文将给出一种方案,来有效的规避上述问题.

  • Springboot-dubbo-fescar 阿里分布式事务的实现方法

    大家可以自行百度下阿里分布式事务,在这里我就不啰嗦了.下面是阿里分布式事务开源框架的一些资料,本文是springboot+dubbo+fescar的集成. 快速开始 https://github.com/alibaba/fescar/wiki/Quick-Start GIT地址 https://github.com/alibaba/fescar 1.sql CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `br

  • spring中通过ApplicationContext getBean获取注入对象的方法实例

    用SpringContextUtil实现ApplicationContextAware package util; import java.util.Locale; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; pub

  • Spring通过ApplicationContext主动获取bean的方法讲解

    问题1: 有个异步线程Runnable里面需要用到dao,无法通过AutoWired和compoment注解传递进来. 于是希望通过Spring context主动去获取bean. 问题2: getBean(name)获取失败. 解决: 默认的dao的name=类名(首字母小写) 例如: 接口名称:TemplateDao 则getName("templateDao")即可 通用的SpringContextUtil获取Bean 1.实现ApplicationContextAware接口

随机推荐