|
@@ -13,17 +13,21 @@ import com.smppw.modaq.domain.dto.MailboxInfoDTO;
|
|
import com.smppw.modaq.infrastructure.util.ExcelUtil;
|
|
import com.smppw.modaq.infrastructure.util.ExcelUtil;
|
|
import com.smppw.modaq.infrastructure.util.FileUtil;
|
|
import com.smppw.modaq.infrastructure.util.FileUtil;
|
|
import com.sun.mail.imap.IMAPStore;
|
|
import com.sun.mail.imap.IMAPStore;
|
|
-import jakarta.activation.DataHandler;
|
|
|
|
-import jakarta.mail.*;
|
|
|
|
-import jakarta.mail.internet.*;
|
|
|
|
-import jakarta.mail.util.ByteArrayDataSource;
|
|
|
|
|
|
+import jakarta.mail.Message;
|
|
|
|
+import jakarta.mail.MessagingException;
|
|
|
|
+import jakarta.mail.Session;
|
|
|
|
+import jakarta.mail.Store;
|
|
|
|
+import jakarta.mail.internet.MimeBodyPart;
|
|
|
|
+import jakarta.mail.internet.MimeMultipart;
|
|
|
|
+import jakarta.mail.internet.MimeUtility;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
-import java.nio.file.Files;
|
|
|
|
-import java.nio.file.Paths;
|
|
|
|
-import java.util.*;
|
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.Properties;
|
|
|
|
|
|
/**
|
|
/**
|
|
* @author mozuwen
|
|
* @author mozuwen
|
|
@@ -51,7 +55,7 @@ public class EmailUtil {
|
|
String emailTitle = message.getSubject();
|
|
String emailTitle = message.getSubject();
|
|
String emailDate = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDDHHMMSS24);
|
|
String emailDate = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDDHHMMSS24);
|
|
String emailDateStr = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDD);
|
|
String emailDateStr = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDD);
|
|
- String filePath = path + "/" + emailAddress + "/" + emailDateStr + "/";
|
|
|
|
|
|
+ String filePath = path + File.separator + emailAddress + File.separator + emailDateStr + File.separator;
|
|
|
|
|
|
MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
|
|
MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
|
|
int length = mimeMultipart.getCount();
|
|
int length = mimeMultipart.getCount();
|
|
@@ -59,50 +63,54 @@ public class EmailUtil {
|
|
for (int i = 0; i < length; i++) {
|
|
for (int i = 0; i < length; i++) {
|
|
EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
|
|
EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
|
|
MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(i);
|
|
MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(i);
|
|
-// Object partContent = part.getContent();
|
|
|
|
|
|
+ Object partContent = part.getContent();
|
|
String contentClass = part.getContent().getClass().getSimpleName();
|
|
String contentClass = part.getContent().getClass().getSimpleName();
|
|
// 1.邮件正文
|
|
// 1.邮件正文
|
|
- if ("String".equals(contentClass)) {
|
|
|
|
-// // 文件名 = 邮件主题 + 邮件日期
|
|
|
|
-// String fileName = emailTitle + "_" + emailDate + ".html";
|
|
|
|
-// String content = partContent.toString();
|
|
|
|
-// emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
|
|
|
|
- } else if ("BASE64DecoderStream".equals(contentClass)) {
|
|
|
|
- if (StrUtil.isNotBlank(part.getFileName())) {
|
|
|
|
- String fileName = MimeUtility.decodeText(part.getFileName());
|
|
|
|
- if (!isSupportedFileType(fileName)) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- emailContentInfoDTO.setFileName(fileName);
|
|
|
|
|
|
+ switch (contentClass) {
|
|
|
|
+ case "String" -> {
|
|
|
|
+ // 文件名 = 邮件主题 + 邮件日期
|
|
|
|
+ String fileName = emailTitle + "_" + emailDate + ".html";
|
|
|
|
+ String content = partContent.toString();
|
|
|
|
+ emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
|
|
|
|
+ }
|
|
|
|
+ case "BASE64DecoderStream" -> {
|
|
|
|
+ if (StrUtil.isNotBlank(part.getFileName())) {
|
|
|
|
+ String fileName = MimeUtility.decodeText(part.getFileName());
|
|
|
|
+ if (isSupportedFileType(fileName)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ emailContentInfoDTO.setFileName(fileName);
|
|
|
|
|
|
- String realPath = filePath + emailDate + fileName;
|
|
|
|
|
|
+ String realPath = filePath + emailDate + fileName;
|
|
|
|
|
|
- File saveFile = cn.hutool.core.io.FileUtil.file(realPath);
|
|
|
|
- if (!saveFile.exists()) {
|
|
|
|
- if (!saveFile.getParentFile().exists()) {
|
|
|
|
- saveFile.getParentFile().mkdirs();
|
|
|
|
|
|
+ File saveFile = cn.hutool.core.io.FileUtil.file(realPath);
|
|
|
|
+ if (!saveFile.exists()) {
|
|
|
|
+ if (!saveFile.getParentFile().exists()) {
|
|
|
|
+ saveFile.getParentFile().mkdirs();
|
|
|
|
+ }
|
|
|
|
+ FileUtil.saveFile(saveFile, part);
|
|
|
|
+ } else {
|
|
|
|
+ cn.hutool.core.io.FileUtil.del(saveFile);
|
|
|
|
+ FileUtil.saveFile(saveFile, part);
|
|
|
|
+ }
|
|
|
|
+ emailContentInfoDTO.setFilePath(realPath);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ case "MimeMultipart" -> {
|
|
|
|
+ MimeMultipart contentPart = (MimeMultipart) partContent;
|
|
|
|
+ int length2 = contentPart.getCount();
|
|
|
|
+ for (int i2 = 0; i2 < length2; i2++) {
|
|
|
|
+ part = (MimeBodyPart) contentPart.getBodyPart(i2);
|
|
|
|
+ partContent = part.getContent();
|
|
|
|
+ contentClass = partContent.getClass().getSimpleName();
|
|
|
|
+ if ("String".equals(contentClass)) {
|
|
|
|
+ // 文件名 = 邮件主题 + 邮件日期
|
|
|
|
+ String fileName = emailTitle + "_" + emailDate + ".html";
|
|
|
|
+ String content = partContent.toString();
|
|
|
|
+ emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
|
|
}
|
|
}
|
|
- FileUtil.saveFile(saveFile, part);
|
|
|
|
- } else {
|
|
|
|
- cn.hutool.core.io.FileUtil.del(saveFile);
|
|
|
|
- FileUtil.saveFile(saveFile, part);
|
|
|
|
}
|
|
}
|
|
- emailContentInfoDTO.setFilePath(realPath);
|
|
|
|
}
|
|
}
|
|
- } else if ("MimeMultipart".equals(contentClass)) {
|
|
|
|
-// MimeMultipart contentPart = (MimeMultipart) partContent;
|
|
|
|
-// int length2 = contentPart.getCount();
|
|
|
|
-// for (int i2 = 0; i2 < length2; i2++) {
|
|
|
|
-// part = (MimeBodyPart) contentPart.getBodyPart(i2);
|
|
|
|
-// partContent = part.getContent();
|
|
|
|
-// contentClass = partContent.getClass().getSimpleName();
|
|
|
|
-// if ("String".equals(contentClass)) {
|
|
|
|
-// // 文件名 = 邮件主题 + 邮件日期
|
|
|
|
-// String fileName = emailTitle + "_" + emailDate + ".html";
|
|
|
|
-// String content = partContent.toString();
|
|
|
|
-// emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
|
|
|
|
-// }
|
|
|
|
-// }
|
|
|
|
}
|
|
}
|
|
String filepath = emailContentInfoDTO.getFilePath();
|
|
String filepath = emailContentInfoDTO.getFilePath();
|
|
if (emailContentInfoDTO.getEmailContent() == null && filepath == null) {
|
|
if (emailContentInfoDTO.getEmailContent() == null && filepath == null) {
|
|
@@ -117,43 +125,43 @@ public class EmailUtil {
|
|
return emailContentInfoDTOList;
|
|
return emailContentInfoDTOList;
|
|
}
|
|
}
|
|
|
|
|
|
- private static List<EmailContentInfoDTO> zipFile(String filepath) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
|
|
+// private static List<EmailContentInfoDTO> zipFile(String filepath) {
|
|
|
|
+// return null;
|
|
|
|
+// }
|
|
|
|
|
|
private static boolean isSupportedFileType(String fileName) {
|
|
private static boolean isSupportedFileType(String fileName) {
|
|
if (StrUtil.isBlank(fileName)) {
|
|
if (StrUtil.isBlank(fileName)) {
|
|
- return false;
|
|
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
- return ExcelUtil.isZip(fileName) || ExcelUtil.isExcel(fileName) || ExcelUtil.isPdf(fileName) || ExcelUtil.isHTML(fileName) || ExcelUtil.isRAR(fileName);
|
|
|
|
|
|
+ return !ExcelUtil.isZip(fileName) && !ExcelUtil.isExcel(fileName) && !ExcelUtil.isPdf(fileName) && !ExcelUtil.isHTML(fileName) && !ExcelUtil.isRAR(fileName);
|
|
}
|
|
}
|
|
|
|
|
|
- /**
|
|
|
|
- * 根据日期过滤邮件
|
|
|
|
- *
|
|
|
|
- * @param messages 采集到的邮件
|
|
|
|
- * @param startDate 邮件起始日期
|
|
|
|
- * @param endDate 邮件截止日期
|
|
|
|
- * @return 符合日期的邮件
|
|
|
|
- */
|
|
|
|
- public static List<Message> filterMessage(Message[] messages, Date startDate, Date endDate) {
|
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
|
- List<Message> messageList = CollUtil.newArrayList();
|
|
|
|
- if (messages == null) {
|
|
|
|
- return messageList;
|
|
|
|
- }
|
|
|
|
- for (Message message : messages) {
|
|
|
|
- try {
|
|
|
|
- if (message.getSentDate().compareTo(startDate) >= 0 && message.getSentDate().compareTo(endDate) <= 0) {
|
|
|
|
- messageList.add(message);
|
|
|
|
- }
|
|
|
|
- } catch (MessagingException e) {
|
|
|
|
- throw new RuntimeException(e);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- logger.info("根据日期过滤邮件耗时 -> {}ms", (System.currentTimeMillis() - startTime));
|
|
|
|
- return messageList;
|
|
|
|
- }
|
|
|
|
|
|
+// /**
|
|
|
|
+// * 根据日期过滤邮件
|
|
|
|
+// *
|
|
|
|
+// * @param messages 采集到的邮件
|
|
|
|
+// * @param startDate 邮件起始日期
|
|
|
|
+// * @param endDate 邮件截止日期
|
|
|
|
+// * @return 符合日期的邮件
|
|
|
|
+// */
|
|
|
|
+// public static List<Message> filterMessage(Message[] messages, Date startDate, Date endDate) {
|
|
|
|
+// long startTime = System.currentTimeMillis();
|
|
|
|
+// List<Message> messageList = CollUtil.newArrayList();
|
|
|
|
+// if (messages == null) {
|
|
|
|
+// return messageList;
|
|
|
|
+// }
|
|
|
|
+// for (Message message : messages) {
|
|
|
|
+// try {
|
|
|
|
+// if (message.getSentDate().compareTo(startDate) >= 0 && message.getSentDate().compareTo(endDate) <= 0) {
|
|
|
|
+// messageList.add(message);
|
|
|
|
+// }
|
|
|
|
+// } catch (MessagingException e) {
|
|
|
|
+// throw new RuntimeException(e);
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// logger.info("根据日期过滤邮件耗时 -> {}ms", (System.currentTimeMillis() - startTime));
|
|
|
|
+// return messageList;
|
|
|
|
+// }
|
|
|
|
|
|
/**
|
|
/**
|
|
* 采集邮件正文
|
|
* 采集邮件正文
|
|
@@ -168,7 +176,7 @@ public class EmailUtil {
|
|
EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
|
|
EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
|
|
try {
|
|
try {
|
|
if ((part.getContentType().contains("text/html") || part.getContentType().contains("TEXT/HTML"))) {
|
|
if ((part.getContentType().contains("text/html") || part.getContentType().contains("TEXT/HTML"))) {
|
|
- emailContentInfoDTO.setEmailContent(partContent.toString());
|
|
|
|
|
|
+ emailContentInfoDTO.setEmailContent(partContent);
|
|
String savePath = filePath + fileName;
|
|
String savePath = filePath + fileName;
|
|
File saveFile = new File(savePath);
|
|
File saveFile = new File(savePath);
|
|
if (!saveFile.exists()) {
|
|
if (!saveFile.exists()) {
|
|
@@ -181,8 +189,8 @@ public class EmailUtil {
|
|
String contentType = part.getContentType();
|
|
String contentType = part.getContentType();
|
|
String html = partContent.toString();
|
|
String html = partContent.toString();
|
|
try {
|
|
try {
|
|
- if (contentType.indexOf("charset=") != -1) {
|
|
|
|
- contentType = contentType.substring(contentType.indexOf("charset=") + 8, contentType.length()).replaceAll("\"", "");
|
|
|
|
|
|
+ if (contentType.contains("charset=")) {
|
|
|
|
+ contentType = contentType.substring(contentType.indexOf("charset=") + 8).replaceAll("\"", "");
|
|
html = html.replace("charset=" + contentType.toLowerCase(), "charset=UTF-8");
|
|
html = html.replace("charset=" + contentType.toLowerCase(), "charset=UTF-8");
|
|
html = html.replace("charset=" + contentType.toUpperCase(), "charset=UTF-8");
|
|
html = html.replace("charset=" + contentType.toUpperCase(), "charset=UTF-8");
|
|
}
|
|
}
|
|
@@ -201,7 +209,7 @@ public class EmailUtil {
|
|
return emailContentInfoDTO;
|
|
return emailContentInfoDTO;
|
|
}
|
|
}
|
|
String fileName1 = MimeUtility.decodeText(part.getFileName());
|
|
String fileName1 = MimeUtility.decodeText(part.getFileName());
|
|
- if (!isSupportedFileType(fileName1)) {
|
|
|
|
|
|
+ if (isSupportedFileType(fileName1)) {
|
|
return emailContentInfoDTO;
|
|
return emailContentInfoDTO;
|
|
}
|
|
}
|
|
emailContentInfoDTO.setFileName(fileName1);
|
|
emailContentInfoDTO.setFileName(fileName1);
|
|
@@ -302,66 +310,65 @@ public class EmailUtil {
|
|
return props;
|
|
return props;
|
|
}
|
|
}
|
|
|
|
|
|
- public static void senEmail(MailboxInfoDTO mailboxInfoDTO, String emails, File file, String htmlText, String host, String emailTitle) throws Exception {
|
|
|
|
- logger.info("send email begin .........");
|
|
|
|
- // 根据Session 构建邮件信息
|
|
|
|
- MimeMessage message = new MimeMessage(getSession(mailboxInfoDTO));
|
|
|
|
- // 创建邮件发送者地址
|
|
|
|
- Address from = new InternetAddress(mailboxInfoDTO.getAccount() + host);
|
|
|
|
- String[] emailArr = emails.split(";");
|
|
|
|
- Address[] toArr = new Address[emailArr.length];
|
|
|
|
- for (int idx = 0; idx < emailArr.length; idx++) {
|
|
|
|
- if (StrUtil.isNotBlank(emailArr[idx])) {
|
|
|
|
- Address to = new InternetAddress(emailArr[idx]);
|
|
|
|
- toArr[idx] = to;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- message.setFrom(from);
|
|
|
|
- message.setRecipients(Message.RecipientType.TO, toArr);
|
|
|
|
- // 邮件主题
|
|
|
|
- message.setSubject(emailTitle);
|
|
|
|
- // 邮件容器
|
|
|
|
- MimeMultipart mimeMultiPart = new MimeMultipart();
|
|
|
|
- // 设置HTML
|
|
|
|
- BodyPart bodyPart = new MimeBodyPart();
|
|
|
|
- logger.info("组装 htmlText.........");
|
|
|
|
- // 邮件内容
|
|
|
|
- bodyPart.setContent(htmlText, "text/html;charset=utf-8");
|
|
|
|
- //设置附件
|
|
|
|
- BodyPart filePart = new MimeBodyPart();
|
|
|
|
- filePart.setFileName(file.getName());
|
|
|
|
- filePart.setDataHandler(
|
|
|
|
- new DataHandler(
|
|
|
|
- new ByteArrayDataSource(
|
|
|
|
- Files.readAllBytes(Paths.get(file.getAbsolutePath())), "application/octet-stream")));
|
|
|
|
- mimeMultiPart.addBodyPart(bodyPart);
|
|
|
|
- mimeMultiPart.addBodyPart(filePart);
|
|
|
|
- message.setContent(mimeMultiPart);
|
|
|
|
- message.setSentDate(new Date());
|
|
|
|
- // 保存邮件
|
|
|
|
- message.saveChanges();
|
|
|
|
- // 发送邮件
|
|
|
|
- Transport.send(message);
|
|
|
|
- }
|
|
|
|
|
|
+// public static void senEmail(MailboxInfoDTO mailboxInfoDTO, String emails, File file, String htmlText, String host, String emailTitle) throws Exception {
|
|
|
|
+// logger.info("send email begin .........");
|
|
|
|
+// // 根据Session 构建邮件信息
|
|
|
|
+// MimeMessage message = new MimeMessage(getSession(mailboxInfoDTO));
|
|
|
|
+// // 创建邮件发送者地址
|
|
|
|
+// Address from = new InternetAddress(mailboxInfoDTO.getAccount() + host);
|
|
|
|
+// String[] emailArr = emails.split(";");
|
|
|
|
+// Address[] toArr = new Address[emailArr.length];
|
|
|
|
+// for (int idx = 0; idx < emailArr.length; idx++) {
|
|
|
|
+// if (StrUtil.isNotBlank(emailArr[idx])) {
|
|
|
|
+// Address to = new InternetAddress(emailArr[idx]);
|
|
|
|
+// toArr[idx] = to;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// message.setFrom(from);
|
|
|
|
+// message.setRecipients(Message.RecipientType.TO, toArr);
|
|
|
|
+// // 邮件主题
|
|
|
|
+// message.setSubject(emailTitle);
|
|
|
|
+// // 邮件容器
|
|
|
|
+// MimeMultipart mimeMultiPart = new MimeMultipart();
|
|
|
|
+// // 设置HTML
|
|
|
|
+// BodyPart bodyPart = new MimeBodyPart();
|
|
|
|
+// logger.info("组装 htmlText.........");
|
|
|
|
+// // 邮件内容
|
|
|
|
+// bodyPart.setContent(htmlText, "text/html;charset=utf-8");
|
|
|
|
+// //设置附件
|
|
|
|
+// BodyPart filePart = new MimeBodyPart();
|
|
|
|
+// filePart.setFileName(file.getName());
|
|
|
|
+// filePart.setDataHandler(
|
|
|
|
+// new DataHandler(
|
|
|
|
+// new ByteArrayDataSource(
|
|
|
|
+// Files.readAllBytes(Paths.get(file.getAbsolutePath())), "application/octet-stream")));
|
|
|
|
+// mimeMultiPart.addBodyPart(bodyPart);
|
|
|
|
+// mimeMultiPart.addBodyPart(filePart);
|
|
|
|
+// message.setContent(mimeMultiPart);
|
|
|
|
+// message.setSentDate(new Date());
|
|
|
|
+// // 保存邮件
|
|
|
|
+// message.saveChanges();
|
|
|
|
+// // 发送邮件
|
|
|
|
+// Transport.send(message);
|
|
|
|
+// }
|
|
|
|
|
|
- public static Session getSession(MailboxInfoDTO mailboxInfoDTO) {
|
|
|
|
- try {
|
|
|
|
- Properties properties = new Properties();
|
|
|
|
- properties.put("mail.smtp.host", mailboxInfoDTO.getHost());
|
|
|
|
- properties.put("mail.smtp.auth", true);
|
|
|
|
- properties.put("mail.smtp.port", mailboxInfoDTO.getPort());
|
|
|
|
- properties.put("mail.smtp.ssl.enable", true);
|
|
|
|
- final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
|
|
|
|
- properties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
|
|
|
|
- properties.setProperty("mail.smtp.socketFactory.fallback", "false");
|
|
|
|
- properties.setProperty("mail.smtp.socketFactory.port", mailboxInfoDTO.getPort());
|
|
|
|
- // 根据邮件的会话属性构造一个发送邮件的Session,
|
|
|
|
- JakartaUserPassAuthenticator authenticator = new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword());
|
|
|
|
- Session session = Session.getInstance(properties, authenticator);
|
|
|
|
- return session;
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- logger.error("getSession : " + e.getMessage());
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
|
|
+// public static Session getSession(MailboxInfoDTO mailboxInfoDTO) {
|
|
|
|
+// try {
|
|
|
|
+// Properties properties = new Properties();
|
|
|
|
+// properties.put("mail.smtp.host", mailboxInfoDTO.getHost());
|
|
|
|
+// properties.put("mail.smtp.auth", true);
|
|
|
|
+// properties.put("mail.smtp.port", mailboxInfoDTO.getPort());
|
|
|
|
+// properties.put("mail.smtp.ssl.enable", true);
|
|
|
|
+// final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
|
|
|
|
+// properties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
|
|
|
|
+// properties.setProperty("mail.smtp.socketFactory.fallback", "false");
|
|
|
|
+// properties.setProperty("mail.smtp.socketFactory.port", mailboxInfoDTO.getPort());
|
|
|
|
+// // 根据邮件的会话属性构造一个发送邮件的Session,
|
|
|
|
+// JakartaUserPassAuthenticator authenticator = new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword());
|
|
|
|
+// return Session.getInstance(properties, authenticator);
|
|
|
|
+// } catch (Exception e) {
|
|
|
|
+// logger.error("getSession : {}", e.getMessage());
|
|
|
|
+// }
|
|
|
|
+// return null;
|
|
|
|
+// }
|
|
}
|
|
}
|