JAVA 对接邮箱实现收件

1.需要启用获取邮箱的

2.直接使用应用专用密码: 开启两步验证, 在配置应用专用密码. 

 3.Util代码

package com.ruoyi.system.utils;

import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.cenum.EmailFormat;
import com.ruoyi.system.domain.email.EmailBox;
import com.ruoyi.system.domain.email.EmailFile;
import com.ruoyi.system.domain.email.User;
import com.ruoyi.system.mapper.EmailBoxMapper;
import com.ruoyi.system.mapper.EmailFileMapper;
import com.sun.mail.imap.IMAPStore;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
@Slf4j
@Data
public class NewEmailUtil {
// @Autowired
// private IEmailService emailService;
// @Autowired
// private UserService userService;
// @Autowired
// private EmailFileService emailFileService;

@Value("${file.email}")
private String email; //配置文件 服务器地址
@Async
public List<EmailBox> getEmailBox(String userEmail, String password, String emailType, Integer pageNo, Integer pageSize,Integer storedEmailCount) throws MessagingException, IOException {

User userDB = new User(1L, userEmail, password);
EmailFormat emailFormat = EmailFormat.getEmailType(userDB.getEmail());
Properties prop = new Properties();
//prop.setProperty("mail.debug", "true");
prop.setProperty("mail.store.protocol", "imap");
prop.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//分片下载关闭 开启后文件传输效率低
prop.setProperty("mail.imap.partialfetch", "false");
//pop3服务器,我这里使用163邮箱
prop.setProperty("mail.imap.host", emailFormat.getHost());
//pop默认110端口
prop.setProperty("mail.imap.port", "993");
// 1、创建session
Session session = Session.getInstance(prop);
// 2、通过session得到Store对象
IMAPStore store = (IMAPStore) session.getStore();
// 3、连上邮件服务器
store.connect(emailFormat.getHost(), 993, userDB.getEmail(), userDB.getPassword());

Folder folder = store.getFolder(emailType);
folder.open(Folder.READ_ONLY);
// 替换为实际的数据库查询结果

int totalMessages = folder.getMessageCount();//当前收件箱的数量
int newEmailCount = totalMessages - storedEmailCount;
System.out.println(totalMessages);

Message[] messages = folder.getMessages(totalMessages - newEmailCount + 1, totalMessages);

// Message[] messages = folder.getMessages(endIndex, startIndex);

List<EmailBox> emailBoxes = new ArrayList<>();
ArrayList<EmailBox> list = new ArrayList<>();
List<EmailFile> fileList = new ArrayList<>();
for (int i = messages.length - 1; i >= 0; i--) {
// if (emailBoxes.size() >= pageSize) {
// break;
// }
System.out.println("现在是第:" + i + "条邮件");
Part mp = messages[i];
MimeMessage msg = (MimeMessage) messages[i];
HashMap<String, String> contentMap = new HashMap<>();
getMailTextHtmlContent(msg, contentMap);
String path = email;
//查询所有的id


// List<EmailBox> emailBoxList = emailService.list(new LambdaQueryWrapper<EmailBox>().eq(EmailBox::getEmailId, msg.getMessageID()).eq(EmailBox::getEmailType,emailType));
// if (!emailBoxList.isEmpty()) {
// break;
// }
if (isContainAttachment(mp)) {
saveAttachment(mp, fileList, msg.getMessageID());
}
System.out.println("==================================");
EmailBox email = new EmailBox();
email.setEmailId(msg.getMessageID());

email.setUsername(userEmail);
email.setEmailType(emailType);
email.setSubject(getSubject(msg));
email.setFromUser(getFrom(msg));
email.setReceiveAddress(getReceiveAddress(msg, Message.RecipientType.TO));
email.setCopyUser(getReceiveAddress(msg, Message.RecipientType.CC));
// email.setContent(contentMap.get("html"));
email.setText(contentMap.get("text"));
email.setSendDate(getSentDate(msg, "yyyy-MM-dd HH:mm:ss"));
email.setIsRead(String.valueOf(isSeen(msg)));
email.setPriority(getPriority(msg));
email.setIsReplySign(String.valueOf(isReplySign(msg)));
email.setIsAttachments(String.valueOf(isContainAttachment(mp)));
email.setAttachmentPath(path);
// emailBoxMapper.insertEmailBox(email);
// if (emailBoxList.isEmpty()) {
list.add(email);
// }
}
// for (EmailFile emailFile : fileList) {
// emailFileMapper.insertEmailFile(emailFile);
// }

// emailService.saveBatch(list);
// emailFileService.saveBatch(fileList);
folder.close(false);
store.close();

// }
return list;
}

/**
* 获得邮件发送时间
*
* @param msg 邮件内容
* @return yyyy年mm月dd日 星期X HH:mm
* @throws MessagingException
*/
public static String getSentDate(MimeMessage msg, String pattern) throws MessagingException {
Date receivedDate = msg.getSentDate();
if (receivedDate == null) {
return "";
}

if (pattern == null || "".equals(pattern)) {
pattern = "yyyy年MM月dd日 E HH:mm ";
}

return new SimpleDateFormat(pattern).format(receivedDate);
}


public static String getSubject(MimeMessage msg) throws UnsupportedEncodingException, MessagingException {
String subject = msg.getSubject();
if (StringUtils.isEmpty(subject)) {
subject = "";
}
return MimeUtility.decodeText(subject);
}

/**
* 获得邮件发件人
*
* @param msg 邮件内容
* @return 姓名 <Email地址>
* @throws MessagingException
* @throws UnsupportedEncodingException
*/
public static String getFrom(MimeMessage msg) throws MessagingException, UnsupportedEncodingException {
String from = "";
Address[] froms = msg.getFrom();
if (froms.length < 1) {
throw new MessagingException("没有发件人!");
}

InternetAddress address = (InternetAddress) froms[0];
String person = address.getPersonal();
if (person != null) {
person = MimeUtility.decodeText(person) + " ";
} else {
person = "";
}
from = person + "<" + address.getAddress() + ">";

return from;
}


/**
* 根据收件人类型,获取邮件收件人、抄送和密送地址。如果收件人类型为空,则获得所有的收件人
* <p>Message.RecipientType.TO 收件人</p>
* <p>Message.RecipientType.CC 抄送</p>
* <p>Message.RecipientType.BCC 密送</p>
*
* @param msg 邮件内容
* @param type 收件人类型
* @return 收件人1 <邮件地址1>, 收件人2 <邮件地址2>, ...
* @throws MessagingException
*/
public static String getReceiveAddress(MimeMessage msg, Message.RecipientType type) throws MessagingException {
StringBuffer receiveAddress = new StringBuffer();
Address[] addresss = null;
if (type == null) {
addresss = msg.getAllRecipients();
} else {
addresss = msg.getRecipients(type);
}
if (addresss == null || addresss.length < 1) {
return null;
}
for (Address address : addresss) {
InternetAddress internetAddress = (InternetAddress) address;
receiveAddress.append(internetAddress.toUnicodeString()).append(",");
}
//删除最后一个逗号
receiveAddress.deleteCharAt(receiveAddress.length() - 1);
return receiveAddress.toString();
}


/**
* 获得邮件文本内容
*
* @param part 邮件体
* @param content 存储邮件文本内容的字符串
* @throws MessagingException
* @throws IOException
*/
public static void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException {
//如果是文本类型的附件,通过getContent方法可以取到文本内容,但这不是我们需要的结果,所以在这里要做判断
boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
if (part.isMimeType("text/*") && !isContainTextAttach) {
try {
content.append(part.getContent().toString());
} catch (IOException e) {
content.append("");
}
} 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);
}
}
}


