Преглед на файлове

优化邮件处理逻辑;增加日志邮件发送器实现;

woody преди 11 месеца
родител
ревизия
bac68aa906

+ 2 - 0
framework-base/src/main/java/com/chelvc/framework/base/context/Session.java

@@ -11,6 +11,7 @@ import lombok.Builder;
 import lombok.Getter;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 import lombok.NonNull;
 import lombok.NonNull;
+import lombok.ToString;
 
 
 /**
 /**
  * 会话信息
  * 会话信息
@@ -20,6 +21,7 @@ import lombok.NonNull;
  */
  */
 @Getter
 @Getter
 @Builder
 @Builder
+@ToString
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
 public class Session implements Serializable {
 public class Session implements Serializable {

+ 0 - 4
framework-common/pom.xml

@@ -27,10 +27,6 @@
             <groupId>org.jsoup</groupId>
             <groupId>org.jsoup</groupId>
             <artifactId>jsoup</artifactId>
             <artifactId>jsoup</artifactId>
         </dependency>
         </dependency>
-        <dependency>
-            <groupId>javax.mail</groupId>
-            <artifactId>mail</artifactId>
-        </dependency>
         <dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <artifactId>guava</artifactId>

+ 4 - 0
framework-email/pom.xml

@@ -19,6 +19,10 @@
     </properties>
     </properties>
 
 
     <dependencies>
     <dependencies>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
         <dependency>
         <dependency>
             <groupId>com.chelvc.framework</groupId>
             <groupId>com.chelvc.framework</groupId>
             <artifactId>framework-base</artifactId>
             <artifactId>framework-base</artifactId>

+ 5 - 0
framework-email/src/main/java/com/chelvc/framework/email/Body.java

@@ -33,6 +33,11 @@ public class Body implements Serializable {
      */
      */
     private String bcc;
     private String bcc;
 
 
+    /**
+     * 内容类型
+     */
+    private String type;
+
     /**
     /**
      * 邮件主题
      * 邮件主题
      */
      */

+ 3 - 3
framework-email/src/main/java/com/chelvc/framework/email/DefaultEmailHandler.java

@@ -11,9 +11,9 @@ import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMessage;
 
 
-import com.chelvc.framework.common.util.EmailUtils;
 import com.chelvc.framework.common.util.StringUtils;
 import com.chelvc.framework.common.util.StringUtils;
 import com.chelvc.framework.email.config.EmailProperties;
 import com.chelvc.framework.email.config.EmailProperties;
+import com.chelvc.framework.email.context.EmailContextHolder;
 import lombok.NonNull;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
@@ -73,7 +73,7 @@ public class DefaultEmailHandler implements EmailHandler {
 
 
             // 设置邮件主题
             // 设置邮件主题
             message.setSubject(body.getSubject());
             message.setSubject(body.getSubject());
-            message.setContent(EmailUtils.mixed(body.getContent(), attachments));
+            message.setContent(EmailContextHolder.mixed(body, attachments));
         } catch (MessagingException | UnsupportedEncodingException e) {
         } catch (MessagingException | UnsupportedEncodingException e) {
             throw new RuntimeException(e);
             throw new RuntimeException(e);
         }
         }
@@ -87,7 +87,7 @@ public class DefaultEmailHandler implements EmailHandler {
 
 
     @Override
     @Override
     public boolean send(@NonNull Body body, @NonNull File... attachments) {
     public boolean send(@NonNull Body body, @NonNull File... attachments) {
-        return this.send(body, EmailUtils.file2mixed(attachments));
+        return this.send(body, EmailContextHolder.part(attachments));
     }
     }
 
 
     @Override
     @Override

+ 78 - 0
framework-email/src/main/java/com/chelvc/framework/email/LogbackEmailAppender.java

@@ -0,0 +1,78 @@
+package com.chelvc.framework.email;
+
+import java.util.Objects;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+import ch.qos.logback.core.Layout;
+import com.chelvc.framework.common.util.StringUtils;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Logback日志邮件发送器
+ *
+ * @author Woody
+ * @date 2024/5/20
+ */
+@Getter
+@Setter
+@Component
+public class LogbackEmailAppender extends AppenderBase<ILoggingEvent> implements ApplicationContextAware {
+    /**
+     * 邮件处理器实例
+     */
+    private static EmailHandler EMAIL_HANDLER;
+
+    private String to;
+    private String subject;
+    private boolean asynchronous = true;
+    private Layout<ILoggingEvent> layout;
+
+    /**
+     * 判断日志邮件发送器是否已准备就绪
+     *
+     * @return true/false
+     */
+    protected boolean isReady() {
+        return this.layout != null && EMAIL_HANDLER != null && StringUtils.notEmpty(this.to);
+    }
+
+    /**
+     * 获取邮件处理器
+     *
+     * @return 邮件处理器
+     */
+    protected EmailHandler getEmailHandler() {
+        return Objects.requireNonNull(EMAIL_HANDLER);
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        EMAIL_HANDLER = applicationContext.getBean(EmailHandler.class);
+    }
+
+    @Override
+    protected void append(ILoggingEvent event) {
+        if (!this.isReady()) {
+            return;
+        }
+
+        // 构建邮件体
+        String type = this.layout.getContentType();
+        String content = this.layout.doLayout(event);
+        Body body = Body.builder().to(this.to).type(type).subject(this.subject).content(content).build();
+
+        // 异步发送邮件
+        EmailHandler handler = this.getEmailHandler();
+        if (this.asynchronous) {
+            this.context.getScheduledExecutorService().execute(() -> handler.send(body));
+        } else {
+            handler.send(body);
+        }
+    }
+}

+ 34 - 25
framework-common/src/main/java/com/chelvc/framework/common/util/EmailUtils.java → framework-email/src/main/java/com/chelvc/framework/email/context/EmailContextHolder.java

@@ -1,4 +1,4 @@
-package com.chelvc.framework.common.util;
+package com.chelvc.framework.email.context;
 
 
 import java.io.File;
 import java.io.File;
 import java.io.IOException;
 import java.io.IOException;
@@ -6,6 +6,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.io.UnsupportedEncodingException;
 import java.net.URL;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.LinkedList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Matcher;
@@ -20,34 +21,43 @@ import javax.mail.internet.MimeMultipart;
 import javax.mail.internet.MimeUtility;
 import javax.mail.internet.MimeUtility;
 import javax.mail.util.ByteArrayDataSource;
 import javax.mail.util.ByteArrayDataSource;
 
 
+import ch.qos.logback.core.util.ContentTypeUtil;
+import com.chelvc.framework.common.util.StringUtils;
+import com.chelvc.framework.email.Body;
 import lombok.NonNull;
 import lombok.NonNull;
 
 
 /**
 /**
  * 邮件工具类
  * 邮件工具类
  *
  *
  * @author Woody
  * @author Woody
- * @date 2024/1/30
+ * @date 2024/4/3
  */
  */
-public final class EmailUtils {
+public final class EmailContextHolder {
     static {
     static {
         FileTypeMap.setDefaultFileTypeMap(FileTypeMap.getDefaultFileTypeMap());
         FileTypeMap.setDefaultFileTypeMap(FileTypeMap.getDefaultFileTypeMap());
     }
     }
 
 
-    private EmailUtils() {
+    private EmailContextHolder() {
     }
     }
 
 
     /**
     /**
-     * 将文本转换成邮件内容体
+     * 将内容转换成邮件内容体
      *
      *
-     * @param text 文本内容
+     * @param body 邮件体
      * @return 邮件内容体
      * @return 邮件内容体
      */
      */
-    public static Multipart text2part(@NonNull String text) {
+    public static Multipart part(@NonNull Body body) {
         // 构建邮件内容部分
         // 构建邮件内容部分
+        String type = body.getType();
+        String text = body.getContent();
         MimeMultipart part = new MimeMultipart();
         MimeMultipart part = new MimeMultipart();
         MimeBodyPart content = new MimeBodyPart();
         MimeBodyPart content = new MimeBodyPart();
         try {
         try {
-            content.setContent(text, "text/html;charset=UTF-8");
+            if (ContentTypeUtil.isTextual(type)) {
+                content.setText(text, StandardCharsets.UTF_8.name(), ContentTypeUtil.getSubType(type));
+            } else {
+                content.setContent(text, type);
+            }
             part.addBodyPart(content);
             part.addBodyPart(content);
             if (StringUtils.isEmpty(text)) {
             if (StringUtils.isEmpty(text)) {
                 return part;
                 return part;
@@ -106,23 +116,23 @@ public final class EmailUtils {
     }
     }
 
 
     /**
     /**
-     * 将文件转换成邮件混合部分
+     * 将文件转换成邮件附件部分
      *
      *
      * @param file 文件对象
      * @param file 文件对象
      * @return 邮件混合部分
      * @return 邮件混合部分
      */
      */
-    public static MimeBodyPart file2mixed(@NonNull File file) {
-        return file2mixed(file, file.getName());
+    public static MimeBodyPart part(@NonNull File file) {
+        return part(file, file.getName());
     }
     }
 
 
     /**
     /**
-     * 将文件转换成邮件混合部分
+     * 将文件转换成邮件附件部分
      *
      *
      * @param file    文件对象
      * @param file    文件对象
      * @param comment 文件说明
      * @param comment 文件说明
      * @return 邮件混合部分
      * @return 邮件混合部分
      */
      */
-    public static MimeBodyPart file2mixed(@NonNull File file, @NonNull String comment) {
+    public static MimeBodyPart part(@NonNull File file, @NonNull String comment) {
         MimeBodyPart body = new MimeBodyPart();
         MimeBodyPart body = new MimeBodyPart();
         try {
         try {
             body.setDataHandler(new DataHandler(new FileDataSource(file)));
             body.setDataHandler(new DataHandler(new FileDataSource(file)));
@@ -134,29 +144,28 @@ public final class EmailUtils {
     }
     }
 
 
     /**
     /**
-     * 将文件转换成邮件混合部分
+     * 将文件转换成邮件附件部分
      *
      *
      * @param files 文件对象数组
      * @param files 文件对象数组
      * @return 邮件混合部分数组
      * @return 邮件混合部分数组
      */
      */
-    public static MimeBodyPart[] file2mixed(@NonNull File... files) {
+    public static MimeBodyPart[] part(@NonNull File... files) {
         MimeBodyPart[] mixes = new MimeBodyPart[files.length];
         MimeBodyPart[] mixes = new MimeBodyPart[files.length];
         for (int i = 0; i < files.length; i++) {
         for (int i = 0; i < files.length; i++) {
-            mixes[i] = file2mixed(files[i]);
+            mixes[i] = part(files[i]);
         }
         }
         return mixes;
         return mixes;
     }
     }
 
 
     /**
     /**
-     * 将文件流转换成邮件混合部分
+     * 将文件流转换成邮件附件部分
      *
      *
      * @param stream  文件流对象
      * @param stream  文件流对象
      * @param type    文件类型
      * @param type    文件类型
      * @param comment 文件说明
      * @param comment 文件说明
      * @return 邮件混合部分
      * @return 邮件混合部分
      */
      */
-    public static MimeBodyPart stream2mixed(@NonNull InputStream stream, @NonNull String type,
-                                            @NonNull String comment) {
+    public static MimeBodyPart part(@NonNull InputStream stream, @NonNull String type, @NonNull String comment) {
         MimeBodyPart body = new MimeBodyPart();
         MimeBodyPart body = new MimeBodyPart();
         try {
         try {
             DataSource dataSource = new ByteArrayDataSource(stream, type);
             DataSource dataSource = new ByteArrayDataSource(stream, type);
@@ -172,23 +181,23 @@ public final class EmailUtils {
     /**
     /**
      * 设置邮件混合文件数据源
      * 设置邮件混合文件数据源
      *
      *
-     * @param text  邮件正文
+     * @param body  邮件体
      * @param files 文件对象集合
      * @param files 文件对象集合
      * @return 邮件消息体对象
      * @return 邮件消息体对象
      */
      */
-    public static Multipart mixed(@NonNull String text, @NonNull File... files) {
-        return mixed(text, file2mixed(files));
+    public static Multipart mixed(@NonNull Body body, @NonNull File... files) {
+        return mixed(body, part(files));
     }
     }
 
 
     /**
     /**
      * 设置邮件混合文件数据源
      * 设置邮件混合文件数据源
      *
      *
-     * @param text  邮件正文
+     * @param body  邮件体
      * @param mixes 混合对象数组
      * @param mixes 混合对象数组
      * @return 邮件消息体对象
      * @return 邮件消息体对象
      */
      */
-    public static Multipart mixed(@NonNull String text, @NonNull MimeBodyPart... mixes) {
-        Multipart part = text2part(text);
+    public static Multipart mixed(@NonNull Body body, @NonNull MimeBodyPart... mixes) {
+        Multipart part = part(body);
         if (mixes.length == 0) {
         if (mixes.length == 0) {
             return part;
             return part;
         }
         }