java监听邮箱并读取邮箱、邮箱内附件内容
提示:java实现监听网易邮箱、java实现监听qq邮箱、java实现监听易宝邮箱、java读取邮箱中的内容、java读取邮箱内的附件、java分页读取邮箱、java读取未读的邮件、java读取邮箱中包含关键字的邮件、将邮件改为已读、java读取邮件附件
文章目录
- 前言
- 一、总体流程
- 二、邮箱设置(生成安全码)
- 1、设置
- 2、SMTP
- 3、新增授权码
- 三、代码实现
- 1、pom依赖
- 2、配置文件
- 3、配置类
- 4、邮箱代码(发送邮件+监听邮箱+读取附件+未读邮件+读完标记已读+分页获取)
- 4.1、网易邮箱
- 4.2、qq邮箱
- 总结
前言
简单说下背景吧,我负责的机票业务线,开具电子形成单时,有的供应商是通过接口获取形成单文件,有的供应商是直接发送的邮箱,需要监听邮箱,并把邮箱中的附件(电子行程单的pdf、ofd文件)读取出来,ocr识别相关信息,推送给页面。
一、总体流程
总的介绍的话,可以分为这么几步:
- 在邮箱设置中生成安全码
- 再代码中配置这个安全码去登录邮箱
- 去读取邮箱中的已读/未读/包含某些关键字的邮箱
- 读取该邮件的附件,进行自己的业务逻辑
二、邮箱设置(生成安全码)
这里以网易邮箱为例,操作步骤如下图所示:
1、设置
2、SMTP
3、新增授权码
三、代码实现
1、pom依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>
不想用starter的话,也可以用下面的这个:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-email2-javax</artifactId></dependency>
2、配置文件
spring:application:name: testDBdatasource:url: jdbc:mysql://localhost:3306/finance?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false&username: tmc1password: aaabd!qqqdriver-class-name: com.mysql.cj.jdbc.Driver#qq邮箱
# mail:
# host: smtp.qq.com
# port: 465
# username: 2982990379@qq.com
# password: ataxbslevurmdcei
# default-encoding: UTF-8
# protocol: smtp
# properties:
# mail:
# smtp:
# ssl:
# enable: true
# auth: true
# connectiontimeout: 5000
# timeout: 3000
# writetimeout: 5000
# socketFactory:
# class: javax.net.ssl.SSLSocketFactory
# fallback: false#163 网易邮箱
# mail:
# host: smtp.163.com
# port: 465
# username: zhengxxx156@163.com
# password: LdWArkgdss8ptRTaw
# default-encoding: UTF-8
# protocol: smtp
# properties:
# mail:
# smtp:
# ssl:
# enable: true
# auth: true
# connectiontimeout: 5000
# timeout: 3000
# writetimeout: 5000
# socketFactory:
# class: javax.net.ssl.SSLSocketFactory
# fallback: false#合思邮箱server:port: 9001
mybatis:mapper-locations: classpath:mapper/**/*.xmlemail:subject: 验证码 #邮件标题contentPrefix: 你的验证码是: #验证码内容前缀contentSuffix: ,请妥善保管,以免泄露对你的账号安全造成危害。 #验证码内容后缀wyemail:subject: 验证码aa #邮件标题contentPrefix: 你的验证码是bb: #验证码内容前缀contentSuffix: ,请妥善保管,以免泄露对你的账号安全造成危害cc。 #验证码内容后缀hsemail:subject: 验证码aa #邮件标题contentPrefix: 你的验证码是bb: #验证码内容前缀contentSuffix: ,请妥善保管,以免泄露对你的账号安全造成危害cc。 #验证码内容后缀
3、配置类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "wyemail")
#@ConfigurationProperties(prefix = "email")
public class WyMailConfig {private String subject;private String contentPrefix;private String contentSuffix;}
4、邮箱代码(发送邮件+监听邮箱+读取附件+未读邮件+读完标记已读+分页获取)
4.1、网易邮箱
package com.zheng.controller;import com.sun.mail.imap.IMAPStore;
import com.zheng.common.Result;
import com.zheng.config.WyMailConfig;
import com.zheng.entity.MailDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.*;import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.search.FlagTerm;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.util.*;/*** @author: ztl* @date: 2025/07/31 22:29* @desc:*/@RestController
@RequestMapping("/wyemail")
public class WyEmailController {@Autowiredprivate JavaMailSender javaMailSender;//发件人邮箱@Value("${spring.mail.username}")private String from;@Autowiredprivate WyMailConfig mailConfig;/*** 不带附件发送邮件* addressee 收件人邮箱* subject 邮件标题* content 邮件内容* @return ResultVO*/@PostMapping("/send")public Result sendEmail(@RequestBody MailDto mail) throws AddressException {//判断文件格式是否正确//获取收件人邮箱String addressee = mail.getAddressee();if(!addressee.contains("@163.com")){return Result.error("502","邮箱格式错误");}//生成随机6位数字StringBuilder sb = (StringBuilder)imgCode().getData();mail.setSubject(mailConfig.getSubject());mail.setContent(mailConfig.getContentPrefix()+sb+mailConfig.getContentSuffix());SimpleMailMessage mailMessage = new SimpleMailMessage();// 发件人邮箱,与配置文件中保持一致,所以直接从配置文件绑定过来了
// mailMessage.setFrom(String.valueOf(new InternetAddress("大浪8" + "<" + from + ">")));mailMessage.setFrom(from);// 收件人mailMessage.setTo(mail.getAddressee());// 标题mailMessage.setSubject(mail.getSubject());// 内容, 第一个参数为邮箱内容, 第二个参数为是否启用html格式,// 如果开启, 那么第一个参数如果有html标签, 会自动识别, 邮件样式更好看mailMessage.setText(mail.getContent());try {javaMailSender.send(mailMessage);return Result.success(sb.toString()); // 返回验证码} catch (MailAuthenticationException e) {return Result.error("530", "认证失败,请检查授权码和SSL配置");} catch (MailSendException e) {return Result.error("531", "邮件发送失败,请检查网络和配置");}//返回验证码
// return Result.success();}@GetMapping("/getImgCode")public Result imgCode(){//生成随机6位数字SecureRandom secureRandom = new SecureRandom();StringBuilder sb = new StringBuilder();for (int i = 0; i < 6; i++) {sb.append(secureRandom.nextInt(10));}return Result.success(sb);}/*** 新增:接收最新的N封邮件* @param count 要获取的邮件数量(默认10封)* @return 邮件列表(包含发件人、主题、内容)*/@GetMapping("/receive")public Result receiveEmails(@RequestParam(defaultValue = "10") int count) {try {// 1. 配置IMAP服务器Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.163.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");props.setProperty("mail.imap.auth", "true");//这部分就是解决异常的关键所在,设置IAMP ID信息HashMap IAM = new HashMap();//带上IMAP ID信息,由key和value组成,例如name,version,vendor,support-email等。// 这个value的值随便写就行IAM.put("name","myname");IAM.put("version","1.0.0");IAM.put("vendor","myclient");IAM.put("support-email","testmail@test.com");// 2. 创建Session并连接邮件服务器Session session = Session.getInstance(props);
// Store store = session.getStore("imap");IMAPStore store = (IMAPStore) session.getStore("imap");
// store.connect("imap.163.com", from, "LHvwWArkg8ptRTaw"); // 使用授权码登录store.connect("zhengtianliang156@163.com", "LHvwWArkg8ptRTaw"); // 使用授权码登录store.id(IAM);// 3. 打开收件箱Folder inbox = store.getFolder("INBOX");inbox.open(Folder.READ_WRITE); // 只读模式// 4. 获取最新的N封邮件Message[] messages = inbox.getMessages();int totalMessages = Math.min(count, messages.length);List<Map<String, String>> emailList = new ArrayList<>();for (int i = messages.length - 1; i >= messages.length - totalMessages; i--) {Message message = messages[i];Map<String, String> emailInfo = new HashMap<>();emailInfo.put("from", InternetAddress.toString(message.getFrom()));emailInfo.put("subject", message.getSubject());emailInfo.put("content", message.getContent().toString());emailInfo.put("date", message.getSentDate().toString());emailList.add(emailInfo);}// 5. 关闭连接inbox.close(false);store.close();return Result.success(emailList);} catch (Exception e) {e.printStackTrace();return Result.error("500", "接收邮件失败: " + e.getMessage());}}/*** 新增:获取最新邮件中的 PDF 附件* @param count 检查的最新邮件数量(默认5封)* @return 包含 PDF 附件的 Base64 编码和文件名*/@GetMapping("/pdfAttachments")public Result getPdfAttachments(@RequestParam(defaultValue = "5") int count) {try {// 1. 配置IMAP服务器Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.163.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");props.setProperty("mail.imap.auth", "true");//这部分就是解决异常的关键所在,设置IAMP ID信息HashMap IAM = new HashMap();//带上IMAP ID信息,由key和value组成,例如name,version,vendor,support-email等。// 这个value的值随便写就行IAM.put("name","myname");IAM.put("version","1.0.0");IAM.put("vendor","myclient");IAM.put("support-email","testmail@test.com");// 2. 创建Session并连接邮件服务器Session session = Session.getInstance(props);
// Store store = session.getStore("imap");IMAPStore store = (IMAPStore) session.getStore("imap");
// store.connect("imap.163.com", from, "LHvwWArkg8ptRTaw"); // 使用授权码登录store.connect("zhengtianliang156@163.com", "LHvwWArkg8ptRTaw"); // 使用授权码登录store.id(IAM);// 3. 打开收件箱Folder inbox = store.getFolder("INBOX");inbox.open(Folder.READ_ONLY);// 4. 获取最新的N封邮件Message[] messages = inbox.getMessages();int totalMessages = Math.min(count, messages.length);List<Map<String, String>> pdfAttachments = new ArrayList<>();// 5. 遍历邮件,查找PDF附件for (int i = messages.length - 1; i >= messages.length - totalMessages; i--) {Message message = messages[i];if (message.isMimeType("multipart/*")) {Multipart multipart = (Multipart) message.getContent();for (int j = 0; j < multipart.getCount(); j++) {BodyPart bodyPart = multipart.getBodyPart(j);if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {String fileName = bodyPart.getFileName();if (fileName != null && fileName.toLowerCase().endsWith(".pdf")) {// 读取PDF附件ByteArrayOutputStream outputStream = new ByteArrayOutputStream();bodyPart.getDataHandler().writeTo(outputStream);byte[] pdfBytes = outputStream.toByteArray();// 转换为Base64String base64Pdf = Base64.getEncoder().encodeToString(pdfBytes);Map<String, String> attachmentInfo = new HashMap<>();attachmentInfo.put("fileName", fileName);attachmentInfo.put("base64Content", base64Pdf);pdfAttachments.add(attachmentInfo);}}}}}// 6. 关闭连接inbox.close(false);store.close();return Result.success(pdfAttachments);} catch (Exception e) {e.printStackTrace();return Result.error("500", "获取PDF附件失败: " + e.getMessage());}}/*** 分页+ 只要未读的邮件* @param count* @return*/@GetMapping("/receivePage")public Result receiveUnreadEmailsByPage(@RequestParam(defaultValue = "1") int page) {IMAPStore store = null;Folder inbox = null;try {// 1. 配置IMAP服务器(163邮箱使用IMAP协议)Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.163.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");props.setProperty("mail.imap.auth", "true");// 设置IMAP ID信息(解决163邮箱认证问题)HashMap<String, String> IAM = new HashMap<>();IAM.put("name", "myname");IAM.put("version", "1.0.0");IAM.put("vendor", "myclient");IAM.put("support-email", "testmail@test.com");// 2. 创建Session并连接邮件服务器Session session = Session.getInstance(props);store = (IMAPStore) session.getStore("imap");store.connect("zhengtianliang156@163.com", "LHvwWArkg8ptRTaw");store.id(IAM);// 3. 打开收件箱(读写模式,才能修改邮件状态)inbox = store.getFolder("INBOX");inbox.open(Folder.READ_WRITE);// 4. 筛选未读邮件(Flags.Flag.SEEN = false)Flags seenFlag = new Flags(Flags.Flag.SEEN);FlagTerm unseenFlagTerm = new FlagTerm(seenFlag, false);Message[] unreadMessages = inbox.search(unseenFlagTerm);// 5. 分页处理(每页2条)int pageSize = 2;int totalUnread = unreadMessages.length;int totalPages = (int) Math.ceil((double) totalUnread / pageSize);// 页码校验if (page < 1 || (page > totalPages && totalPages > 0)) {return Result.error("400", "页码超出范围");}// 6. 获取当前页数据List<Map<String, String>> emailList = new ArrayList<>();int startIdx = (page - 1) * pageSize;int endIdx = Math.min(startIdx + pageSize, totalUnread);for (int i = startIdx; i < endIdx; i++) {Message message = unreadMessages[i];Map<String, String> emailInfo = new HashMap<>();emailInfo.put("from", InternetAddress.toString(message.getFrom()));emailInfo.put("subject", message.getSubject());emailInfo.put("content", getTextFromMessage(message)); // 改进的内容获取方法emailInfo.put("date", message.getSentDate().toString());// 标记为已读message.setFlag(Flags.Flag.SEEN, true);emailList.add(emailInfo);}// 7. 返回分页结果Map<String, Object> result = new HashMap<>();result.put("emails", emailList);result.put("currentPage", page);result.put("pageSize", pageSize);result.put("totalUnread", totalUnread);result.put("totalPages", totalPages);// 8. 关闭连接(保存更改)inbox.close(true);store.close();return Result.success(result);} catch (Exception e) {e.printStackTrace();try {if (inbox != null && inbox.isOpen()) inbox.close(false);if (store != null && store.isConnected()) store.close();} catch (Exception ex) {ex.printStackTrace();}return Result.error("500", "接收邮件失败: " + e.getMessage());}}@GetMapping("/receivePage1")public Result receiveUnreadEmailsByPage(@RequestParam(defaultValue = "1") int page,HttpServletResponse response) {IMAPStore store = null;Folder inbox = null;try {// 1. 配置IMAP服务器Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.163.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");props.setProperty("mail.imap.auth", "true");// 设置IMAP ID信息HashMap<String, String> IAM = new HashMap<>();IAM.put("name", "myname");IAM.put("version", "1.0.0");IAM.put("vendor", "myclient");IAM.put("support-email", "testmail@test.com");// 2. 创建Session并连接邮件服务器Session session = Session.getInstance(props);store = (IMAPStore) session.getStore("imap");store.connect("zhengtianliang156@163.com", "LHvwWArkg8ptRTaw");store.id(IAM);// 3. 打开收件箱inbox = store.getFolder("INBOX");inbox.open(Folder.READ_WRITE);// 4. 筛选未读邮件Flags seenFlag = new Flags(Flags.Flag.SEEN);FlagTerm unseenFlagTerm = new FlagTerm(seenFlag, false);Message[] unreadMessages = inbox.search(unseenFlagTerm);// 5. 分页处理int pageSize = 2;int totalUnread = unreadMessages.length;int totalPages = (int) Math.ceil((double) totalUnread / pageSize);// 6. 处理邮件和附件List<Map<String, Object>> emailList = new ArrayList<>();int startIdx = (page - 1) * pageSize;int endIdx = Math.min(startIdx + pageSize, totalUnread);for (int i = startIdx; i < endIdx; i++) {Message message = unreadMessages[i];Map<String, Object> emailInfo = new HashMap<>();// 基础信息emailInfo.put("from", InternetAddress.toString(message.getFrom()));emailInfo.put("subject", message.getSubject());emailInfo.put("content", getTextFromMessage(message));emailInfo.put("date", message.getSentDate().toString());if (message.isMimeType("multipart/*")) {Multipart multipart = (Multipart) message.getContent();for (int j = 0; j < multipart.getCount(); j++) {BodyPart bodyPart = multipart.getBodyPart(j);if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {String fileName = bodyPart.getFileName();if (fileName != null && fileName.toLowerCase().endsWith(".ofd")) {// 读取PDF附件ByteArrayOutputStream outputStream = new ByteArrayOutputStream();bodyPart.getDataHandler().writeTo(outputStream);byte[] pdfBytes = outputStream.toByteArray();// 转换为Base64String base64Pdf = Base64.getEncoder().encodeToString(pdfBytes);Map<String, String> attachmentInfo = new HashMap<>();attachmentInfo.put("fileName", fileName);attachmentInfo.put("base64Content", base64Pdf);emailInfo.put("date", message.getSentDate().toString());emailInfo.put("attachmentInfo1", attachmentInfo);}}}}// 处理附件List<Map<String, String>> attachments = processAttachments(message, response);emailInfo.put("attachments", attachments);// 标记为已读
// message.setFlag(Flags.Flag.SEEN, true);emailList.add(emailInfo);}// 7. 返回结果Map<String, Object> result = new HashMap<>();result.put("emails", emailList);result.put("currentPage", page);result.put("pageSize", pageSize);result.put("totalUnread", totalUnread);result.put("totalPages", totalPages);return Result.success(result);} catch (Exception e) {e.printStackTrace();return Result.error("500", "接收邮件失败: " + e.getMessage());} finally {try {if (inbox != null && inbox.isOpen()) inbox.close(true);if (store != null && store.isConnected()) store.close();} catch (Exception e) {e.printStackTrace();}}}private List<Map<String, String>> processAttachments(Message message, HttpServletResponse response)throws Exception {List<Map<String, String>> attachments = new ArrayList<>();if (message.isMimeType("multipart/*")) {Multipart multipart = (Multipart) message.getContent();for (int i = 0; i < multipart.getCount(); i++) {BodyPart bodyPart = multipart.getBodyPart(i);if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {String fileName = bodyPart.getFileName();String fileType = bodyPart.getContentType();long fileSize = bodyPart.getSize();// 附件信息Map<String, String> attachmentInfo = new HashMap<>();attachmentInfo.put("fileName", fileName);attachmentInfo.put("fileType", fileType);attachmentInfo.put("fileSize", String.valueOf(fileSize));attachmentInfo.put("downloadUrl", "/downloadAttachment?fileName=" +URLEncoder.encode(fileName, "UTF-8"));attachments.add(attachmentInfo);// 保存附件到临时目录}}}return attachments;}private String getTextFromMessage(Message message) throws Exception {if (message.isMimeType("text/plain")) {return message.getContent().toString();} else if (message.isMimeType("multipart/*")) {return processMultipart((Multipart) message.getContent());} else if (message.isMimeType("text/html")) {return htmlToText(message.getContent().toString());}return "无法解析的邮件内容";}/*** String text = html.replaceAll("<[^>]+>", "").replaceAll(" ", " ");* @param multipart* @return* @throws Exception*/private String processMultipart(Multipart multipart) throws Exception {StringBuilder result = new StringBuilder();for (int i = 0; i < multipart.getCount(); i++) {BodyPart bodyPart = multipart.getBodyPart(i);// 处理multipart/related类型的嵌套内容if (bodyPart.isMimeType("multipart/related")) {result.append(processMultipart((Multipart) bodyPart.getContent()));}// 处理其他multipart类型(如mixed/alternative)else if (bodyPart.getContent() instanceof Multipart) {result.append(processMultipart((Multipart) bodyPart.getContent()));}// 处理纯文本内容else if (bodyPart.isMimeType("text/plain")) {result.append(bodyPart.getContent().toString());}// 处理HTML内容else if (bodyPart.isMimeType("text/html")) {result.append(htmlToText(bodyPart.getContent().toString()));}// 可以添加对其他内容类型的处理...}return result.toString().trim();}private String htmlToText(String html) {// 使用JSoup去除HTML标签,保留文本内容return html;}}
4.2、qq邮箱
package com.zheng.controller;import com.zheng.common.Result;
import com.zheng.config.MailConfig;
import com.zheng.entity.MailDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.*;import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import java.io.ByteArrayOutputStream;
import java.security.SecureRandom;
import java.util.*;@RestController
@RequestMapping("/email")
public class QqEmailController {@Autowiredprivate JavaMailSender javaMailSender;//发件人邮箱@Value("${spring.mail.username}")private String from;@Autowiredprivate MailConfig mailConfig;/*** 不带附件发送邮件* addressee 收件人邮箱* subject 邮件标题* content 邮件内容* @return ResultVO*/@PostMapping("/send")public Result sendEmail(@RequestBody MailDto mail) throws AddressException {//判断文件格式是否正确//获取收件人邮箱String addressee = mail.getAddressee();if(!addressee.contains("@qq.com")){return Result.error("502","邮箱格式错误");}//生成随机6位数字StringBuilder sb = (StringBuilder)imgCode().getData();mail.setSubject(mailConfig.getSubject());mail.setContent(mailConfig.getContentPrefix()+sb+mailConfig.getContentSuffix());SimpleMailMessage mailMessage = new SimpleMailMessage();// 发件人邮箱,与配置文件中保持一致,所以直接从配置文件绑定过来了
// mailMessage.setFrom(String.valueOf(new InternetAddress("大浪8" + "<" + from + ">")));mailMessage.setFrom(from);// 收件人mailMessage.setTo(mail.getAddressee());// 标题mailMessage.setSubject(mail.getSubject());// 内容, 第一个参数为邮箱内容, 第二个参数为是否启用html格式,// 如果开启, 那么第一个参数如果有html标签, 会自动识别, 邮件样式更好看mailMessage.setText(mail.getContent());try {javaMailSender.send(mailMessage);return Result.success(sb.toString()); // 返回验证码} catch (MailAuthenticationException e) {return Result.error("530", "认证失败,请检查授权码和SSL配置");} catch (MailSendException e) {return Result.error("531", "邮件发送失败,请检查网络和配置");}//返回验证码
// return Result.success();}@GetMapping("/getImgCode")public Result imgCode(){//生成随机6位数字SecureRandom secureRandom = new SecureRandom();StringBuilder sb = new StringBuilder();for (int i = 0; i < 6; i++) {sb.append(secureRandom.nextInt(10));}return Result.success(sb);}/*** 新增:接收最新的N封邮件* @param count 要获取的邮件数量(默认10封)* @return 邮件列表(包含发件人、主题、内容)*/@GetMapping("/receive")public Result receiveEmails(@RequestParam(defaultValue = "10") int count) {try {// 1. 配置IMAP服务器(QQ邮箱使用IMAP协议)Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.qq.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");// 2. 创建Session并连接邮件服务器Session session = Session.getInstance(props);Store store = session.getStore("imap");store.connect("imap.qq.com", from, "atqxbylewurmdcei"); // 使用授权码登录// 3. 打开收件箱Folder inbox = store.getFolder("INBOX");inbox.open(Folder.READ_ONLY); // 只读模式// 4. 获取最新的N封邮件Message[] messages = inbox.getMessages();int totalMessages = Math.min(count, messages.length);List<Map<String, String>> emailList = new ArrayList<>();for (int i = messages.length - 1; i >= messages.length - totalMessages; i--) {Message message = messages[i];Map<String, String> emailInfo = new HashMap<>();emailInfo.put("from", InternetAddress.toString(message.getFrom()));emailInfo.put("subject", message.getSubject());emailInfo.put("content", message.getContent().toString());emailInfo.put("date", message.getSentDate().toString());emailList.add(emailInfo);}// 5. 关闭连接inbox.close(false);store.close();return Result.success(emailList);} catch (Exception e) {e.printStackTrace();return Result.error("500", "接收邮件失败: " + e.getMessage());}}/*** 新增:获取最新邮件中的 PDF 附件* @param count 检查的最新邮件数量(默认5封)* @return 包含 PDF 附件的 Base64 编码和文件名*/@GetMapping("/pdfAttachments")public Result getPdfAttachments(@RequestParam(defaultValue = "5") int count) {try {// 1. 配置IMAP服务器Properties props = new Properties();props.setProperty("mail.store.protocol", "imap");props.setProperty("mail.imap.host", "imap.qq.com");props.setProperty("mail.imap.port", "993");props.setProperty("mail.imap.ssl.enable", "true");// 2. 连接邮箱服务器Session session = Session.getInstance(props);Store store = session.getStore("imap");store.connect("imap.qq.com", from, "atqxbylewurmdcei");// 3. 打开收件箱Folder inbox = store.getFolder("INBOX");inbox.open(Folder.READ_ONLY);// 4. 获取最新的N封邮件Message[] messages = inbox.getMessages();int totalMessages = Math.min(count, messages.length);List<Map<String, String>> pdfAttachments = new ArrayList<>();// 5. 遍历邮件,查找PDF附件for (int i = messages.length - 1; i >= messages.length - totalMessages; i--) {Message message = messages[i];if (message.isMimeType("multipart/*")) {Multipart multipart = (Multipart) message.getContent();for (int j = 0; j < multipart.getCount(); j++) {BodyPart bodyPart = multipart.getBodyPart(j);if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {String fileName = bodyPart.getFileName();if (fileName != null && fileName.toLowerCase().endsWith(".pdf")) {// 读取PDF附件ByteArrayOutputStream outputStream = new ByteArrayOutputStream();bodyPart.getDataHandler().writeTo(outputStream);byte[] pdfBytes = outputStream.toByteArray();// 转换为Base64String base64Pdf = Base64.getEncoder().encodeToString(pdfBytes);Map<String, String> attachmentInfo = new HashMap<>();attachmentInfo.put("fileName", fileName);attachmentInfo.put("base64Content", base64Pdf);pdfAttachments.add(attachmentInfo);}}}}}// 6. 关闭连接inbox.close(false);store.close();return Result.success(pdfAttachments);} catch (Exception e) {e.printStackTrace();return Result.error("500", "获取PDF附件失败: " + e.getMessage());}}}
总结
java监听读取邮件时,大家可能是自己公司内部有自己的邮箱,也是类似的,生成相关安全码然后代码去监听就行。可以用xxljob每10分钟监听一次,或者根据自己的真实业务来个性化的处理。