前言
使用对应专栏前一篇文档中的邮箱账号来配置定时任务,实现每天获取一次邮件数据,并把简历同步到系统中。
创建定时任务Bean
eladmin的定时任务类放在eladmin-system中,包名为me.zhengjie.modules.quartz.task,先在这个包中创建一个测试类,仅仅查询并打印下邮箱账号信息:
package me.zhengjie.modules.quartz.task;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.xingchenlie.basedata.service.EmailAccountService;
import me.zhengjie.xingchenlie.basedata.service.dto.EmailAccountDto;
import me.zhengjie.xingchenlie.basedata.service.dto.EmailAccountQueryCriteria;
/**
* 定时获取邮件
*/
@Slf4j
@Async
@Component
public class EmailTask {
@Autowired EmailAccountService emailAccountService;
public void run(){
log.info("进入email定时任务");
List<EmailAccountDto> accounts = emailAccountService.queryAll(new EmailAccountQueryCriteria());
for(EmailAccountDto dto : accounts) {
System.out.println(JSON.toJSON(dto).toString());
}
}
}
其中,注解@Slf4j和@Component需要都有。
配置定时任务
重启后台,然后前端页面左侧目录的系统管理–任务调度中开始配置。
点击添加:
其中,任务名称和任务描述是给自己看的,Bean名称就是创建的类首字母小写,执行方法就是Bean中要调用的方法名称,Cron表达式官方文档有样例参考:
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
创建完成后,点击列表的执行,可以看到控制台打印了run方法中log的内容,表示已经调用成功了。
完善
至此已经实现了定时任务的配置,接下来将对应的任务方法完善,因为简历表还没有创建,此处先提供获取邮件的辅助类。
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.mail.Address;
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.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import com.lootaa.xcl.business.db.EmailAccount;
import com.lootaa.xcl.business.task.vo.EmailVo;
import com.sun.mail.imap.IMAPStore;
public class EmailUtil {
// 如果date为null,查询全部邮件;如果date有值yyyy-MM-dd,查询指定日期邮件
public static List<EmailVo> getEmailList(EmailAccount account, String date, List<String> messageIds) throws Exception {
List<EmailVo> list = new ArrayList<>();
Properties props = System.getProperties();
props.setProperty(account.getHostKey(), account.getHost());
props.setProperty(account.getPortKey(), account.getPort());
props.setProperty(account.getProtocolKey(), account.getProtocol());
props.setProperty("mail.imap.partialfetch", "false");
props.setProperty("mail.imaps.partialfetch", "false");
Session session = Session.getInstance(props);
IMAPStore store = (IMAPStore) session.getStore(account.getProtocol());
store.connect(account.getAccount(), account.getPassword());
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE); // Folder.READ_ONLY:只读权限 Folder.READ_WRITE:可读可写(可以修改邮件的状态)
Message[] messages = folder.getMessages();
int count = messages.length;
for (int i = count - 1; i >= 0; i--) {
// 常规邮件这一行就可以,遇到退信或者类似部分平台发送的邮件会报错javax.mail.MessagingException: Unable to load BODYSTRUCTURE
// 所以需要下面两行处理,复制出来一份后重新赋值
MimeMessage msg2 = (MimeMessage) messages[i];
MimeMessage msg = new MimeMessage(msg2);
EmailVo vo = new EmailVo();
String messageId = msg.getMessageID();
if(messageIds!= null && messageIds.size() > 0 && messageIds.contains(messageId)) {
continue;
}
vo.setMessageId(messageId);
String sendTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(msg.getSentDate());
if(date != null && date.length() > 0) {
if(sendTime.compareTo(date) < 0) {
break;
} else if(!sendTime.startsWith(date)) {
continue;
}
}
System.out.println(i + ":" + sendTime);
vo.setSendTime(sendTime);
vo.setSubject(msg.getSubject());
Address[] froms = msg.getFrom();
if (froms.length > 0) {
InternetAddress address = (InternetAddress) froms[0];
vo.setFromEmail(address.getAddress());
vo.setFromName(address.getPersonal());
}
Address[] addresss = msg.getAllRecipients();
if (addresss != null && addresss.length > 0) {
StringBuffer receiveAddress = new StringBuffer();
for (Address address : addresss) {
InternetAddress internetAddress = (InternetAddress) address;
receiveAddress.append(internetAddress.toUnicodeString()).append(",");
}
receiveAddress.deleteCharAt(receiveAddress.length() - 1);
vo.setReceive(receiveAddress.toString());
}
vo.setRead(msg.getFlags().contains(Flags.Flag.SEEN));
boolean isContainerAttachment = isContainAttachment(msg);
vo.setContainerAttachment(isContainerAttachment);
StringBuffer content = new StringBuffer(100);
getMailTextContent(msg, content);
vo.setContent(content.toString());
if (isContainerAttachment) {
StringBuffer fileName = new StringBuffer(100);
InputStream is = getAttachment(msg, fileName);
System.out.println(fileName);
byte[] byteBuffer = null;
ByteArrayOutputStream outByte = new ByteArrayOutputStream();
byte[] tmpByte = new byte[2048];
int len = 0;
while ((len = is.read(tmpByte)) != -1) {
outByte.write(tmpByte, 0, len);
}
byteBuffer = outByte.toByteArray();
vo.setAttachmentFile(byteBuffer);
vo.setFileName(fileName.toString());
}
list.add(vo);
// if(list.size() > 100) {
// folder.close(true);
// store.close();
// return list;
// }
}
folder.close(true);
store.close();
return list;
}
private static InputStream getAttachment(Part part, StringBuffer fileName)
throws UnsupportedEncodingException, MessagingException, FileNotFoundException, IOException {
if (part.isMimeType("multipart/*")) {
Multipart multipart = (Multipart) part.getContent();
int partCount = multipart.getCount();
for (int i = 1; i < partCount; i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if(bodyPart == null) {
continue;
}
String disp = bodyPart.getDisposition();
if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
InputStream is = bodyPart.getInputStream();
fileName = fileName.append(MimeUtility.decodeText(bodyPart.getFileName()));
return is;
} else if (bodyPart.isMimeType("multipart/*")) {
return getAttachment(bodyPart, fileName);
} else {
String contentType = bodyPart.getContentType();
if (contentType.indexOf("name") != -1 || contentType.indexOf("application") != -1) {
InputStream is = bodyPart.getInputStream();
fileName = fileName.append(MimeUtility.decodeText(bodyPart.getFileName()));
return is;
}
}
}
} else if (part.isMimeType("message/rfc822")) {
return getAttachment((Part) part.getContent(), fileName);
}
return null;
}
private static void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException {
boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
if (part.isMimeType("text/*") && !isContainTextAttach) {
content.append(part.getContent().toString());
} else if (part.isMimeType("message/rfc822")) {
getMailTextContent((Part) part.getContent(), content);
} else if (part.isMimeType("multipart/*")) {
Multipart multipart = (Multipart) part.getContent();
int partCount = multipart.getCount();
for (int i = 0; i < partCount; i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
getMailTextContent(bodyPart, content);
}
}
}
/**
* 判断邮件中是否包含附件
*/
private static boolean isContainAttachment(Part part) throws MessagingException, IOException {
boolean flag = false;
if (part.isMimeType("multipart/*")) {
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("multipart/*")) {
flag = isContainAttachment(bodyPart);
} else {
String contentType = bodyPart.getContentType();
if (contentType.indexOf("application") != -1) {
flag = true;
}
if (contentType.indexOf("name") != -1) {
flag = true;
}
}
if (flag)
break;
}
} else if (part.isMimeType("message/rfc822")) {
flag = isContainAttachment((Part) part.getContent());
}
return flag;
}
}