From d65d066b3e5f5ccd61353ffca6f06a2934c4f039 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Sat, 19 Oct 2024 21:28:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=82=AE=E4=BB=B6=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=B0=81=E8=A3=85=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ReadMe.md | 34 ---------- .../service/utils/mail/MailSenderUtil.java | 54 ++++++++-------- .../cn/bunny/dao/pojo/common/EmailSend.java | 19 ++++-- .../bunny/dao/pojo/common/EmailSendInit.java | 12 ++++ data/auth_admin.sql | 31 +++++---- service/Dockerfile | 4 +- .../bunny/services/factory/EmailFactory.java | 60 +++++++++--------- .../service/impl/UserServiceImpl.java | 41 +++++++++--- .../services/factory/EmailFactoryTest.java | 63 +++++++++++++++++++ 9 files changed, 198 insertions(+), 120 deletions(-) create mode 100644 service/src/test/java/cn/bunny/services/factory/EmailFactoryTest.java diff --git a/ReadMe.md b/ReadMe.md index f2534e0..4ce2d65 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -172,37 +172,3 @@ docker run -d \ 9. `usingJobData(JobDataMap jobData, boolean merge)`:添加自定义数据,并指定是否与现有的 `JobDataMap` 合并。 10. `build()`:构建并返回最终的 `JobDetail` 实例。 - -# 展望未来 - -## 定时任务加入 - -数据备份:根据数据的重要性和变化频率,定时备份数据库或文件系统。例如,每晚备份数据库,或者在数据变更达到一定量后触发备份。 - -系统维护:包括软件更新、系统清理、磁盘碎片整理等,这些任务可能在系统负载较低的时段执行。 - -监控报告:定时生成系统或网络的使用报告、性能报告等,用于分析和审计。 - -内容更新:对于网站或应用,定时更新内容,如新闻网站定时更新新闻,天气应用定时更新天气信息。 - -缓存清理:定期清理缓存文件,以释放存储空间和提高系统性能。 - -日志轮转:自动归档和压缩旧的日志文件,以便于管理和分析。 - -邮件发送:定时发送邮件,如账单、通知、营销邮件等。 - -资源调度:在云计算环境中,根据需求动态调整资源分配,如自动扩展或缩减服务器实例。 - -数据同步:在多个系统或数据库之间定时同步数据,保持数据一致性。 - -安全扫描:定期执行安全扫描,检测系统漏洞或异常行为。 - -任务调度:在工作流管理系统中,根据预设的规则和条件动态触发任务。 - -库存管理:在电子商务或仓库管理中,定时检查库存水平,自动触发补货或调整价格。 - -广告轮播:在广告系统中,定时更换展示的广告内容。 - -用户行为分析:定时收集和分析用户行为数据,用于改进产品或服务。 - -健康检查:对关键系统组件进行定时健康检查,确保系统稳定运行。 \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java index 304249c..5b8690f 100644 --- a/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java @@ -8,46 +8,55 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.web.multipart.MultipartFile; -import java.util.List; import java.util.Objects; public class MailSenderUtil { - private final String username; - private final JavaMailSenderImpl javaMailSender; /** - * * 设置邮件发送基础信息 - * 设置发送邮件地址、端口、用户名和密码 + * * 邮件发送初始化 * - * @param emailSendInit 初始化参数 + * @param emailSendInit 邮件发送初始化 */ - public MailSenderUtil(EmailSendInit emailSendInit) { + public static JavaMailSenderImpl senderUtil(EmailSendInit emailSendInit) { JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); javaMailSender.setHost(emailSendInit.getHost()); javaMailSender.setPort(emailSendInit.getPort()); javaMailSender.setUsername(emailSendInit.getUsername()); javaMailSender.setPassword(emailSendInit.getPassword()); - javaMailSender.setProtocol("smtps"); + javaMailSender.setProtocol(emailSendInit.getProtocol()); javaMailSender.setDefaultEncoding("UTF-8"); - this.username = emailSendInit.getUsername(); - this.javaMailSender = javaMailSender; + return javaMailSender; } - public void sendEmail(EmailSend emailSend) throws MessagingException { - check(emailSend); - + /** + * * 发送邮件 + * + * @param emailSendInit 邮件发送初始化 + * @param emailSend 邮件发送表单 + */ + public static void sendEmail(EmailSendInit emailSendInit, EmailSend emailSend) throws MessagingException { + // 发送邮件初始化 + JavaMailSenderImpl javaMailSender = senderUtil(emailSendInit); MimeMessage message = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true); - // message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to1@example.com,to2@example.com")); - helper.setFrom(username); - helper.setTo(emailSend.getSendTo()); + + // 设置发件人 + helper.setFrom(emailSendInit.getUsername()); + + // 设置群发内容 + helper.setTo(emailSend.getSendTo().toArray(new String[0])); + + // 设置主题 helper.setSubject(emailSend.getSubject()); - helper.setText(emailSend.getMessage(), emailSend.isRichText()); - List ccList = emailSend.getCcParam() != null ? List.of(emailSend.getCcParam().split(",")) : List.of(); - helper.setCc(ccList.toArray(new String[0])); + // 设置发送文本 + helper.setText(emailSend.getText(), emailSend.isRichText()); + // 设置抄送 + helper.setCc(emailSend.getCcParam().toArray(new String[0])); + + // 设置附件 MultipartFile[] files = emailSend.getFiles(); if (files != null) { for (MultipartFile file : files) { @@ -55,12 +64,7 @@ public class MailSenderUtil { } } + // 发送邮件 javaMailSender.send(message); } - - private void check(EmailSend emailSend) { - // 添加验证逻辑 - Class aClass = EmailSend.class; - - } } diff --git a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java index 7042769..8fd3da5 100644 --- a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java +++ b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java @@ -1,12 +1,17 @@ package cn.bunny.dao.pojo.common; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.web.multipart.MultipartFile; +import java.util.ArrayList; +import java.util.List; + /** * 邮件发送对象 */ @@ -17,20 +22,26 @@ import org.springframework.web.multipart.MultipartFile; @Schema(name = "EmailSend", title = "邮件发送表单", description = "邮件发送表单") public class EmailSend { - @Schema(name = "sendTo", title = "给谁发送") - private String sendTo; + @Schema(name = "sendTo", title = "收件人") + @NotBlank(message = "收件人机不能为空") + @NotNull(message = "收件人不能为空") + private List sendTo; @Schema(name = "subject", title = "发送主题") + @NotBlank(message = "发送主题不能为空") + @NotNull(message = "发送主题不能为空") private String subject; @Schema(name = "isRichText", title = "是否为富文本") private boolean isRichText = true; @Schema(name = "message", title = "发送内容") - private String message; + @NotBlank(message = "发送内容不能为空") + @NotNull(message = "发送内容不能为空") + private String text; @Schema(name = "ccParam", title = "抄送人") - private String ccParam; + private List ccParam = new ArrayList<>(); @Schema(name = "file", title = "发送的文件") private MultipartFile[] files; diff --git a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java index 007daea..d25bd58 100644 --- a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java +++ b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java @@ -1,6 +1,8 @@ package cn.bunny.dao.pojo.common; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -17,15 +19,25 @@ import lombok.NoArgsConstructor; public class EmailSendInit { @Schema(name = "port", title = "端口") + @NotNull(message = "端口不能为空") private Integer port; @Schema(name = "host", title = "主机") + @NotBlank(message = "主机不能为空") + @NotNull(message = "主机不能为空") private String host; + @Schema(name = "protocol", description = "协议") + private String protocol = "smtps"; + @Schema(name = "username", title = "用户名") + @NotBlank(message = "用户名不能为空") + @NotNull(message = "用户名不能为空") private String username; @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") private String password; } \ No newline at end of file diff --git a/data/auth_admin.sql b/data/auth_admin.sql index 1a09f03..9a77dea 100644 --- a/data/auth_admin.sql +++ b/data/auth_admin.sql @@ -1,17 +1,17 @@ /* Navicat Premium Dump SQL - Source Server : mysql(192.168.3.98) + Source Server : 阿里云(正式) Source Server Type : MySQL Source Server Version : 80033 (8.0.33) - Source Host : 192.168.3.98:3304 + Source Host : 106.15.251.123:3306 Source Schema : auth_admin Target Server Type : MySQL Target Server Version : 80033 (8.0.33) File Encoding : 65001 - Date: 19/10/2024 16:39:06 + Date: 19/10/2024 17:52:05 */ SET NAMES utf8mb4; @@ -71,11 +71,10 @@ CREATE TABLE `log_user_login` ( -- ---------------------------- -- Records of log_user_login -- ---------------------------- -INSERT INTO `log_user_login` VALUES (1847355954367836162, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLQQrCMBBF7zLrRjImk0m6EnduvENiZkCh1bYGFPHuBtx93nv_A1srMMKxzfMbBpDXA0bkfYrRMYUB2ibrqXb2n-c8Sc_RYUrWIvnDsuwu96lfb89rNyqsrko0hJSNZ68m-0DGBi2WC4rWAN8fveZ32HcAAAA.3ojnO1B0cRHidpCTdMlHFGpY_ZPTC8AvMx4LhprjVrU', '127.0.0.1', '内网IP', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', 'login', 'XMLHttpRequest', '\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"', '?0', '\"Windows\"', '2024-10-19 03:15:56', '2024-10-19 03:15:56', 1, 1, 0); -INSERT INTO `log_user_login` VALUES (1847355983346282498, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLQQrCMBBF7zLrRjImk0m6EnduvENiZkCh1bYGFPHuBtx93nv_A1srMMKxzfMbBpDXA0bkfYrRMYUB2ibrqXb2n-c8Sc_RYUrWIvnDsuwu96lfb89rNyqsrko0hJSNZ68m-0DGBi2WC4rWAN8fveZ32HcAAAA.3ojnO1B0cRHidpCTdMlHFGpY_ZPTC8AvMx4LhprjVrU', '127.0.0.1', '内网IP', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', 'logout', 'XMLHttpRequest', '\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"', '?0', '\"Windows\"', '2024-10-19 03:16:03', '2024-10-19 03:16:03', 1, 1, 0); -INSERT INTO `log_user_login` VALUES (1847356167765635073, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLQQrCMBBF7zLrRjJtks50Je668Q4m-YJCq7UGKuLdjbj7vPf-m9YSaaBDmecXNYTtTgP3rYp0YvuGyorHmCv7z-NpQs25Y1Vr2bv9suzSbarX6_PyMwIPwBlEhnGaookpqBHnUwj5nHMr9PkC8ofSBncAAAA.Hd5yqpx-oUCtt8EykNFcKm0EHRkKtrFrik4kXTad774', '127.0.0.1', '内网IP', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', 'login', 'XMLHttpRequest', '\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"', '?0', '\"Windows\"', '2024-10-19 03:16:47', '2024-10-19 03:16:47', 1, 1, 0); INSERT INTO `log_user_login` VALUES (1847356246924734465, 1, NULL, NULL, '127.0.0.1', '内网IP', NULL, 'forcedOffline', NULL, NULL, NULL, NULL, '2024-10-19 03:17:06', '2024-10-19 03:17:06', 1, 1, 0); INSERT INTO `log_user_login` VALUES (1847356317057691650, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLQQrCMBBF7zLrRmaSmXbSlXTnxjukcQoKrdY2oIh3N-Du8977H9jKCD0MZVne0IC9HtBT56NqUPYNlM2ep0tl_3lOs9WcAsWISMLHdT3k-1yvt_1aDbN46YScBhLHKbQuobXOcPIjTpo5G3x_bEMAvHcAAAA.hWcfG-ulaNVTFqKl1EGFeoJP6L3DtQMKCS3Hwo4JSLM', '127.0.0.1', '内网IP', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', 'login', 'XMLHttpRequest', '\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"', '?0', '\"Windows\"', '2024-10-19 03:17:23', '2024-10-19 03:17:23', 1, 1, 0); +INSERT INTO `log_user_login` VALUES (1847569964447891458, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLMQ7CMAxF7-K5qRwcE9wJsbFwh8bx0EotlBKpFeLujcT29d77X1hLgg5uZZ53aMC2F3Q-nkQoxAs2UFZ733Nl__noJ6u5Jy-C6Dlcl6XV51Sv42eohhTNiNmZiLpAaC5xRBdSz6TxnDUL_A4r7Di_dwAAAA.DYH6L5ApfggqAPwcfTZ9whrBDidSLUODbf_4naFEppE', '112.22.102.78', '江苏省,无锡市 移动', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', 'login', 'XMLHttpRequest', NULL, NULL, NULL, '2024-10-19 17:26:20', '2024-10-19 17:26:20', 1, 1, 0); +INSERT INTO `log_user_login` VALUES (1847571032372215810, 1, 'bunny', 'eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_yWLwQqDMBBE_2XPpmzcRDueSm9e-g8xJmBBW2sDltJ_74KHgeHNmy9tZaCOrmVZPlRR2p_U2bYGxLO4isqWXv2o7Ki3MCfVrViA2Xp3WddTfMx6vb8nXXLLHDRmHGIwLqIx55xgRADXINeePf3-HW6_BXcAAAA.b9oj6Y5gKeTmoAOI-hrOkkuoYODlO5gqGQHpvhigLxw', '112.22.102.78', '江苏省,无锡市 移动', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0', 'login', 'XMLHttpRequest', NULL, NULL, NULL, '2024-10-19 17:30:35', '2024-10-19 17:30:35', 1, 1, 0); -- ---------------------------- -- Table structure for qrtz_blob_triggers @@ -442,10 +441,10 @@ CREATE TABLE `sys_files` ( -- ---------------------------- -- Records of sys_files -- ---------------------------- -INSERT INTO `sys_files` VALUES (1842110808781082625, '5C7D14EDDC3ED2A9470F05FB60890431.png', '/auth-admin/avatar/2024/10-04/76ba1e92-4071-40da-ad1d-786c095caa83.png', 258720, 'image/png', 0, 1, NULL, NULL, '2024-10-04 15:53:36', 0); -INSERT INTO `sys_files` VALUES (1842212956680331265, 'blob', '/auth-admin/avatar/2024/10-04/d06ce74a-4c20-44cc-92be-e2cee9af70df', 1148373, 'image/png', 0, 1, '2024-10-05 06:39:30', 1, '2024-10-04 22:39:30', 0); -INSERT INTO `sys_files` VALUES (1845703953328300033, '1.jpg', '/auth-admin/avatar/2024/10-14/98b53ed4-f973-4d42-bdba-2c8760a5792c.jpg', 3338, 'image/jpeg', 4, 1, NULL, NULL, '2024-10-14 13:51:29', 0); -INSERT INTO `sys_files` VALUES (1845703953336688641, '2.jpg', '/auth-admin/avatar/2024/10-14/649e0a3e-9b12-4995-be38-17c59db996c2.jpg', 1646, 'image/jpeg', 0, 1, '2024-10-14 21:51:29', 1, '2024-10-14 13:51:29', 0); +INSERT INTO `sys_files` VALUES (1847572639960858626, 'blob', '/auth-admin/avatar/2024/10-19/d1e47ae9-9ca9-4ec5-a3d0-7208537e4df4', 20678, 'image/png', 0, 1, '2024-10-19 17:36:58', 1, '2024-10-19 17:36:58', 0); +INSERT INTO `sys_files` VALUES (1847572757975990273, 'blob', '/auth-admin/avatar/2024/10-19/9642c319-70b5-45b3-a7ed-a816fcd2092c', 43442, 'image/png', 0, 1, '2024-10-19 17:37:26', 1, '2024-10-19 17:37:26', 0); +INSERT INTO `sys_files` VALUES (1847572877920501762, 'blob', '/auth-admin/avatar/2024/10-19/da185724-906d-4f48-aaf5-4bbefd86f58e', 4319, 'image/png', 0, 1, '2024-10-19 17:37:55', 1, '2024-10-19 17:37:55', 0); +INSERT INTO `sys_files` VALUES (1847572991925878785, 'blob', '/auth-admin/avatar/2024/10-19/445fa7f4-a165-46ec-8ea2-e4d00dd1b790', 13841, 'image/png', 0, 1, '2024-10-19 17:38:22', 1, '2024-10-19 17:38:22', 0); -- ---------------------------- -- Table structure for sys_i18n @@ -1354,7 +1353,7 @@ INSERT INTO `sys_i18n` VALUES (1847142538338353154, 'quartzExecuteLog_endTime', INSERT INTO `sys_i18n` VALUES (1847142563105718274, 'quartzExecuteLog_endTime', '结束时间', 'zh', 1, 1, '2024-10-18 13:08:00', '2024-10-18 13:08:00', 0); INSERT INTO `sys_i18n` VALUES (1847149633842397185, 'confirm_update_sort', '是否确认更新排序', 'zh', 1, 1, '2024-10-18 13:36:06', '2024-10-18 13:36:06', 0); INSERT INTO `sys_i18n` VALUES (1847149685306507266, 'confirm_update_sort', 'confirm update sort', 'en', 1, 1, '2024-10-18 13:36:18', '2024-10-18 13:36:18', 0); -INSERT INTO `sys_i18n` VALUES (1847292350901882881, 'userLoginLog', '用户登录日志', 'zh', 1, 1, '2024-10-18 23:03:12', '2024-10-18 23:03:12', 0); +INSERT INTO `sys_i18n` VALUES (1847292350901882881, 'userLoginLog', '用户登录日志', 'zh', 1, 1, '2024-10-19 17:29:57', '2024-10-18 23:03:12', 0); INSERT INTO `sys_i18n` VALUES (1847292378651398146, 'userLoginLog', 'user login log', 'en', 1, 1, '2024-10-18 23:03:19', '2024-10-18 23:03:19', 0); INSERT INTO `sys_i18n` VALUES (1847292460075421698, 'userLoginLog_userId', 'user id', 'en', 1, 1, '2024-10-18 23:03:38', '2024-10-18 23:03:38', 0); INSERT INTO `sys_i18n` VALUES (1847292488735100930, 'userLoginLog_userId', '用户ID', 'zh', 1, 1, '2024-10-18 23:03:45', '2024-10-18 23:03:45', 0); @@ -1713,7 +1712,7 @@ INSERT INTO `sys_router` VALUES (1845812113861079042, 1846804024660791298, '/sch INSERT INTO `sys_router` VALUES (1846166163060285441, 1846804024660791298, '/scheduler/schedulersGroup', '/scheduler/schedulersGroup/index', '', 'schedulersGroup', 'schedulersGroup', 0, 'uis:layer-group', 6, 1, 1, 1, '2024-10-18 13:39:03', '2024-10-16 04:28:08', 0); INSERT INTO `sys_router` VALUES (1846804024660791298, 0, '/scheduler', '', '', 'scheduler', 'scheduler', 0, 'mingcute:time-fill', 4, 1, 1, 1, '2024-10-18 10:17:55', '2024-10-17 14:42:46', 0); INSERT INTO `sys_router` VALUES (1847140225619992577, 1844644093987880962, '/monitor/schedulerExecuteLog', '/monitor/schedulerExecuteLog/index', '', 'quartzExecuteLog', 'quartzExecuteLog', 0, 'octicon:log-16', 7, 1, 1, 1, '2024-10-18 22:33:07', '2024-10-18 12:58:43', 0); -INSERT INTO `sys_router` VALUES (1847291834822123521, 1844644093987880962, '/monitor/userLoginLog', '/monitor/userLoginLog/index', '', 'userLoginLog', 'userLoginLog', 0, 'ph:log-bold', 6, 1, 1, 1, '2024-10-18 23:08:53', '2024-10-18 23:01:09', 0); +INSERT INTO `sys_router` VALUES (1847291834822123521, 1844644093987880962, '/monitor/userLoginLog', '/monitor/userLoginLog/index', '', 'userLoginLog', 'userLoginLog', 0, 'ph:log-bold', 6, 1, 1, 1, '2024-10-19 17:29:32', '2024-10-18 23:01:09', 0); -- ---------------------------- -- Table structure for sys_router_role @@ -1764,10 +1763,10 @@ CREATE TABLE `sys_user` ( -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO `sys_user` VALUES (1, 'bunny', 'bunny', '1319900154@qq.com', '12345678910', '0192023a7bbd73250516f069df18b500', '/auth-admin/avatar/2024/10-13/b7508e5a-1e7c-4422-88a5-61f0431f2aaa', 1, 'admin123', '127.0.0.1', '内网IP', 0, '2024-09-26 14:29:33', '2024-10-19 03:17:23', 0, 1, 0); -INSERT INTO `sys_user` VALUES (1842091082096930817, 'password', 'password', 'password@qq.com', '123456', 'd7cfe615ccf8fdcbec37ea905a7dab90', '/auth-admin/avatar/2024/10-13/b4dff57f-df93-496a-9a00-e6355ec8c5bc', 0, 'passwordpasswordpassword', NULL, NULL, 0, '2024-10-04 14:35:13', '2024-10-13 01:18:09', 1, 1, 0); -INSERT INTO `sys_user` VALUES (1843477994034401281, '测试', '测试', '测试@qq.com', '测试', 'db06c78d1e24cf708a14ce81c9b617ec', '/auth-admin/avatar/2024/10-13/8f531e28-8bd3-456e-8ada-1b6fdb652ace', 0, '测试测试测试', NULL, NULL, 0, '2024-10-08 10:26:19', '2024-10-13 22:36:12', 1, 1, 0); -INSERT INTO `sys_user` VALUES (1843908587394150402, '啊啊啊', '啊啊啊', '啊啊啊@qq.com', '2312312321', 'fc0ec9e6c7c3e1821db2254238e6a98e', NULL, 0, '这个人很懒,没有介绍', NULL, NULL, 1, '2024-10-09 14:57:20', '2024-10-10 10:22:21', 1, 1, 0); +INSERT INTO `sys_user` VALUES (1, 'bunny', 'bunny', '1319900154@qq.com', '12345678910', '0192023a7bbd73250516f069df18b500', '/auth-admin/avatar/2024/10-19/d1e47ae9-9ca9-4ec5-a3d0-7208537e4df4', 1, 'admin123', '112.22.102.78', '江苏省,无锡市 移动', 0, '2024-09-26 14:29:33', '2024-10-19 17:36:58', 0, 1, 0); +INSERT INTO `sys_user` VALUES (1842091082096930817, 'password', 'password', 'password@qq.com', '123456', 'd7cfe615ccf8fdcbec37ea905a7dab90', '/auth-admin/avatar/2024/10-19/9642c319-70b5-45b3-a7ed-a816fcd2092c', 0, 'passwordpasswordpassword', NULL, NULL, 0, '2024-10-04 14:35:13', '2024-10-19 17:37:26', 1, 1, 0); +INSERT INTO `sys_user` VALUES (1843477994034401281, '测试', '测试', '测试@qq.com', '测试', 'db06c78d1e24cf708a14ce81c9b617ec', '/auth-admin/avatar/2024/10-19/da185724-906d-4f48-aaf5-4bbefd86f58e', 0, '测试测试测试', NULL, NULL, 0, '2024-10-08 10:26:19', '2024-10-19 17:37:55', 1, 1, 0); +INSERT INTO `sys_user` VALUES (1843908587394150402, '啊啊啊', '啊啊啊', '啊啊啊@qq.com', '2312312321', 'fc0ec9e6c7c3e1821db2254238e6a98e', '/auth-admin/avatar/2024/10-19/445fa7f4-a165-46ec-8ea2-e4d00dd1b790', 0, '这个人很懒,没有介绍', NULL, NULL, 1, '2024-10-09 14:57:20', '2024-10-19 17:38:22', 1, 1, 0); -- ---------------------------- -- Table structure for sys_user_dept diff --git a/service/Dockerfile b/service/Dockerfile index 88286fa..4a52015 100644 --- a/service/Dockerfile +++ b/service/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:17-jdk-alpine +FROM openjdk:17 MAINTAINER server #系统编码 @@ -22,7 +22,7 @@ VOLUME /etc/docker/daemon.json # 启动容器时的进程 ENTRYPOINT ["java","-jar","/home/server/app.jar"] -#暴露 7070 端口 +#暴露 8000 端口 EXPOSE 8000 # mvn clean package -Pprod -DskipTests diff --git a/service/src/main/java/cn/bunny/services/factory/EmailFactory.java b/service/src/main/java/cn/bunny/services/factory/EmailFactory.java index 9bf6202..ac87229 100644 --- a/service/src/main/java/cn/bunny/services/factory/EmailFactory.java +++ b/service/src/main/java/cn/bunny/services/factory/EmailFactory.java @@ -6,19 +6,18 @@ import cn.bunny.dao.entity.system.EmailTemplate; import cn.bunny.dao.entity.system.EmailUsers; import cn.bunny.dao.pojo.common.EmailSend; import cn.bunny.dao.pojo.common.EmailSendInit; -import cn.bunny.dao.pojo.enums.EmailTemplateEnums; import cn.bunny.dao.pojo.result.ResultCodeEnum; import cn.bunny.services.mapper.EmailTemplateMapper; import cn.bunny.services.mapper.EmailUsersMapper; -import cn.hutool.captcha.CaptchaUtil; -import cn.hutool.captcha.CircleCaptcha; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import jakarta.mail.MessagingException; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.List; + @Component public class EmailFactory { @@ -29,27 +28,18 @@ public class EmailFactory { private EmailUsersMapper emailUsersMapper; /** - * 生成邮箱验证码 - * - * @param email 接受者邮箱 + * * 发送邮件模板 + * 根据已存在的邮件模板发送邮件 */ - public String sendmailCode(String email) { - // 查询验证码邮件模板 - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(EmailTemplate::getIsDefault, true); - lambdaQueryWrapper.eq(EmailTemplate::getType, EmailTemplateEnums.VERIFICATION_CODE.getType()); - EmailTemplate emailTemplate = emailTemplateMapper.selectOne(lambdaQueryWrapper); - + public void sendEmailTemplate(String email, EmailTemplate emailTemplate, HashMap params) { // 判断邮件模板是否为空 if (emailTemplate == null) throw new BunnyException(ResultCodeEnum.EMAIL_TEMPLATE_IS_EMPTY); - // 查询配置发送邮箱 + // 查询配置发送邮箱,如果没有配置发件者邮箱改用用户列表中默认的,如果默认的也为空则报错 Long emailUser = emailTemplate.getEmailUser(); EmailUsers emailUsers; - // 如果没有配置发件者邮箱改用用户列表中默认的 if (emailUser == null) { emailUsers = emailUsersMapper.selectOne(Wrappers.lambdaQuery().eq(EmailUsers::getIsDefault, true)); - // 如果默认的也为空则报错 if (emailUsers == null) throw new BunnyException(ResultCodeEnum.EMAIL_USER_IS_EMPTY); } else { emailUsers = emailUsersMapper.selectOne(Wrappers.lambdaQuery().eq(EmailUsers::getId, emailUser)); @@ -59,28 +49,34 @@ public class EmailFactory { EmailSendInit emailSendInit = new EmailSendInit(); BeanUtils.copyProperties(emailUsers, emailSendInit); emailSendInit.setUsername(emailUsers.getEmail()); + emailSendInit.setProtocol(emailUsers.getSmtpAgreement()); - // 生成验证码 - CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2); - String code = captcha.getCode(); - String htmlContent = emailTemplate.getBody() - .replace("${sendEmailUser}", emailUsers.getEmail()) - .replace("${verifyCode}", code); + // 邮件发送模板 + EmailSend emailSend = new EmailSend(); + emailSend.setSubject(emailTemplate.getSubject()); + emailSend.setSendTo(List.of(email)); + emailSend.setRichText(true); - // 发送验证码 - MailSenderUtil mailSenderUtil = new MailSenderUtil(emailSendInit); + // 替换模板中字符串 + final String[] modifiedTemplate = {emailTemplate.getBody()}; + params.forEach((key, value) -> modifiedTemplate[0] = modifiedTemplate[0].replaceAll(key, String.valueOf(value))); + + // 发送邮件 try { - EmailSend emailSend = new EmailSend(); - emailSend.setSubject(emailTemplate.getSubject()); - emailSend.setMessage(htmlContent); - emailSend.setSendTo(email); - emailSend.setRichText(true); - mailSenderUtil.sendEmail(emailSend); + emailSend.setText(modifiedTemplate[0]); + MailSenderUtil.sendEmail(emailSendInit, emailSend); } catch (MessagingException e) { throw new BunnyException(ResultCodeEnum.SEND_MAIL_CODE_ERROR); } + } - return code; + /** + * * 发送邮件模板 + * 根据邮件模板发送邮件 + */ + public void sendEmailTemplate(String email, Long emailTemplateId, HashMap params) { + EmailTemplate emailTemplate = emailTemplateMapper.selectOne(Wrappers.lambdaQuery().eq(EmailTemplate::getId, emailTemplateId)); + sendEmailTemplate(email, emailTemplate, params); } /** diff --git a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java index 338b3f2..96bb284 100644 --- a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java +++ b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java @@ -10,9 +10,11 @@ import cn.bunny.dao.dto.system.user.*; import cn.bunny.dao.entity.log.UserLoginLog; import cn.bunny.dao.entity.system.AdminUser; import cn.bunny.dao.entity.system.AdminUserAndDept; +import cn.bunny.dao.entity.system.EmailTemplate; import cn.bunny.dao.entity.system.UserDept; import cn.bunny.dao.pojo.constant.MinioConstant; import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.pojo.enums.EmailTemplateEnums; import cn.bunny.dao.pojo.result.PageResult; import cn.bunny.dao.pojo.result.ResultCodeEnum; import cn.bunny.dao.vo.system.files.FileInfoVo; @@ -22,12 +24,12 @@ import cn.bunny.dao.vo.system.user.RefreshTokenVo; import cn.bunny.dao.vo.system.user.UserVo; import cn.bunny.services.factory.EmailFactory; import cn.bunny.services.factory.UserFactory; -import cn.bunny.services.mapper.UserDeptMapper; -import cn.bunny.services.mapper.UserLoginLogMapper; -import cn.bunny.services.mapper.UserMapper; -import cn.bunny.services.mapper.UserRoleMapper; +import cn.bunny.services.mapper.*; import cn.bunny.services.service.FilesService; import cn.bunny.services.service.UserService; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -45,6 +47,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; @@ -62,10 +65,10 @@ public class UserServiceImpl extends ServiceImpl implemen private UserFactory userFactory; @Autowired - private RedisTemplate redisTemplate; + private EmailFactory emailFactory; @Autowired - private EmailFactory emailFactory; + private RedisTemplate redisTemplate; @Autowired private MinioUtil minioUtil; @@ -82,6 +85,9 @@ public class UserServiceImpl extends ServiceImpl implemen @Autowired private UserLoginLogMapper userLoginLogMapper; + @Autowired + private EmailTemplateMapper emailTemplateMapper; + /** * 登录发送邮件验证码 * @@ -89,7 +95,28 @@ public class UserServiceImpl extends ServiceImpl implemen */ @Override public void sendLoginEmail(@NotNull String email) { - String emailCode = emailFactory.sendmailCode(email); + // 查询验证码邮件模板 + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(EmailTemplate::getIsDefault, true); + lambdaQueryWrapper.eq(EmailTemplate::getType, EmailTemplateEnums.VERIFICATION_CODE.getType()); + EmailTemplate emailTemplate = emailTemplateMapper.selectOne(lambdaQueryWrapper); + + // 生成验证码 + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2); + String emailCode = captcha.getCode(); + + // 需要替换模板内容 + HashMap hashMap = new HashMap<>(); + hashMap.put("#title#", "BunnyAdmin"); + hashMap.put("#verifyCode#", emailCode); + hashMap.put("#expires#", 15); + hashMap.put("#sendEmailUser#", emailTemplate.getEmailUser()); + hashMap.put("#companyName#", "BunnyAdmin"); + + // 发送邮件 + emailFactory.sendEmailTemplate(email, emailTemplate, hashMap); + + // 在Redis中存储验证码 redisTemplate.opsForValue().set(RedisUserConstant.getAdminUserEmailCodePrefix(email), emailCode); } diff --git a/service/src/test/java/cn/bunny/services/factory/EmailFactoryTest.java b/service/src/test/java/cn/bunny/services/factory/EmailFactoryTest.java new file mode 100644 index 0000000..b07af83 --- /dev/null +++ b/service/src/test/java/cn/bunny/services/factory/EmailFactoryTest.java @@ -0,0 +1,63 @@ +package cn.bunny.services.factory; + +import cn.bunny.common.service.utils.mail.MailSenderUtil; +import cn.bunny.dao.pojo.common.EmailSend; +import cn.bunny.dao.pojo.common.EmailSendInit; +import org.junit.jupiter.api.Test; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +class EmailFactoryTest { + @Test + void testSendEmail() throws Exception { + File file = new File("H:\\学习\\WpfApp2\\WpfApp2"); + List fileList = Arrays.stream(Objects.requireNonNull(file.listFiles())).map(file1 -> { + try { + return (MultipartFile) new MockMultipartFile("file", file.getName(), null, new FileInputStream(file1)); + } catch (IOException e) { + throw new RuntimeException(e); + } + }).toList(); + + // 初始化发送内容 + EmailSendInit emailSendInit = new EmailSendInit(); + emailSendInit.setUsername("3324855376@qq.com"); + emailSendInit.setPassword("fdehkkbmavalcjea"); + emailSendInit.setPort(465); + emailSendInit.setHost("smtp.qq.com"); + + // 发送邮件信息 + EmailSend emailSend = new EmailSend(); + emailSend.setSendTo(List.of("794demetris@rustyload.com", "a0w_q6ct@linshiyouxiang.net")); + emailSend.setSubject("测试邮件发送"); + emailSend.setText("

测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试

"); + emailSend.setRichText(true); + emailSend.setCcParam(List.of("tiec@snapmail.cc", "yenibex934@angewy.com")); + emailSend.setFiles(fileList.toArray(new MultipartFile[0])); + + // 发送邮件 + MailSenderUtil.sendEmail(emailSendInit, emailSend); + } + + @Test + void testReplace() { + final String[] modifiedTemplate = {"template"}; + + HashMap hashMap = new HashMap<>(); + hashMap.put("#title#", "BunnyAdmin"); + hashMap.put("#erifyCode#", "emailCode"); + hashMap.put("#expires#", 15); + hashMap.put("#sendEmailUser#", "emailUsers.getEmail()"); + hashMap.put("#companyName#", "BunnyAdmin"); + + hashMap.forEach((key, value) -> modifiedTemplate[0] = modifiedTemplate[0].replaceAll(key, String.valueOf(value))); + } +} \ No newline at end of file