背景

刚开始计划指定几个同事轮流发送,业务只要不被攻击一般是没有问题的。但是想一想休息日还要处理工作上的事情(非紧急的)就不爽,近几年一直在做前端的事情,后台碰的少,毕竟也接触过,所以决定搞一个定时发送邮件的程序,遂上网查找资料。

邮件类选择

在网上大致上看了下,目前有两种方案:

  1. MimeMessage
        String title = createTitle();
        String text = createText();
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.qq.com");
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        Session session = Session.getDefaultInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                 return new PasswordAuthentication(from, passwd);
                }
            });
        MimeMessage message = new MimeMessage(session);
        try {
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject(title);
            message.setText(text);
            System.out.println(text);
            Transport.send(message);
        } catch(Exception e) {
            e.printStackTrace();
        }
  1. SimpleMail
        mail.setHostName(host);
        mail.setAuthentication(user, passwd);
        mail.setFrom(user);
        mail.setCharset("UTF-8");
        mail.setSubject(title);
        mail.setSSLOnConnect(true);
        mail.setMsg(content);
        mail.addTo(to);
        mail.send();

在本地重构代码并进行了测试,都是正常发送和接收,个人觉得SimpleMail看起来更加简洁,所以邮件类就选它了

定时器

网上搜索一大堆,具体就不一一介绍了,我用的是Quartz
Quartz 设计有三个核心类,分别是

  • Scheduler 调度器
    调度器就相当于一个容器,装载着任务和触发器。该类是一个接口,代表一个 Quartz 的独立运行容器, TriggerJobDetail 可以注册到 Scheduler 中, 两者在 Scheduler 中拥有各自的组及名称, 组及名称是 Scheduler 查找定位容器中某一对象的依据, Trigger 的组及名称必须唯一, JobDetail 的组和名称也必须唯一(但可以和 Trigger 的组和名称相同,因为它们是不同类型的)。Scheduler 定义了多个接口方法, 允许外部通过组及名称访问和控制容器中 TriggerJobDetail
  • Job任务
    定义需要执行的任务。该类是一个接口,只定义一个方法 execute(JobExecutionContext context),在实现类的 execute 方法中编写所需要定时执行的 Job(任务), JobExecutionContext 类提供了调度应用的一些信息。Job 运行时的信息保存在 JobDataMap 实例中
  • Trigger 触发器
    负责设置调度策略。该类是一个接口,描述触发 job 执行的时间触发规则。主要有 SimpleTriggerCronTrigger 这两个子类。当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger 是最适合的选择;而 CronTrigger 则可以通过 Cron 表达式定义出各种复杂时间规则的调度方案:如工作日周一到周五的 15:00~16:00 执行调度等

开发测试

  1. 创建SendMail类,将发送邮件逻辑代码进行封装
public class SendMail implements Job {

    private static String user = "[email protected]";
    private static String passwd = "passwd";//授权码
    private static String to = "[email protected]";
    private static String host = "smtp.qq.com";

    public static void sendMailForSmtp(String title, String content, String[] tos, String[] ccs) throws EmailException {
        SimpleEmail mail = new SimpleEmail();
        // 设置邮箱服务器信息
        mail.setHostName(host);
        // 设置密码验证器passwd为授权码
        mail.setAuthentication(user, passwd);
        // 设置邮件发送者
        mail.setFrom(user);
        // 设置邮件编码
        mail.setCharset("UTF-8");
        // 设置邮件主题
        mail.setSubject(title);
        //SSL方式
        mail.setSSLOnConnect(true);
        // 设置邮件内容
//      mail.setMsg(content);
        // 设置邮件接收者
//      mail.addTo(to);
        mail.addTo(tos);
        mail.addCc(ccs);
        // 发送邮件
        MimeMultipart multipart = new MimeMultipart();
        //邮件正文
        BodyPart contentPart = new MimeBodyPart();
        try {
            contentPart.setContent(content, "text/html;charset=utf-8");
            multipart.addBodyPart(contentPart);
            //邮件附件
            BodyPart attachmentPart = new MimeBodyPart();
            File file = new File("C:\\lutong\\20190918002.log");
            FileDataSource source = new FileDataSource(file);
            attachmentPart.setDataHandler(new DataHandler(source));
            attachmentPart.setFileName(MimeUtility.encodeWord(file.getName()));
            multipart.addBodyPart(attachmentPart);
            mail.setContent(multipart);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        System.out.println(JsonUtil.toJson(mail));
        mail.send();
        System.out.println("mail send success!");
    }
    @Override
    public void execute(JobExecutionContext var1) throws JobExecutionException {
        // TODO Auto-generated method stub
        //多个接收者
        String[] tos = {"[email protected]","[email protected]"};
        //多个抄送者
        String[] ccs = {"[email protected]","[email protected]"};
        try {
            SendMail.sendMailForSmtp("title", "hello <br> ccy", tos, ccs);
        } catch (EmailException e) {
            e.printStackTrace();
        }
    }
}
  1. 创建CronTrigger,定时发送任务
public class CronTrigger {
    public static void main(String[] args){
        //初始化job
        JobDetail job = JobBuilder.newJob(SendMail.class)// 创建 jobDetail 实例,绑定 Job 实现类
                .withIdentity("ccy", "group1")//指明job名称、所在组名称
                .build();
        //定义规则
         Trigger trigger = TriggerBuilder
         .newTrigger()
         .withIdentity("ccy", "group1")//triggel名称、组
         .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))//每隔5s执行
         .build();
        Scheduler scheduler = null;
        try {
            scheduler = new StdSchedulerFactory().getScheduler();
            System.out.println("start job...");
            //把作业和触发器注册到任务调度中
            scheduler.scheduleJob(job, trigger);
            //启动
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

测试结果

后记

技术沟通群欢迎加入

如果对笔者感兴趣也欢迎你加我好友一起讨论技术,夸夸白
本人微信gm4118679254

02-01 06:34