新增预警页面
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package com.jeesite.modules.app.dao;
|
||||
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MailReceived implements Serializable {
|
||||
|
||||
private BizMailReceived received;
|
||||
|
||||
private List<BizMailAttachments> attachments = new ArrayList<>();
|
||||
|
||||
|
||||
public MailReceived(BizMailReceived received, List<BizMailAttachments> attachments) {
|
||||
this.received = received;
|
||||
this.attachments = attachments;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -144,6 +144,7 @@ public class LoggerUtils {
|
||||
StandardCharsets.UTF_8 // 避免中文乱码
|
||||
)
|
||||
)) {
|
||||
System.out.print(logContent);
|
||||
writer.write(logContent.toString());
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import com.jeesite.modules.app.dao.MailReceived;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.*;
|
||||
import javax.mail.search.FlagTerm;
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
public class MailReceiveUtils {
|
||||
|
||||
// 连接重试配置
|
||||
private static final int CONNECT_RETRY_TIMES = 3;
|
||||
private static final long CONNECT_RETRY_INTERVAL = 1000L;
|
||||
private static final LoggerUtils logger = LoggerUtils.getInstance();
|
||||
|
||||
// 缓存ByteBuffer
|
||||
private static final ThreadLocal<ByteBuffer> BUFFER_LOCAL = ThreadLocal.withInitial(() -> ByteBuffer.allocate(8192));
|
||||
|
||||
// MIME类型映射(修复附件FileType识别)
|
||||
private static final MimetypesFileTypeMap MIME_TYPE_MAP = new MimetypesFileTypeMap();
|
||||
|
||||
static {
|
||||
// 扩展MIME类型映射,解决常见文件类型识别错误
|
||||
MIME_TYPE_MAP.addMimeTypes("application/pdf pdf");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/msword doc");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.wordprocessingml.document docx");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/vnd.ms-excel xls");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/vnd.ms-powerpoint ppt");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.presentationml.presentation pptx");
|
||||
MIME_TYPE_MAP.addMimeTypes("image/jpeg jpg jpeg");
|
||||
MIME_TYPE_MAP.addMimeTypes("image/png png");
|
||||
MIME_TYPE_MAP.addMimeTypes("image/gif gif");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/zip zip");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/x-rar-compressed rar");
|
||||
MIME_TYPE_MAP.addMimeTypes("application/x-7z-compressed 7z");
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收未读邮件(优化:优先解析HTML格式正文)
|
||||
*/
|
||||
public static List<MailReceived> receiveUnreadMails(BizMailAccount mailAccount, String saveBasePath) throws Exception {
|
||||
List<MailReceived> receivedMailList = new ArrayList<>();
|
||||
Session session = createMailSession(mailAccount);
|
||||
Store store = null;
|
||||
Folder folder = null;
|
||||
|
||||
try {
|
||||
// 1. 建立IMAP连接(带重试)
|
||||
store = session.getStore("imap");
|
||||
boolean isConnected = false;
|
||||
int retryCount = 0;
|
||||
while (!isConnected) {
|
||||
try {
|
||||
store.connect(mailAccount.getHost(), mailAccount.getImapPort(),
|
||||
mailAccount.getUsername(), mailAccount.getPassword());
|
||||
isConnected = store.isConnected();
|
||||
if (isConnected) {
|
||||
logger.info("第" + (retryCount + 1) + "次连接IMAP成功:" + mailAccount.getHost());
|
||||
}
|
||||
} catch (AuthenticationFailedException e) {
|
||||
logger.error("账号/密码错误,直接返回", e);
|
||||
return receivedMailList;
|
||||
} catch (MessagingException e) {
|
||||
retryCount++;
|
||||
logger.error("第" + retryCount + "次连接失败:" + e.getMessage());
|
||||
if (retryCount >= CONNECT_RETRY_TIMES) {
|
||||
throw new IllegalStateException("IMAP连接失败(重试3次)", e);
|
||||
}
|
||||
Thread.sleep(CONNECT_RETRY_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 打开收件箱
|
||||
folder = store.getFolder("INBOX");
|
||||
if (folder == null || !folder.exists()) {
|
||||
logger.error("收件箱不存在");
|
||||
return receivedMailList;
|
||||
}
|
||||
folder.open(Folder.READ_WRITE);
|
||||
logger.info("未读邮件数:" + folder.getUnreadMessageCount());
|
||||
|
||||
// 3. 筛选未读邮件
|
||||
Message[] unreadMessages = folder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
|
||||
if (unreadMessages == null || unreadMessages.length == 0) {
|
||||
logger.warn("无未读邮件");
|
||||
return receivedMailList;
|
||||
}
|
||||
|
||||
// 4. 处理每封邮件
|
||||
for (Message message : unreadMessages) {
|
||||
try {
|
||||
BizMailReceived bizMail = buildBizMailReceived(message, mailAccount);
|
||||
// 记录整封邮件附件下载开始时间
|
||||
long mailAttachDownloadStart = System.currentTimeMillis();
|
||||
logger.info("开始下载邮件[" + getMessageId(message) + "]的附件,开始时间:" + new Date(mailAttachDownloadStart));
|
||||
|
||||
List<BizMailAttachments> attachments = downloadExplicitAttachments(message, bizMail.getMessageId(), saveBasePath);
|
||||
|
||||
// 记录整封邮件附件下载结束时间
|
||||
long mailAttachDownloadEnd = System.currentTimeMillis();
|
||||
logger.info("完成下载邮件[" + getMessageId(message) + "]的附件,结束时间:" + new Date(mailAttachDownloadEnd) +
|
||||
",耗时:" + (mailAttachDownloadEnd - mailAttachDownloadStart) + "ms");
|
||||
|
||||
receivedMailList.add(new MailReceived(bizMail, attachments));
|
||||
message.setFlag(Flags.Flag.SEEN, true); // 标记已读
|
||||
} catch (Exception e) {
|
||||
logger.error("处理邮件失败(Message-ID:" + getMessageId(message) + "):" + e.getMessage(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
// 关闭资源
|
||||
if (folder != null && folder.isOpen()) {
|
||||
try {
|
||||
folder.close(true);
|
||||
} catch (MessagingException e) {
|
||||
logger.error("关闭文件夹失败", e);
|
||||
}
|
||||
}
|
||||
if (store != null && store.isConnected()) {
|
||||
try {
|
||||
store.close();
|
||||
} catch (MessagingException e) {
|
||||
logger.error("关闭连接失败", e);
|
||||
}
|
||||
}
|
||||
BUFFER_LOCAL.remove();
|
||||
}
|
||||
|
||||
return receivedMailList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建邮件会话(优化编码+IMAP配置)
|
||||
*/
|
||||
private static Session createMailSession(BizMailAccount mailAccount) {
|
||||
Properties props = new Properties();
|
||||
boolean sslEnable = "true".equals(mailAccount.getSslEnable());
|
||||
props.put("mail.imap.host", mailAccount.getHost());
|
||||
props.put("mail.imap.port", mailAccount.getImapPort());
|
||||
props.put("mail.imap.ssl.enable", sslEnable);
|
||||
props.put("mail.imap.ssl.protocols", "TLSv1.2"); // 强制TLS1.2,避免SSL漏洞
|
||||
props.put("mail.imap.auth", "true");
|
||||
props.put("mail.imap.connectiontimeout", "10000");
|
||||
props.put("mail.imap.timeout", "30000");
|
||||
props.put("mail.imap.partialfetch", "false"); // 禁用部分获取,避免内容截断
|
||||
props.put("mail.mime.charset", "UTF-8");
|
||||
props.put("mail.mime.base64.ignoreerrors", "true");
|
||||
props.put("mail.mime.decodefilenamehandler", "com.sun.mail.imap.protocol.IMAPUTF8DecodeHandler");
|
||||
// 关键:启用UTF-8文件名解码
|
||||
System.setProperty("mail.mime.encodeparameters", "false");
|
||||
|
||||
return Session.getInstance(props, new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(mailAccount.getUsername(), mailAccount.getPassword());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建邮件实体(核心优化:优先解析HTML正文)
|
||||
*/
|
||||
private static BizMailReceived buildBizMailReceived(Message message, BizMailAccount mailAccount) throws Exception {
|
||||
BizMailReceived received = new BizMailReceived();
|
||||
received.setCreateTime(new Date());
|
||||
received.setMessageId(getMessageId(message));
|
||||
received.setAccountId(mailAccount.getId());
|
||||
received.setUstatus("1");
|
||||
received.setMailbox("INBOX");
|
||||
|
||||
// 发件人(修复编码)
|
||||
Address[] from = message.getFrom();
|
||||
if (from != null && from.length > 0) {
|
||||
InternetAddress fromAddr = (InternetAddress) from[0];
|
||||
received.setFromAddress(fromAddr.getAddress());
|
||||
// 优先解码发件人名称
|
||||
String personal = fromAddr.getPersonal();
|
||||
if (personal != null) {
|
||||
received.setFromName(decodeMimeText(personal));
|
||||
} else {
|
||||
received.setFromName(fromAddr.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
// 收件人/抄送/密送(修复编码)
|
||||
received.setToAddresses(convertAddresses(message.getRecipients(Message.RecipientType.TO)));
|
||||
received.setCcAddresses(convertAddresses(message.getRecipients(Message.RecipientType.CC)));
|
||||
received.setBccAddresses(convertAddresses(message.getRecipients(Message.RecipientType.BCC)));
|
||||
|
||||
// 主题(修复乱码)
|
||||
String subject = message.getSubject();
|
||||
received.setSubject(subject == null ? "" : decodeMimeText(subject));
|
||||
|
||||
// 核心优化:优先解析HTML格式正文
|
||||
String htmlContent = parseHtmlMailContent(message);
|
||||
// 最终空内容兜底
|
||||
received.setMailContent(htmlContent.isEmpty() ? "<p>(无正文内容)</p>" : htmlContent);
|
||||
|
||||
// 时间
|
||||
received.setReceivedTime(new Date());
|
||||
received.setSendTime(message.getSentDate() != null ? message.getSentDate() : new Date());
|
||||
|
||||
// 是否有显式附件
|
||||
received.setHasAttachment(hasExplicitAttachment(message) ? "1" : "0");
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心优化:专门解析HTML格式正文(优先提取HTML,无则将纯文本转为HTML)
|
||||
*/
|
||||
private static String parseHtmlMailContent(Message message) throws Exception {
|
||||
Object content = message.getContent();
|
||||
StringBuilder htmlSb = new StringBuilder();
|
||||
|
||||
// 递归提取HTML内容
|
||||
extractHtmlContentRecursive(content, htmlSb);
|
||||
|
||||
// 清理HTML内容,去除无效标签和空白
|
||||
String rawHtml = htmlSb.toString().replaceAll("\\n+", "").replaceAll("\\s+", " ").trim();
|
||||
// 如果没有提取到HTML内容,尝试提取纯文本并转为HTML格式
|
||||
if (rawHtml.isEmpty()) {
|
||||
String plainText = extractPlainTextContent(message);
|
||||
if (!plainText.isEmpty()) {
|
||||
// 将纯文本转为基本HTML格式(换行转<br>,空格转 )
|
||||
rawHtml = "<p>" + plainText.replaceAll("\\n", "<br>").replaceAll(" ", " ") + "</p>";
|
||||
}
|
||||
}
|
||||
|
||||
// 标准化HTML结构
|
||||
return standardizeHtml(rawHtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归提取HTML内容(优先获取text/html类型)
|
||||
*/
|
||||
private static void extractHtmlContentRecursive(Object content, StringBuilder sb) throws Exception {
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 直接是HTML文本(极少情况)
|
||||
if (content instanceof String text) {
|
||||
if (text.contains("<html>") || text.contains("<body>") || text.contains("<p>") || text.contains("<br>")) {
|
||||
sb.append(text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. MimeMultipart:优先提取text/html部分
|
||||
if (content instanceof MimeMultipart multipart) {
|
||||
String multipartType = multipart.getContentType().split(";")[0].trim().toLowerCase();
|
||||
|
||||
// 处理multipart/alternative(多格式正文,优先取text/html)
|
||||
if ("multipart/alternative".equals(multipartType)) {
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart part = multipart.getBodyPart(i);
|
||||
String partType = part.getContentType().split(";")[0].trim().toLowerCase();
|
||||
if ("text/html".equals(partType)) {
|
||||
// 读取HTML内容并追加
|
||||
sb.append(readBodyPartContent(part));
|
||||
return; // 找到HTML后直接返回,不再处理其他部分
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理其他multipart类型(递归提取所有HTML部分)
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
String disposition = bodyPart.getDisposition();
|
||||
|
||||
// 跳过显式附件
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 提取HTML内容
|
||||
String partType = bodyPart.getContentType().split(";")[0].trim().toLowerCase();
|
||||
if ("text/html".equals(partType)) {
|
||||
sb.append(readBodyPartContent(bodyPart));
|
||||
} else {
|
||||
// 递归解析子内容
|
||||
extractHtmlContentRecursive(bodyPart.getContent(), sb);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 单个MimeBodyPart:如果是HTML类型则读取
|
||||
if (content instanceof MimeBodyPart bodyPart) {
|
||||
String disposition = bodyPart.getDisposition();
|
||||
// 跳过显式附件
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String partType = bodyPart.getContentType().split(";")[0].trim().toLowerCase();
|
||||
if ("text/html".equals(partType)) {
|
||||
sb.append(readBodyPartContent(bodyPart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取纯文本内容(作为HTML的降级方案)
|
||||
*/
|
||||
private static String extractPlainTextContent(Message message) throws Exception {
|
||||
Object content = message.getContent();
|
||||
StringBuilder plainSb = new StringBuilder();
|
||||
|
||||
extractPlainTextRecursive(content, plainSb);
|
||||
|
||||
return plainSb.toString().replaceAll("^\\s+|\\s+$", "").replaceAll("\\n+", "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归提取纯文本内容
|
||||
*/
|
||||
private static void extractPlainTextRecursive(Object content, StringBuilder sb) throws Exception {
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 纯文本直接追加
|
||||
if (content instanceof String) {
|
||||
String text = ((String) content).trim();
|
||||
if (!text.isEmpty()) {
|
||||
sb.append(text).append("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理MimeMultipart
|
||||
if (content instanceof MimeMultipart multipart) {
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
// 跳过附件
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
|
||||
continue;
|
||||
}
|
||||
// 提取纯文本
|
||||
extractPlainTextRecursive(bodyPart.getContent(), sb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理单个BodyPart
|
||||
if (content instanceof MimeBodyPart bodyPart) {
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
|
||||
return;
|
||||
}
|
||||
// 读取纯文本内容
|
||||
String partContent = readBodyPartContent(bodyPart);
|
||||
if (!partContent.isEmpty()) {
|
||||
sb.append(partContent).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准化HTML结构(补全基本标签,确保格式合法)
|
||||
*/
|
||||
private static String standardizeHtml(String html) {
|
||||
if (html.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 补全HTML基本结构
|
||||
if (!html.startsWith("<html>")) {
|
||||
html = "<html><head><meta charset=\"UTF-8\"></head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
// 修复常见的HTML格式问题
|
||||
html = html.replaceAll("<br>", "<br/>")
|
||||
.replaceAll("<hr>", "<hr/>")
|
||||
.replaceAll("&", "&")
|
||||
.replaceAll("<p>\\s*</p>", "") // 移除空p标签
|
||||
.replaceAll(">\\s+<", "><"); // 移除标签间多余空格
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取BodyPart内容(优先原始流,自动识别编码)
|
||||
*/
|
||||
private static String readBodyPartContent(BodyPart part) throws Exception {
|
||||
// 1. 获取ContentType和编码
|
||||
String contentType = part.getContentType() == null ? "" : part.getContentType().toLowerCase();
|
||||
Charset charset = getCharsetFromContentType(contentType);
|
||||
|
||||
// 2. 优先读取原始输入流(避免getContent()的自动转换错误)
|
||||
try (InputStream is = part.getInputStream();
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(bis, charset))) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] buffer = new char[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||
sb.append(buffer, 0, bytesRead);
|
||||
}
|
||||
// 清理无效字符
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
logger.warn("读取BodyPart流失败:" + e.getMessage());
|
||||
Object fallbackContent = part.getContent();
|
||||
return fallbackContent instanceof String ? ((String) fallbackContent).trim() : "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邮件内容
|
||||
*/
|
||||
private static Charset getCharsetFromContentType(String contentType) {
|
||||
if (contentType == null || contentType.isEmpty()) {
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
// 提取charset参数(支持多种格式)
|
||||
String charsetStr = null;
|
||||
String[] parts = contentType.split(";");
|
||||
for (String part : parts) {
|
||||
part = part.trim().toLowerCase();
|
||||
if (part.startsWith("charset=")) {
|
||||
charsetStr = part.substring("charset=".length()).trim()
|
||||
.replace("\"", "").replace("'", "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 验证编码有效性
|
||||
if (charsetStr != null && !charsetStr.isEmpty()) {
|
||||
try {
|
||||
return Charset.forName(charsetStr);
|
||||
} catch (Exception e) {
|
||||
logger.warn("不支持的编码:" + charsetStr + ",使用默认UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
// 兜底编码(优先GBK,兼容中文邮件)
|
||||
try {
|
||||
return Charset.forName("GBK");
|
||||
} catch (Exception e) {
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码MIME编码的文本(主题/发件人名称等)
|
||||
*/
|
||||
private static String decodeMimeText(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return MimeUtility.decodeText(text);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// 多级降级处理
|
||||
try {
|
||||
return new String(text.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
} catch (Exception e1) {
|
||||
try {
|
||||
return new String(text.getBytes(StandardCharsets.ISO_8859_1), "GBK");
|
||||
} catch (Exception e2) {
|
||||
try {
|
||||
return new String(text.getBytes(StandardCharsets.ISO_8859_1), "GB2312");
|
||||
} catch (Exception e3) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载显式附件(保持原有逻辑)
|
||||
*/
|
||||
private static List<BizMailAttachments> downloadExplicitAttachments(Message message, String messageId, String saveBasePath) throws Exception {
|
||||
List<BizMailAttachments> attachments = new ArrayList<>();
|
||||
if (!message.isMimeType("multipart/*")) {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
MimeMultipart multipart = (MimeMultipart) message.getContent();
|
||||
File saveDir = new File(saveBasePath);
|
||||
if (!saveDir.exists()) {
|
||||
Files.createDirectories(saveDir.toPath());
|
||||
}
|
||||
|
||||
// 遍历所有显式附件
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart part = multipart.getBodyPart(i);
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
|
||||
try {
|
||||
BizMailAttachments attach = downloadSingleAttachment(part, messageId, saveDir);
|
||||
attachments.add(attach);
|
||||
} catch (Exception e) {
|
||||
logger.error("单附件下载失败(文件名:" + part.getFileName() + "):" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载单个附件(保持原有逻辑)
|
||||
*/
|
||||
private static BizMailAttachments downloadSingleAttachment(BodyPart part, String messageId, File saveDir) throws Exception {
|
||||
BizMailAttachments attachment = new BizMailAttachments();
|
||||
|
||||
// 1. 记录单个附件下载开始时间
|
||||
long attachDownloadStartTime = System.currentTimeMillis();
|
||||
String originalFileName = part.getFileName();
|
||||
String fileNameForLog = originalFileName == null ? "未知文件名" : decodeMimeText(originalFileName);
|
||||
logger.info("开始下载附件[" + fileNameForLog + "],开始时间:" + new Date(attachDownloadStartTime));
|
||||
|
||||
// 2. 修复:文件名解码(解决乱码)
|
||||
if (originalFileName != null) {
|
||||
originalFileName = decodeMimeText(originalFileName);
|
||||
} else {
|
||||
originalFileName = "unknown_" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// 3. 修复:附件FileType(优先从文件扩展名识别,解决ContentType错误)
|
||||
String fileExt = getFileExtension(originalFileName);
|
||||
String fileType = MIME_TYPE_MAP.getContentType(originalFileName);
|
||||
// 降级处理:如果MIME类型为空,使用BodyPart的ContentType
|
||||
if (fileType == null || fileType.isEmpty() || fileType.equals("application/octet-stream")) {
|
||||
fileType = part.getContentType().split(";")[0].trim(); // 去除charset等参数
|
||||
}
|
||||
|
||||
// 4. 计算MD5+保存文件
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
ByteBuffer buffer = BUFFER_LOCAL.get();
|
||||
buffer.clear();
|
||||
|
||||
// 临时文件
|
||||
File tempFile = new File(saveDir, UUID.randomUUID().toString());
|
||||
try (InputStream is = part.getInputStream();
|
||||
FileChannel channel = FileChannel.open(tempFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
|
||||
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer.array())) != -1) {
|
||||
md.update(buffer.array(), 0, bytesRead);
|
||||
buffer.limit(bytesRead);
|
||||
channel.write(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// MD5命名(避免重名)
|
||||
String md5 = bytesToHex(md.digest());
|
||||
File finalFile = new File(saveDir, md5 + (fileExt.isEmpty() ? "" : "." + fileExt));
|
||||
|
||||
// 处理文件已存在
|
||||
if (finalFile.exists()) {
|
||||
logger.warn("附件已存在(MD5:" + md5 + "),跳过重复保存");
|
||||
} else {
|
||||
if (!tempFile.renameTo(finalFile)) {
|
||||
logger.warn("附件重命名失败,使用临时文件名:" + tempFile.getName());
|
||||
finalFile = tempFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 记录单个附件下载结束时间
|
||||
long attachDownloadEndTime = System.currentTimeMillis();
|
||||
long costTime = attachDownloadEndTime - attachDownloadStartTime;
|
||||
logger.info("完成下载附件[" + originalFileName + "],结束时间:" + new Date(attachDownloadEndTime) +
|
||||
",耗时:" + costTime + "ms,文件路径:" + finalFile.getAbsolutePath());
|
||||
|
||||
// 6. 封装附件信息(修复FileType,增加下载时间字段)
|
||||
attachment.setStoragePath(finalFile.getAbsolutePath());
|
||||
attachment.setFileSize(finalFile.length());
|
||||
attachment.setCreateTime(new Date());
|
||||
attachment.setTid(System.currentTimeMillis());
|
||||
attachment.setMailId(System.currentTimeMillis());
|
||||
attachment.setMessageId(messageId);
|
||||
attachment.setFileName(originalFileName);
|
||||
attachment.setFileType(fileType); // 修复后的MIME类型
|
||||
attachment.setFileExt(fileExt);
|
||||
attachment.setFileMd5(md5);
|
||||
attachment.setDownloadCount(0);
|
||||
attachment.setIsCompressed(isCompressedFile(originalFileName) ? "1" : "0");
|
||||
attachment.setIsEncrypted("N");
|
||||
attachment.setDownloadStartTime(new Date(attachDownloadStartTime)); // 附件下载开始时间
|
||||
attachment.setDownloadEndTime(new Date(attachDownloadEndTime)); // 附件下载结束时间
|
||||
attachment.setDownloadCostTime(costTime); // 附件下载耗时(毫秒)
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有显式附件
|
||||
*/
|
||||
private static boolean hasExplicitAttachment(Message message) throws Exception {
|
||||
if (!message.isMimeType("multipart/*")) {
|
||||
return false;
|
||||
}
|
||||
MimeMultipart multipart = (MimeMultipart) message.getContent();
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(multipart.getBodyPart(i).getDisposition())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------ 工具方法 ------------------------
|
||||
private static String getMessageId(Message message) throws MessagingException {
|
||||
String[] ids = message.getHeader("Message-ID");
|
||||
if (ids != null && ids.length > 0) {
|
||||
return ids[0].replace("<", "").replace(">", "").trim();
|
||||
}
|
||||
return UUID.randomUUID().toString() + "@" + message.getSession().getProperty("mail.imap.host");
|
||||
}
|
||||
|
||||
private static String convertAddresses(Address[] addresses) throws Exception {
|
||||
if (addresses == null || addresses.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Address addr : addresses) {
|
||||
sb.append(decodeMimeText(addr.toString())).append(",");
|
||||
}
|
||||
return !sb.isEmpty() ? sb.substring(0, sb.length() - 1) : "";
|
||||
}
|
||||
|
||||
private static String getFileExtension(String fileName) {
|
||||
if (fileName == null || !fileName.contains(".")) {
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
||||
}
|
||||
|
||||
private static boolean isCompressedFile(String fileName) {
|
||||
Set<String> exts = new HashSet<>(Arrays.asList("zip", "rar", "7z", "tar", "gz", "bz2"));
|
||||
return exts.contains(getFileExtension(fileName));
|
||||
}
|
||||
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
char[] hex = new char[bytes.length * 2];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
int v = bytes[i] & 0xFF;
|
||||
hex[i * 2] = Character.forDigit(v >>> 4, 16);
|
||||
hex[i * 2 + 1] = Character.forDigit(v & 0x0F, 16);
|
||||
}
|
||||
return new String(hex).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jeesite.modules.biz.dao;
|
||||
|
||||
import com.jeesite.common.dao.CrudDao;
|
||||
import com.jeesite.common.mybatis.annotation.MyBatisDao;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
|
||||
/**
|
||||
* 邮件信息DAO接口
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@MyBatisDao(dataSourceName="work")
|
||||
public interface BizMailAccountDao extends CrudDao<BizMailAccount> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jeesite.modules.biz.dao;
|
||||
|
||||
import com.jeesite.common.dao.CrudDao;
|
||||
import com.jeesite.common.mybatis.annotation.MyBatisDao;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
|
||||
/**
|
||||
* 邮件附件表DAO接口
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@MyBatisDao(dataSourceName="work")
|
||||
public interface BizMailAttachmentsDao extends CrudDao<BizMailAttachments> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jeesite.modules.biz.dao;
|
||||
|
||||
import com.jeesite.common.dao.CrudDao;
|
||||
import com.jeesite.common.mybatis.annotation.MyBatisDao;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
|
||||
/**
|
||||
* 收件DAO接口
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@MyBatisDao(dataSourceName="work")
|
||||
public interface BizMailReceivedDao extends CrudDao<BizMailReceived> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jeesite.modules.biz.dao;
|
||||
|
||||
import com.jeesite.common.dao.CrudDao;
|
||||
import com.jeesite.common.mybatis.annotation.MyBatisDao;
|
||||
import com.jeesite.modules.biz.entity.BizMailSent;
|
||||
|
||||
/**
|
||||
* 发件DAO接口
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@MyBatisDao(dataSourceName="work")
|
||||
public interface BizMailSentDao extends CrudDao<BizMailSent> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.jeesite.modules.biz.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable;
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 邮件信息Entity
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table(name = "biz_mail_account", alias = "a", label = "邮件信息信息", columns = {
|
||||
@Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false),
|
||||
@Column(name = "id", attrName = "id", label = "主键ID", isPK = true),
|
||||
@Column(name = "account_name", attrName = "accountName", label = "配置名称"),
|
||||
@Column(name = "host", attrName = "host", label = "发送地址"),
|
||||
@Column(name = "smtp_port", attrName = "smtpPort", label = "SMTP端口", isQuery = false),
|
||||
@Column(name = "imap_host", attrName = "imapHost", label = "接收地址"),
|
||||
@Column(name = "imap_port", attrName = "imapPort", label = "IMAP端口", isQuery = false),
|
||||
@Column(name = "username", attrName = "username", label = "用户名称"),
|
||||
@Column(name = "password", attrName = "password", label = "用户密码", isQuery = false),
|
||||
@Column(name = "from_address", attrName = "fromAddress", label = "发件人地址"),
|
||||
@Column(name = "ssl_enable", attrName = "sslEnable", label = "是否启用SSL"),
|
||||
@Column(name = "ustatus", attrName = "ustatus", label = "状态"),
|
||||
@Column(name = "remark", attrName = "remark", label = "备注", isQuery = false),
|
||||
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false),
|
||||
@Column(name = "f_tenant_id", attrName = "ftenantId", label = "租户id", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_id", attrName = "fflowId", label = "流程id", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_task_id", attrName = "fflowTaskId", label = "流程任务主键", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_state", attrName = "fflowState", label = "流程任务状态", isUpdate = false, isQuery = false, isUpdateForce = true),
|
||||
}, orderBy = "a.create_time DESC"
|
||||
)
|
||||
@Data
|
||||
public class BizMailAccount extends DataEntity<BizMailAccount> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Date createTime; // 记录时间
|
||||
private String accountName;
|
||||
private String host; // 服务地址
|
||||
private Integer smtpPort; // SMTP端口
|
||||
private String imapHost;
|
||||
private Integer imapPort; // IMAP端口
|
||||
private String username; // 用户名称
|
||||
private String password; // 用户密码
|
||||
private String fromAddress; // 发件人地址
|
||||
private String sslEnable; // 是否启用SSL
|
||||
private String ustatus;
|
||||
private String remark; // 备注
|
||||
private Date updateTime; // 更新时间
|
||||
private String ftenantId; // 租户id
|
||||
private String fflowId; // 流程id
|
||||
private String fflowTaskId; // 流程任务主键
|
||||
private Integer fflowState; // 流程任务状态
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "主键标识", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "SMTP服务", attrName = "host", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "SMTP端口", attrName = "smtpPort", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "IMAP服务", attrName = "imapHost", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "IMAP端口", attrName = "imapPort", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "用户名称", attrName = "username", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "发件地址", attrName = "fromAddress", align = Align.CENTER, sort = 80),
|
||||
@ExcelField(title = "是否启用SSL", attrName = "sslEnable", dictType = "is_open", align = Align.CENTER, sort = 90),
|
||||
@ExcelField(title = "状态", attrName = "ustatus", dictType = "ustatus", align = Align.CENTER, sort = 100),
|
||||
@ExcelField(title = "备注", attrName = "remark", align = Align.CENTER, sort = 110),
|
||||
@ExcelField(title = "更新时间", attrName = "updateTime", align = Align.CENTER, sort = 120, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
})
|
||||
public BizMailAccount() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BizMailAccount(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Date getCreateTime_gte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_gte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.GTE, createTime);
|
||||
}
|
||||
|
||||
public Date getCreateTime_lte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.LTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_lte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.LTE, createTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.jeesite.modules.biz.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable;
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 邮件附件表Entity
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table(name = "biz_mail_attachments", alias = "a", label = "邮件附件表信息", columns = {
|
||||
@Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false, isUpdateForce = true),
|
||||
@Column(name = "id", attrName = "tid", label = "附件标识", isPK = true),
|
||||
@Column(name = "mail_id", attrName = "mailId", label = "收件标识"),
|
||||
@Column(name = "message_id", attrName = "messageId", label = "消息标识", isQuery = false),
|
||||
@Column(name = "file_name", attrName = "fileName", label = "附件名称", queryType = QueryType.LIKE),
|
||||
@Column(name = "file_size", attrName = "fileSize", label = "文件大小", isQuery = false),
|
||||
@Column(name = "file_type", attrName = "fileType", label = "文件类型", isQuery = false),
|
||||
@Column(name = "file_ext", attrName = "fileExt", label = "文件扩展名"),
|
||||
@Column(name = "storage_path", attrName = "storagePath", label = "存储路径", isQuery = false),
|
||||
@Column(name = "file_md5", attrName = "fileMd5", label = "文件MD5", isQuery = false),
|
||||
@Column(name = "download_count", attrName = "downloadCount", label = "下载次数", isQuery = false, isUpdateForce = true),
|
||||
@Column(name = "is_compressed", attrName = "isCompressed", label = "是否压缩"),
|
||||
@Column(name = "is_encrypted", attrName = "isEncrypted", label = "是否加密"),
|
||||
@Column(name = "download_start_time", attrName = "downloadStartTime", label = "下载开始时间"),
|
||||
@Column(name = "download_end_time", attrName = "downloadEndTime", label = "下载结束时间"),
|
||||
@Column(name = "download_cost_time", attrName = "downloadCostTime", label = "下载耗时"),
|
||||
}, orderBy = "a.create_time DESC"
|
||||
)
|
||||
@Data
|
||||
public class BizMailAttachments extends DataEntity<BizMailAttachments> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Date createTime; // 记录时间
|
||||
private Long tid; // 附件标识
|
||||
private Long mailId; // 收件标识
|
||||
private String messageId; // 消息标识
|
||||
private String fileName; // 附件名称
|
||||
private Long fileSize; // 文件大小
|
||||
private String fileType; // 文件类型
|
||||
private String fileExt; // 文件扩展名
|
||||
private String storagePath; // 存储路径
|
||||
private String fileMd5; // 文件MD5
|
||||
private Integer downloadCount; // 下载次数
|
||||
private String isCompressed; // 是否压缩
|
||||
private String isEncrypted; // 是否加密
|
||||
|
||||
private Date downloadStartTime; // 附件下载开始时间
|
||||
private Date downloadEndTime; // 附件下载结束时间
|
||||
private Long downloadCostTime; // 附件下载耗时(毫秒)
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "附件标识", attrName = "tid", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "收件标识", attrName = "mailId", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "消息标识", attrName = "messageId", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "附件名称", attrName = "fileName", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "文件大小", attrName = "fileSize", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "文件类型", attrName = "fileType", align = Align.CENTER, sort = 70),
|
||||
@ExcelField(title = "文件扩展名", attrName = "fileExt", align = Align.CENTER, sort = 80),
|
||||
@ExcelField(title = "存储路径", attrName = "storagePath", align = Align.CENTER, sort = 90),
|
||||
@ExcelField(title = "文件MD5", attrName = "fileMd5", align = Align.CENTER, sort = 100),
|
||||
@ExcelField(title = "下载次数", attrName = "downloadCount", align = Align.CENTER, sort = 110),
|
||||
@ExcelField(title = "是否压缩", attrName = "isCompressed", align = Align.CENTER, sort = 120),
|
||||
@ExcelField(title = "是否加密", attrName = "isEncrypted", align = Align.CENTER, sort = 130),
|
||||
})
|
||||
public BizMailAttachments() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BizMailAttachments(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Date getCreateTime_gte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_gte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.GTE, createTime);
|
||||
}
|
||||
|
||||
public Date getCreateTime_lte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.LTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_lte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.LTE, createTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.jeesite.modules.biz.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable;
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 收件Entity
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table(name = "biz_mail_received", alias = "a", label = "收件信息", columns = {
|
||||
@Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false),
|
||||
@Column(name = "id", attrName = "id", label = "主键ID", isPK = true),
|
||||
@Column(name = "message_id", attrName = "messageId", label = "邮件服务器消息ID", isQuery = false),
|
||||
@Column(name = "account_id", attrName = "accountId", label = "邮件账户标识"),
|
||||
@Column(name = "from_address", attrName = "fromAddress", label = "发件人地址", isQuery = false),
|
||||
@Column(name = "from_name", attrName = "fromName", label = "发件人名称", queryType = QueryType.LIKE),
|
||||
@Column(name = "to_addresses", attrName = "toAddresses", label = "收件人地址", isQuery = false),
|
||||
@Column(name = "cc_addresses", attrName = "ccAddresses", label = "抄送地址", isQuery = false),
|
||||
@Column(name = "bcc_addresses", attrName = "bccAddresses", label = "密送地址", isQuery = false),
|
||||
@Column(name = "subject", attrName = "subject", label = "邮件主题", queryType = QueryType.LIKE),
|
||||
@Column(name = "mail_content", attrName = "mailContent", label = "邮件内容", isQuery = false),
|
||||
@Column(name = "received_time", attrName = "receivedTime", label = "接收时间", isQuery = false),
|
||||
@Column(name = "send_time", attrName = "sendTime", label = "发送时间", isQuery = false, isUpdateForce = true),
|
||||
@Column(name = "has_attachment", attrName = "hasAttachment", label = "是否有附件"),
|
||||
@Column(name = "mailbox", attrName = "mailbox", label = "mailbox", isQuery = false),
|
||||
@Column(name = "ustatus", attrName = "ustatus", label = "状态"),
|
||||
}, orderBy = "a.id DESC"
|
||||
)
|
||||
@Data
|
||||
public class BizMailReceived extends DataEntity<BizMailReceived> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Date createTime; // 记录时间
|
||||
private String messageId; // 邮件服务器消息ID
|
||||
private String accountId; // 邮件账户标识
|
||||
private String fromAddress; // 发件人地址
|
||||
private String fromName; // 发件人名称
|
||||
private String toAddresses; // 收件人地址
|
||||
private String ccAddresses; // 抄送地址
|
||||
private String bccAddresses; // 密送地址
|
||||
private String subject; // 邮件主题
|
||||
private String mailContent; // 邮件内容
|
||||
private Date receivedTime; // 接收时间
|
||||
private Date sendTime; // 发送时间
|
||||
private String hasAttachment; // 是否有附件
|
||||
private String mailbox; // mailbox
|
||||
private String ustatus; // 状态
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "主键ID", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "邮件服务器消息ID", attrName = "messageId", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "邮件账户标识", attrName = "accountId", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "发件人地址", attrName = "fromAddress", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "发件人名称", attrName = "fromName", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "收件人地址", attrName = "toAddresses", align = Align.CENTER, sort = 70),
|
||||
@ExcelField(title = "抄送地址", attrName = "ccAddresses", align = Align.CENTER, sort = 80),
|
||||
@ExcelField(title = "密送地址", attrName = "bccAddresses", align = Align.CENTER, sort = 90),
|
||||
@ExcelField(title = "邮件主题", attrName = "subject", align = Align.CENTER, sort = 100),
|
||||
@ExcelField(title = "邮件内容", attrName = "mailContent", align = Align.CENTER, sort = 110),
|
||||
@ExcelField(title = "接收时间", attrName = "receivedTime", align = Align.CENTER, sort = 120, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "发送时间", attrName = "sendTime", align = Align.CENTER, sort = 130, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "是否有附件", attrName = "hasAttachment", align = Align.CENTER, sort = 140),
|
||||
@ExcelField(title = "状态", attrName = "ustatus", align = Align.CENTER, sort = 160),
|
||||
})
|
||||
public BizMailReceived() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BizMailReceived(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Date getCreateTime_gte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_gte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.GTE, createTime);
|
||||
}
|
||||
|
||||
public Date getCreateTime_lte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.LTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_lte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.LTE, createTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.jeesite.modules.biz.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable;
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 发件Entity
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table(name = "biz_mail_sent", alias = "a", label = "发件信息", columns = {
|
||||
@Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false, isUpdateForce = true),
|
||||
@Column(name = "id", attrName = "id", label = "主键标识", isPK = true),
|
||||
@Column(name = "message_id", attrName = "messageId", label = "件服务器消息标识", isQuery = false),
|
||||
@Column(name = "account_id", attrName = "accountId", label = "邮件账户标识"),
|
||||
@Column(name = "from_address", attrName = "fromAddress", label = "发件人地址", queryType = QueryType.LIKE),
|
||||
@Column(name = "to_addresses", attrName = "toAddresses", label = "收件人地址", isQuery = false),
|
||||
@Column(name = "cc_addresses", attrName = "ccAddresses", label = "抄送人地址", isQuery = false),
|
||||
@Column(name = "subject", attrName = "subject", label = "邮件主题", queryType = QueryType.LIKE),
|
||||
@Column(name = "content", attrName = "content", label = "邮件内容", isQuery = false),
|
||||
@Column(name = "send_time", attrName = "sendTime", label = "发送时间", isQuery = false, isUpdateForce = true),
|
||||
@Column(name = "send_status", attrName = "sendStatus", label = "发送状态"),
|
||||
@Column(name = "error_msg", attrName = "errorMsg", label = "错误信息", isQuery = false),
|
||||
@Column(name = "has_attachment", attrName = "hasAttachment", label = "是否有附件"),
|
||||
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true),
|
||||
@Column(name = "f_tenant_id", attrName = "ftenantId", label = "租户id", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_id", attrName = "fflowId", label = "流程id", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_task_id", attrName = "fflowTaskId", label = "流程任务主键", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_state", attrName = "fflowState", label = "流程任务状态", isUpdate = false, isQuery = false, isUpdateForce = true),
|
||||
}, orderBy = "a.create_time DESC"
|
||||
)
|
||||
@Data
|
||||
public class BizMailSent extends DataEntity<BizMailSent> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Date createTime; // 记录时间
|
||||
private String messageId; // 件服务器消息标识
|
||||
private String accountId; // 邮件账户标识
|
||||
private String fromAddress; // 发件人地址
|
||||
private String toAddresses; // 收件人地址
|
||||
private String ccAddresses; // 抄送人地址
|
||||
private String subject; // 邮件主题
|
||||
private String content; // 邮件内容
|
||||
private Date sendTime; // 发送时间
|
||||
private String sendStatus; // 发送状态
|
||||
private String errorMsg; // 错误信息
|
||||
private String hasAttachment; // 是否有附件
|
||||
private Date updateTime; // 更新时间
|
||||
private String ftenantId; // 租户id
|
||||
private String fflowId; // 流程id
|
||||
private String fflowTaskId; // 流程任务主键
|
||||
private Integer fflowState; // 流程任务状态
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "主键标识", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "件服务器消息标识", attrName = "messageId", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "邮件账户标识", attrName = "accountId", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "发件人地址", attrName = "fromAddress", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "收件人地址", attrName = "toAddresses", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "抄送人地址", attrName = "ccAddresses", align = Align.CENTER, sort = 70),
|
||||
@ExcelField(title = "邮件主题", attrName = "subject", align = Align.CENTER, sort = 80),
|
||||
@ExcelField(title = "邮件内容", attrName = "content", align = Align.CENTER, sort = 90),
|
||||
@ExcelField(title = "发送时间", attrName = "sendTime", align = Align.CENTER, sort = 100, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "发送状态", attrName = "sendStatus", align = Align.CENTER, sort = 110),
|
||||
@ExcelField(title = "错误信息", attrName = "errorMsg", align = Align.CENTER, sort = 120),
|
||||
@ExcelField(title = "是否有附件", attrName = "hasAttachment", align = Align.CENTER, sort = 130),
|
||||
@ExcelField(title = "更新时间", attrName = "updateTime", align = Align.CENTER, sort = 140, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
})
|
||||
public BizMailSent() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BizMailSent(String id) {
|
||||
super(id);
|
||||
}
|
||||
public Date getCreateTime_gte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_gte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.GTE, createTime);
|
||||
}
|
||||
|
||||
public Date getCreateTime_lte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.LTE);
|
||||
}
|
||||
|
||||
public void setCreateTime_lte(Date createTime) {
|
||||
sqlMap.getWhere().and("create_time", QueryType.LTE, createTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.jeesite.modules.biz.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.dao.BizMailAccountDao;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.validator.ValidatorUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 邮件信息Service
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Service
|
||||
public class BizMailAccountService extends CrudService<BizMailAccountDao, BizMailAccount> {
|
||||
|
||||
/**
|
||||
* 获取单条数据
|
||||
* @param bizMailAccount 主键
|
||||
*/
|
||||
@Override
|
||||
public BizMailAccount get(BizMailAccount bizMailAccount) {
|
||||
return super.get(bizMailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分页数据
|
||||
* @param bizMailAccount 查询条件
|
||||
* @param bizMailAccount page 分页对象
|
||||
*/
|
||||
@Override
|
||||
public Page<BizMailAccount> findPage(BizMailAccount bizMailAccount) {
|
||||
return super.findPage(bizMailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
* @param bizMailAccount 查询条件
|
||||
*/
|
||||
@Override
|
||||
public List<BizMailAccount> findList(BizMailAccount bizMailAccount) {
|
||||
return super.findList(bizMailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据(插入或更新)
|
||||
* @param bizMailAccount 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(BizMailAccount bizMailAccount) {
|
||||
super.save(bizMailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
* @param file 导入的数据文件
|
||||
*/
|
||||
@Transactional
|
||||
public String importData(MultipartFile file) {
|
||||
if (file == null){
|
||||
throw new ServiceException(text("请选择导入的数据文件!"));
|
||||
}
|
||||
int successNum = 0; int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
try(ExcelImport ei = new ExcelImport(file, 2, 0)){
|
||||
List<BizMailAccount> list = ei.getDataList(BizMailAccount.class);
|
||||
for (BizMailAccount bizMailAccount : list) {
|
||||
try{
|
||||
ValidatorUtils.validateWithException(bizMailAccount);
|
||||
this.save(bizMailAccount);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、编号 " + bizMailAccount.getId() + " 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、编号 " + bizMailAccount.getId() + " 导入失败:";
|
||||
if (e instanceof ConstraintViolationException){
|
||||
ConstraintViolationException cve = (ConstraintViolationException)e;
|
||||
for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
|
||||
msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")";
|
||||
}
|
||||
}else{
|
||||
msg += e.getMessage();
|
||||
}
|
||||
failureMsg.append(msg);
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
failureMsg.append(e.getMessage());
|
||||
return failureMsg.toString();
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
}else{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param bizMailAccount 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateStatus(BizMailAccount bizMailAccount) {
|
||||
super.updateStatus(bizMailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param bizMailAccount 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(BizMailAccount bizMailAccount) {
|
||||
super.delete(bizMailAccount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.jeesite.modules.biz.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.dao.BizMailAttachmentsDao;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.validator.ValidatorUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 邮件附件表Service
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Service
|
||||
public class BizMailAttachmentsService extends CrudService<BizMailAttachmentsDao, BizMailAttachments> {
|
||||
|
||||
/**
|
||||
* 获取单条数据
|
||||
* @param bizMailAttachments 主键
|
||||
*/
|
||||
@Override
|
||||
public BizMailAttachments get(BizMailAttachments bizMailAttachments) {
|
||||
return super.get(bizMailAttachments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分页数据
|
||||
* @param bizMailAttachments 查询条件
|
||||
* @param bizMailAttachments page 分页对象
|
||||
*/
|
||||
@Override
|
||||
public Page<BizMailAttachments> findPage(BizMailAttachments bizMailAttachments) {
|
||||
return super.findPage(bizMailAttachments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
* @param bizMailAttachments 查询条件
|
||||
*/
|
||||
@Override
|
||||
public List<BizMailAttachments> findList(BizMailAttachments bizMailAttachments) {
|
||||
return super.findList(bizMailAttachments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据(插入或更新)
|
||||
* @param bizMailAttachments 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(BizMailAttachments bizMailAttachments) {
|
||||
super.save(bizMailAttachments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
* @param file 导入的数据文件
|
||||
*/
|
||||
@Transactional
|
||||
public String importData(MultipartFile file) {
|
||||
if (file == null){
|
||||
throw new ServiceException(text("请选择导入的数据文件!"));
|
||||
}
|
||||
int successNum = 0; int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
try(ExcelImport ei = new ExcelImport(file, 2, 0)){
|
||||
List<BizMailAttachments> list = ei.getDataList(BizMailAttachments.class);
|
||||
for (BizMailAttachments bizMailAttachments : list) {
|
||||
try{
|
||||
ValidatorUtils.validateWithException(bizMailAttachments);
|
||||
this.save(bizMailAttachments);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、编号 " + bizMailAttachments.getId() + " 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、编号 " + bizMailAttachments.getId() + " 导入失败:";
|
||||
if (e instanceof ConstraintViolationException){
|
||||
ConstraintViolationException cve = (ConstraintViolationException)e;
|
||||
for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
|
||||
msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")";
|
||||
}
|
||||
}else{
|
||||
msg += e.getMessage();
|
||||
}
|
||||
failureMsg.append(msg);
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
failureMsg.append(e.getMessage());
|
||||
return failureMsg.toString();
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
}else{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param bizMailAttachments 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateStatus(BizMailAttachments bizMailAttachments) {
|
||||
super.updateStatus(bizMailAttachments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param bizMailAttachments 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(BizMailAttachments bizMailAttachments) {
|
||||
super.delete(bizMailAttachments);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.jeesite.modules.biz.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
import com.jeesite.modules.biz.dao.BizMailReceivedDao;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.validator.ValidatorUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 收件Service
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Service
|
||||
public class BizMailReceivedService extends CrudService<BizMailReceivedDao, BizMailReceived> {
|
||||
|
||||
/**
|
||||
* 获取单条数据
|
||||
* @param bizMailReceived 主键
|
||||
*/
|
||||
@Override
|
||||
public BizMailReceived get(BizMailReceived bizMailReceived) {
|
||||
return super.get(bizMailReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分页数据
|
||||
* @param bizMailReceived 查询条件
|
||||
* @param bizMailReceived page 分页对象
|
||||
*/
|
||||
@Override
|
||||
public Page<BizMailReceived> findPage(BizMailReceived bizMailReceived) {
|
||||
return super.findPage(bizMailReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
* @param bizMailReceived 查询条件
|
||||
*/
|
||||
@Override
|
||||
public List<BizMailReceived> findList(BizMailReceived bizMailReceived) {
|
||||
return super.findList(bizMailReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据(插入或更新)
|
||||
* @param bizMailReceived 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(BizMailReceived bizMailReceived) {
|
||||
super.save(bizMailReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
* @param file 导入的数据文件
|
||||
*/
|
||||
@Transactional
|
||||
public String importData(MultipartFile file) {
|
||||
if (file == null){
|
||||
throw new ServiceException(text("请选择导入的数据文件!"));
|
||||
}
|
||||
int successNum = 0; int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
try(ExcelImport ei = new ExcelImport(file, 2, 0)){
|
||||
List<BizMailReceived> list = ei.getDataList(BizMailReceived.class);
|
||||
for (BizMailReceived bizMailReceived : list) {
|
||||
try{
|
||||
ValidatorUtils.validateWithException(bizMailReceived);
|
||||
this.save(bizMailReceived);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、编号 " + bizMailReceived.getId() + " 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、编号 " + bizMailReceived.getId() + " 导入失败:";
|
||||
if (e instanceof ConstraintViolationException){
|
||||
ConstraintViolationException cve = (ConstraintViolationException)e;
|
||||
for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
|
||||
msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")";
|
||||
}
|
||||
}else{
|
||||
msg += e.getMessage();
|
||||
}
|
||||
failureMsg.append(msg);
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
failureMsg.append(e.getMessage());
|
||||
return failureMsg.toString();
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
}else{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param bizMailReceived 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateStatus(BizMailReceived bizMailReceived) {
|
||||
super.updateStatus(bizMailReceived);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param bizMailReceived 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(BizMailReceived bizMailReceived) {
|
||||
super.delete(bizMailReceived);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.jeesite.modules.biz.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.modules.biz.entity.BizMailSent;
|
||||
import com.jeesite.modules.biz.dao.BizMailSentDao;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.modules.file.utils.FileUploadUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.validator.ValidatorUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 发件Service
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Service
|
||||
public class BizMailSentService extends CrudService<BizMailSentDao, BizMailSent> {
|
||||
|
||||
/**
|
||||
* 获取单条数据
|
||||
* @param bizMailSent 主键
|
||||
*/
|
||||
@Override
|
||||
public BizMailSent get(BizMailSent bizMailSent) {
|
||||
return super.get(bizMailSent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分页数据
|
||||
* @param bizMailSent 查询条件
|
||||
* @param bizMailSent page 分页对象
|
||||
*/
|
||||
@Override
|
||||
public Page<BizMailSent> findPage(BizMailSent bizMailSent) {
|
||||
return super.findPage(bizMailSent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
* @param bizMailSent 查询条件
|
||||
*/
|
||||
@Override
|
||||
public List<BizMailSent> findList(BizMailSent bizMailSent) {
|
||||
return super.findList(bizMailSent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据(插入或更新)
|
||||
* @param bizMailSent 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(BizMailSent bizMailSent) {
|
||||
super.save(bizMailSent);
|
||||
// 保存上传附件
|
||||
FileUploadUtils.saveFileUpload(bizMailSent, bizMailSent.getId(), "bizMailSent_file");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
* @param file 导入的数据文件
|
||||
*/
|
||||
@Transactional
|
||||
public String importData(MultipartFile file) {
|
||||
if (file == null){
|
||||
throw new ServiceException(text("请选择导入的数据文件!"));
|
||||
}
|
||||
int successNum = 0; int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
try(ExcelImport ei = new ExcelImport(file, 2, 0)){
|
||||
List<BizMailSent> list = ei.getDataList(BizMailSent.class);
|
||||
for (BizMailSent bizMailSent : list) {
|
||||
try{
|
||||
ValidatorUtils.validateWithException(bizMailSent);
|
||||
this.save(bizMailSent);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、编号 " + bizMailSent.getId() + " 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、编号 " + bizMailSent.getId() + " 导入失败:";
|
||||
if (e instanceof ConstraintViolationException){
|
||||
ConstraintViolationException cve = (ConstraintViolationException)e;
|
||||
for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
|
||||
msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")";
|
||||
}
|
||||
}else{
|
||||
msg += e.getMessage();
|
||||
}
|
||||
failureMsg.append(msg);
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
failureMsg.append(e.getMessage());
|
||||
return failureMsg.toString();
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
}else{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param bizMailSent 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateStatus(BizMailSent bizMailSent) {
|
||||
super.updateStatus(bizMailSent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param bizMailSent 数据对象
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(BizMailSent bizMailSent) {
|
||||
super.delete(bizMailSent);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.jeesite.modules.app.dao.MailReceived;
|
||||
import com.jeesite.modules.app.utils.MailReceiveUtils;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
import com.jeesite.modules.biz.service.BizMailAttachmentsService;
|
||||
import com.jeesite.modules.biz.service.BizMailReceivedService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelExport;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.service.BizMailAccountService;
|
||||
|
||||
/**
|
||||
* 邮件信息Controller
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/biz/mailAccount")
|
||||
public class BizMailAccountController extends BaseController {
|
||||
|
||||
private final BizMailAccountService bizMailAccountService;
|
||||
|
||||
private static final ExecutorService MAIL_EXECUTOR = Executors.newFixedThreadPool(5);
|
||||
|
||||
@Resource
|
||||
private BizMailReceivedService receivedService;
|
||||
|
||||
@Resource
|
||||
private BizMailAttachmentsService attachmentsService;
|
||||
|
||||
|
||||
private String MAIL_PATH = "/ogsapp/mail";
|
||||
|
||||
public BizMailAccountController(BizMailAccountService bizMailAccountService) {
|
||||
this.bizMailAccountService = bizMailAccountService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailAccount get(String id, boolean isNewRecord) {
|
||||
return bizMailAccountService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailAccount bizMailAccount, Model model) {
|
||||
model.addAttribute("bizMailAccount", bizMailAccount);
|
||||
return "modules/biz/bizMailAccountList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailAccount> listData(BizMailAccount bizMailAccount, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailAccount.setPage(new Page<>(request, response));
|
||||
Page<BizMailAccount> page = bizMailAccountService.findPage(bizMailAccount);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailAccount bizMailAccount, Model model) {
|
||||
model.addAttribute("bizMailAccount", bizMailAccount);
|
||||
return "modules/biz/bizMailAccountForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailAccount bizMailAccount) {
|
||||
bizMailAccountService.save(bizMailAccount);
|
||||
return renderResult(Global.TRUE, text("保存邮件信息成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailAccount bizMailAccount, HttpServletResponse response) {
|
||||
List<BizMailAccount> list = bizMailAccountService.findList(bizMailAccount);
|
||||
String fileName = "邮件信息" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("邮件信息", BizMailAccount.class)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailAccount bizMailAccount = new BizMailAccount();
|
||||
List<BizMailAccount> list = ListUtils.newArrayList(bizMailAccount);
|
||||
String fileName = "邮件信息模板.xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("邮件信息", BizMailAccount.class, Type.IMPORT)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailAccount:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailAccountService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:" + message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAccount:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailAccount bizMailAccount) {
|
||||
bizMailAccountService.delete(bizMailAccount);
|
||||
return renderResult(Global.TRUE, text("删除邮件信息成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件接收
|
||||
*/
|
||||
@RequestMapping(value = "received")
|
||||
@ResponseBody
|
||||
public String received(BizMailAccount bizMailAccount) {
|
||||
MAIL_EXECUTOR.submit(() -> {
|
||||
try {
|
||||
List<MailReceived> receivedList = MailReceiveUtils.receiveUnreadMails(bizMailAccount, MAIL_PATH);
|
||||
for (MailReceived mailReceived : receivedList) {
|
||||
BizMailReceived received = mailReceived.getReceived();
|
||||
List<BizMailAttachments> attachments = mailReceived.getAttachments();
|
||||
for (BizMailAttachments mailAttachments : attachments) {
|
||||
attachmentsService.insert(mailAttachments);
|
||||
}
|
||||
receivedService.save(received);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("后台处理邮件失败", e.getMessage());
|
||||
}
|
||||
});
|
||||
return renderResult(Global.TRUE, text("操作接收邮件成功!"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelExport;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.service.BizMailAttachmentsService;
|
||||
|
||||
/**
|
||||
* 邮件附件表Controller
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/biz/mailAttachments")
|
||||
public class BizMailAttachmentsController extends BaseController {
|
||||
|
||||
private final BizMailAttachmentsService bizMailAttachmentsService;
|
||||
|
||||
public BizMailAttachmentsController(BizMailAttachmentsService bizMailAttachmentsService) {
|
||||
this.bizMailAttachmentsService = bizMailAttachmentsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailAttachments get(Long tid, boolean isNewRecord) {
|
||||
return bizMailAttachmentsService.get(tid, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailAttachments> listData(BizMailAttachments bizMailAttachments, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailAttachments.setPage(new Page<>(request, response));
|
||||
Page<BizMailAttachments> page = bizMailAttachmentsService.findPage(bizMailAttachments);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.save(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("保存邮件附件表成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailAttachments bizMailAttachments, HttpServletResponse response) {
|
||||
List<BizMailAttachments> list = bizMailAttachmentsService.findList(bizMailAttachments);
|
||||
String fileName = "邮件附件表" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailAttachments bizMailAttachments = new BizMailAttachments();
|
||||
List<BizMailAttachments> list = ListUtils.newArrayList(bizMailAttachments);
|
||||
String fileName = "邮件附件表模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailAttachmentsService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.delete(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("删除邮件附件表成功!"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelExport;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
import com.jeesite.modules.biz.service.BizMailReceivedService;
|
||||
|
||||
/**
|
||||
* 收件Controller
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/biz/mailReceived")
|
||||
public class BizMailReceivedController extends BaseController {
|
||||
|
||||
private final BizMailReceivedService bizMailReceivedService;
|
||||
|
||||
public BizMailReceivedController(BizMailReceivedService bizMailReceivedService) {
|
||||
this.bizMailReceivedService = bizMailReceivedService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailReceived get(String id, boolean isNewRecord) {
|
||||
return bizMailReceivedService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailReceived> listData(BizMailReceived bizMailReceived, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailReceived.setPage(new Page<>(request, response));
|
||||
Page<BizMailReceived> page = bizMailReceivedService.findPage(bizMailReceived);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.save(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("保存收件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailReceived bizMailReceived, HttpServletResponse response) {
|
||||
List<BizMailReceived> list = bizMailReceivedService.findList(bizMailReceived);
|
||||
String fileName = "收件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("收件", BizMailReceived.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailReceived bizMailReceived = new BizMailReceived();
|
||||
List<BizMailReceived> list = ListUtils.newArrayList(bizMailReceived);
|
||||
String fileName = "收件模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("收件", BizMailReceived.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailReceivedService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.delete(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("删除收件成功!"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelExport;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.biz.entity.BizMailSent;
|
||||
import com.jeesite.modules.biz.service.BizMailSentService;
|
||||
|
||||
/**
|
||||
* 发件Controller
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/biz/mailSent")
|
||||
public class BizMailSentController extends BaseController {
|
||||
|
||||
private final BizMailSentService bizMailSentService;
|
||||
|
||||
public BizMailSentController(BizMailSentService bizMailSentService) {
|
||||
this.bizMailSentService = bizMailSentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailSent get(String id, boolean isNewRecord) {
|
||||
return bizMailSentService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailSent> listData(BizMailSent bizMailSent, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailSent.setPage(new Page<>(request, response));
|
||||
Page<BizMailSent> page = bizMailSentService.findPage(bizMailSent);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailSent bizMailSent) {
|
||||
bizMailSentService.save(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("保存发件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailSent bizMailSent, HttpServletResponse response) {
|
||||
List<BizMailSent> list = bizMailSentService.findList(bizMailSent);
|
||||
String fileName = "发件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("发件", BizMailSent.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailSent bizMailSent = new BizMailSent();
|
||||
List<BizMailSent> list = ListUtils.newArrayList(bizMailSent);
|
||||
String fileName = "发件模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("发件", BizMailSent.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailSentService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailSent bizMailSent) {
|
||||
bizMailSentService.delete(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("删除发件成功!"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user