/**
* 判断邮件是否已读
*
* @param msg 邮件内容
* @return 如果邮件已读返回true, 否则返回false
* @throws MessagingException
*/
public static boolean isSeen(MimeMessage msg) throws MessagingException {
return msg.getFlags().contains(Flags.Flag.SEEN);
}

/**
* 获得邮件的优先级
*
* @param msg 邮件内容
* @return 1(High):紧急 3:普通(Normal) 5:低(Low)
* @throws MessagingException
*/
public static String getPriority(MimeMessage msg) throws MessagingException {
String priority = "普通";
String[] headers = msg.getHeader("X-Priority");
if (headers != null) {
String headerPriority = headers[0];
if (headerPriority.contains("1") || headerPriority.contains("High")) {
priority = "紧急";
} else if (
headerPriority.contains("5") || headerPriority.contains("Low")) {
priority = "低";
} else {
priority = "普通";
}
}
return priority;
}


/**
* 判断邮件是否需要阅读回执
*
* @param msg 邮件内容
* @return 需要回执返回true, 否则返回false
* @throws MessagingException
*/
public static boolean isReplySign(MimeMessage msg) throws MessagingException {
boolean replySign = false;
String[] headers = msg.getHeader("Disposition-Notification-To");
if (headers != null) {
replySign = true;
}
return replySign;
}


/**
* 判断邮件中是否包含附件
*
* @param part 邮件内容
* @return 邮件中存在附件返回true,不存在返回false
* @throws MessagingException
* @throws IOException
*/
public 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.contains("application")) {
flag = true;
}

if (contentType.contains("name")) {
flag = true;
}
}

