Quellcode durchsuchen

feat:集成发送邮件服务

huangjinliang vor 5 Tagen
Ursprung
Commit
7845b0ade0

+ 23 - 1
fuintBackend/configure/dev/application.properties

@@ -105,4 +105,26 @@ weixin.subMessage.couponExpire=[{'key':'name', 'name':'\u5361\u5238\u540D\u79F0'
 weixin.subMessage.couponArrival=[{'key':'name', 'name':'\u5361\u5238\u540D\u79F0'},{'key':'amount', 'name':'\u91D1\u989D'},{'key':'tips', 'name':'\u6E29\u99A8\u63D0\u793A'}]
 weixin.subMessage.balanceChange=[{'key':'amount', 'name':'\u53D8\u52A8\u91D1\u989D'},{'key':'time', 'name':'\u53D8\u52A8\u65F6\u95F4'},{'key':'tips', 'name':'\u6E29\u99A8\u63D0\u793A'}]
 weixin.subMessage.couponConfirm=[{'key':'name', 'name':'\u5361\u5238\u540D\u79F0'},{'key':'time', 'name':'\u6838\u9500\u65F6\u95F4'}]
-weixin.subMessage.pointChange=[{'key':'amount', 'name':'\u53D8\u52A8\u6570\u91CF'},{'key':'time', 'name':'\u53D8\u52A8\u65F6\u95F4'},{'key':'remark', 'name':'\u5907\u6CE8\u4FE1\u606F'}]
+weixin.subMessage.pointChange=[{'key':'amount', 'name':'\u53D8\u52A8\u6570\u91CF'},{'key':'time', 'name':'\u53D8\u52A8\u65F6\u95F4'},{'key':'remark', 'name':'\u5907\u6CE8\u4FE1\u606F'}]
+
+
+# \u90AE\u7BB1\u914D\u7F6E
+spring.mail.host=smtp.163.com
+spring.mail.port=465
+spring.mail.username=17633944959@163.com
+spring.mail.password=CHb8mqa9Hxst7V5G
+spring.mail.protocol=smtp
+spring.mail.properties.mail.smtp.ssl.enable=true
+spring.mail.properties.mail.smtp.auth=true
+
+# \u9884\u8B66\u914D\u7F6E\uFF08\u652F\u6301\u914D\u7F6E\u4E2D\u5FC3\uFF09
+alert.from-email=17633944959@163.com
+alert.to-email=huangjinliang35@gmail.com
+# \u6284\u9001
+#alert.email.cc=2822711420@qq.com
+# \u5BC6\u9001
+#alert.email.bcc=2822711420@qq.com
+# \u539F\u914D\u7F6E\uFF08\u6BCF\u59298\u70B9\uFF09
+#alert.cron-expression=0 0 8 * * ?
+# \u65B0\u914D\u7F6E\uFF08\u6BCF10\u79D2\u6267\u884C\uFF09
+alert.cron-expression=*/10 * * * * *

+ 6 - 0
fuintBackend/fuint-application/pom.xml

@@ -170,6 +170,12 @@
             <version>3.23.9</version>
         </dependency>
 
+        <!-- Spring Mail -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 23 - 0
fuintBackend/fuint-application/src/main/java/com/fuint/common/config/AlertConfig.java

@@ -0,0 +1,23 @@
+package com.fuint.common.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Survive
+ * @date 2025/3/10
+ * @description TODO 预警配置类
+ */
+@Getter
+@Setter
+@Component
+@ConfigurationProperties(prefix = "alert")
+public class AlertConfig {
+    private String fromEmail;
+    private String toEmail;//主收件人
+    private String ccEmails;       // 抄送(可选)
+    private String bccEmails;      // 密送(可选)
+    private String cronExpression;//定时器时间
+}

+ 30 - 0
fuintBackend/fuint-application/src/main/java/com/fuint/common/config/AsyncConfig.java

@@ -0,0 +1,30 @@
+package com.fuint.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+/**
+ * @author Survive
+ * @date 2025/3/10
+ * @description TODO 定时任务异步执行(避免任务堆积)
+ *                   在定时方法上添加@Async:@Async("taskExecutor")
+ */
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+    // 配置线程池
+    @Bean(name = "taskExecutor")
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(5);
+        executor.setMaxPoolSize(10);
+        executor.setQueueCapacity(100);
+        executor.setThreadNamePrefix("Async-");
+        executor.initialize();
+        return executor;
+    }
+}

+ 23 - 0
fuintBackend/fuint-application/src/main/java/com/fuint/common/dto/ext/EmailDto.java

@@ -0,0 +1,23 @@
+package com.fuint.common.dto.ext;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author Survive
+ * @date 2025/3/10
+ * @description TODO 邮件服务DTO
+ */
+@Data
+@AllArgsConstructor
+public class EmailDto {
+    @ApiModelProperty("收件人")
+    private String to;
+
+    @ApiModelProperty("邮件主题")
+    private String subject;
+
+    @ApiModelProperty("邮件内容")
+    private String content;
+}

+ 10 - 0
fuintBackend/fuint-application/src/main/java/com/fuint/common/service/EmailService.java

@@ -0,0 +1,10 @@
+package com.fuint.common.service;
+
+import com.fuint.common.dto.ext.EmailDto;
+
+/**
+ * 邮件发送服务
+ */
+public interface EmailService {
+    void sendAlertEmail(EmailDto emailDTO);
+}

+ 55 - 0
fuintBackend/fuint-application/src/main/java/com/fuint/common/service/impl/EmailServiceImpl.java

@@ -0,0 +1,55 @@
+package com.fuint.common.service.impl;
+
+import com.fuint.common.config.AlertConfig;
+import com.fuint.common.dto.ext.EmailDto;
+import com.fuint.common.service.EmailService;
+import com.fuint.framework.exception.EmailException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+/**
+ * @author Survive
+ * @date 2025/3/10
+ * @description TODO 邮件发送服务
+ */
+@Service
+@RequiredArgsConstructor
+public class EmailServiceImpl implements EmailService {
+    private final JavaMailSender mailSender;
+    private final AlertConfig alertConfig;
+    @Override
+    public void sendAlertEmail(EmailDto emailDTO) {
+        try {
+            MimeMessage message = mailSender.createMimeMessage();
+            MimeMessageHelper helper = new MimeMessageHelper(message, true);
+
+            // 设置发件人
+            helper.setFrom(alertConfig.getFromEmail());
+            // 解析多个收件人
+            String[] toEmails = emailDTO.getTo().split(",\\s*");
+            helper.setTo(toEmails);
+//            helper.setTo(emailDTO.getTo());
+            // 设置主题和内容
+            helper.setSubject(emailDTO.getSubject());
+            helper.setText(emailDTO.getContent());
+
+            // 抄送
+            if (StringUtils.hasText(alertConfig.getCcEmails())) {
+                helper.setCc(alertConfig.getCcEmails().split(",\\s*"));
+            }
+            // 密送
+            if (StringUtils.hasText(alertConfig.getBccEmails())) {
+                helper.setBcc(alertConfig.getBccEmails().split(",\\s*"));
+            }
+            mailSender.send(message);
+        } catch (MessagingException e) {
+            throw new EmailException("邮件发送失败", e);
+        }
+    }
+}

+ 7 - 0
fuintBackend/fuint-framework/src/main/java/com/fuint/framework/exception/EmailException.java

@@ -0,0 +1,7 @@
+package com.fuint.framework.exception;
+
+public class EmailException extends RuntimeException {
+    public EmailException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

+ 13 - 0
fuintBackend/fuint-framework/src/main/java/com/fuint/framework/exception/GlobalExceptionHandler.java

@@ -3,6 +3,8 @@ package com.fuint.framework.exception;
 import com.fuint.framework.web.ResponseObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.validation.BindException;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -23,6 +25,17 @@ public class GlobalExceptionHandler {
 
     private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
+    /**
+     * 邮件服务异常
+     * @param ex
+     * @return
+     */
+    @ExceptionHandler(EmailException.class)
+    public ResponseEntity<String> handleEmailException(EmailException ex) {
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                .body("邮件服务异常: " + ex.getMessage());
+    }
+
     @ExceptionHandler(IllegalArgumentException.class)
     public ResponseObject handleHttpRequestMethodNotSupported(IllegalArgumentException e,HttpServletRequest request){
         String requestURI = request.getRequestURI();