if (flag) {
break;
}
}
} else if (part.isMimeType("message/rfc822")) {
flag = isContainAttachment((Part) part.getContent());
}
return flag;
}


/**
* 保存附件
*
* @param part 邮件中多个组合体中的其中一个组合体
* @throws UnsupportedEncodingException
* @throws MessagingException
* @throws FileNotFoundException
* @throws IOException
*/
public static String saveAttachment(Part part, List<EmailFile> fileList, String emailId) throws UnsupportedEncodingException, MessagingException,
FileNotFoundException, IOException {
StringBuffer stringBuffer = new StringBuffer();
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);
//某一个邮件体也有可能是由多个邮件体组成的复杂体
String disp = bodyPart.getDisposition();
if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
//获取文件名称
String fileName = bodyPart.getFileName();
if (Objects.equals(fileName, null)) {
fileName = "1";
}
fileList.add(new EmailFile(null, emailId, MimeUtility.decodeText(fileName)));
} else if (bodyPart.isMimeType("multipart/*")) {
saveAttachment(bodyPart, fileList, emailId);
} else {
String contentType = bodyPart.getContentType();
if (contentType.contains("name") || contentType.contains("application")) {
String fileName = bodyPart.getFileName();
fileList.add(new EmailFile(null, emailId, MimeUtility.decodeText(fileName)));
}
}
}
} else if (part.isMimeType("message/rfc822")) {
saveAttachment((Part) part.getContent(), fileList, emailId);
}
return stringBuffer.toString();
}


/**
* 数据解码
*
* @param encodeText
* @return String
* @author THX
* @date 2024/6/5 9:52
*/
public static String decodeText(String encodeText) throws UnsupportedEncodingException {
if (encodeText == null || "".equals(encodeText)) {
return "";
} else {
return MimeUtility.decodeText(encodeText);
}
}


public static void getMailTextHtmlContent(Part part, HashMap<String, String> contentMap) throws MessagingException, IOException {
//如果是文本类型的附件,通过getContent方法可以取到文本内容,但这不是我们需要的结果,所以在这里要做判断HashMap<String, String> contentMap = new HashMap<>();
boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
if (part.isMimeType("text/*") && !isContainTextAttach) {
if (part.isMimeType("text/html")) {
try {
contentMap.put("html", part.getContent().toString());
} catch (IOException e) {
contentMap.put("html", "");
}
} else {
try {
contentMap.put("text", part.getContent().toString());
} catch (IOException e) {
contentMap.put("text", "");
}
}
} else if (part.isMimeType("message/rfc822")) {
getMailTextHtmlContent((Part) part.getContent(), contentMap);
} 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);
getMailTextHtmlContent(bodyPart, contentMap);
}
}
}


// @Async
// public void updateEmailStatus(String email,String emailId) throws MessagingException {
// LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(User::getEmail, email);
// User userDB = userService.getOne(queryWrapper);
//
// EmailFormat emailFormat = EmailFormat.getEmailType(userDB.getEmail());
// Properties prop = new Properties();
// //prop.setProperty("mail.debug", "true");
// prop.setProperty("mail.store.protocol", "imap");
// prop.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
// //分片下载关闭 开启后文件传输效率低
// prop.setProperty("mail.imap.partialfetch", "false");
// //pop3服务器,我这里使用163邮箱
// prop.setProperty("mail.imap.host", "imap." + userDB.getEmail().substring(userDB.getEmail().indexOf("@") + 1));
// //pop默认110端口
// prop.setProperty("mail.imap.port", "993");
// // 1、创建session
// Session session = Session.getInstance(prop);
// // 2、通过session得到Store对象
// IMAPStore store = (IMAPStore) session.getStore();
// // 3、连上邮件服务器
// store.connect("imap." + userDB.getEmail().substring(userDB.getEmail().indexOf("@") + 1), 993, userDB.getEmail(), userDB.getPassword());
// if ("163".equals(emailFormat.getType())) {
// HashMap IAM = new HashMap();
// //带上IMAP ID信息,由key和value组成,例如name,version,vendor,support-email等。
// // 这个value的值随便写就行
// IAM.put("name", "name");
// IAM.put("version", "1.0.0");
// IAM.put("vendor", "client");
// IAM.put("support-email", "mail@163.com");
// store.id(IAM);
// }
// Folder inbox = store.getFolder("INBOX");
// inbox.open(Folder.READ_WRITE);
// Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
// for (Message message : messages) {
// if (message instanceof MimeMessage) {
// MimeMessage mimeMessage = (MimeMessage) message;
// String[] messageIdHeader = mimeMessage.getHeader("Message-ID");
// if (messageIdHeader != null && messageIdHeader.length > 0) {
// String messageId = messageIdHeader[0];
// if (messageId.equals(emailId)) {
// mimeMessage.setFlag(Flags.Flag.SEEN, true);
// System.out.println("已读的邮件是: " + mimeMessage.getSubject());
// break;
// }
// }
// }
// }
// inbox.close(false);
// store.close();
// }


// public void deleteEmail(String email, String emailId) throws MessagingException {
// LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(User::getEmail, email);
// User userDB = userService.getOne(queryWrapper);
// EmailFormat emailFormat = EmailFormat.getEmailType(userDB.getEmail());
// Properties prop = new Properties();
// prop.setProperty("mail.store.protocol", "imap");
// prop.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
// prop.setProperty("mail.imap.partialfetch", "false");
// prop.setProperty("mail.imap.host", "imap." + userDB.getEmail().substring(userDB.getEmail().indexOf("@") + 1));
// prop.setProperty("mail.imap.port", "993");
// Session session = Session.getInstance(prop);
// IMAPStore store = (IMAPStore) session.getStore();
// store.connect("imap." + userDB.getEmail().substring(userDB.getEmail().indexOf("@") + 1), 993, userDB.getEmail(), userDB.getPassword());
// if ("163".equals(emailFormat.getType())) {
// HashMap<String, String> IAM = new HashMap<>();
// IAM.put("name", "name");
// IAM.put("version", "1.0.0");
// IAM.put("vendor", "client");
// IAM.put("support-email", "mail@163.com");
// store.id(IAM);
// }
// Folder inbox = store.getFolder("INBOX");
// inbox.open(Folder.READ_WRITE);
// Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.DELETED), false));
// for (Message message : messages) {
// if (message instanceof MimeMessage) {
// MimeMessage mimeMessage = (MimeMessage) message;
// String[] messageIdHeader = mimeMessage.getHeader("Message-ID");
// if (messageIdHeader != null && messageIdHeader.length > 0) {
// String messageId = messageIdHeader[0];
// if (messageId.equals(emailId)) {
// mimeMessage.setFlag(Flags.Flag.DELETED, true);
// System.out.println("删除邮件: " + mimeMessage.getSubject());
// break;
// }
// }
// }
// }
// inbox.close(true);
// store.close();
// }


}

 实体类

package com.ruoyi.system.domain.email;


import com.ruoyi.common.core.domain.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailBox extends BaseEntity {
private Long id;
private String username;
private String emailId;
private String emailType;
private String subject;
private String fromUser;
private String copyUser;
private String receiveAddress;
private String sendDate;
private String isRead;//是否已读
private String isReplySign;
private String content;
private String text;
private String isAttachments;//是否有附件
private String priority;
private String attachmentPath;
private Long employeeId;
private String employeeName;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

private Long id;
private String email;
private String password;
}

 

 枚举

package com.ruoyi.system.domain.cenum;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public enum EmailFormat {

EMAIL_QQ("qq","^[a-zA-Z0-9._%+-]+@qq\\.com$","imap.qq.com","993"),
EMAIL_163("163","^[a-zA-Z0-9._%+-]+@163\\.com$","imap.163.com","993"),
EMAIL_139("139","^[a-zA-Z0-9._%+-]+@139\\.com$","imap.139.com","993"),
EMAIL_GMAIL("gmail","^[a-zA-Z0-9._%+-]+@gmail\\.com$","imap.gmail.com","993");
// EMAIL_OUTLOOK("gmail","^[a-zA-Z0-9._%+-]+@(outlook\\.com|hotmail\\.com|live\\.com|msn\\.com)$","imap.outlook.com","993"),
// EMAIL_SINA("sina","^[a-zA-Z0-9._%+-]+@sina\\.com$","imap.sina.com","993");

private String type;
private String pattern;

private String host;

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getPattern() {
return pattern;
}

public void setPattern(String pattern) {
this.pattern = pattern;
}

public String getHost() {
return host;
}

public void setHost(String host) {
this.host = host;
}

public String getPort() {
return port;
}

public void setPort(String port) {
this.port = port;
}

EmailFormat(String type, String pattern, String host, String port) {
this.type = type;
this.pattern = pattern;
this.host = host;
this.port = port;
}

private String port;

public static EmailFormat getEmailType(String email){
List<EmailFormat> list = Arrays.asList(EMAIL_163, EMAIL_QQ,EMAIL_139,EMAIL_GMAIL);
for (EmailFormat emailFormat : list) {
Pattern pattern = Pattern.compile(emailFormat.pattern); // 保存一个副本
Matcher matcher = pattern.matcher(email);
if (matcher.matches()){
return emailFormat;
}
}
return null;
}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值