From 22079719f02ebb05881302be0757d8d2ee18aad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Thu, 28 Aug 2025 21:02:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(email):=20=E5=AE=9E=E7=8E=B0=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E6=A8=A1=E6=9D=BF=E7=B3=BB=E7=BB=9F=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=82=AE=E4=BB=B6=E5=8F=91=E9=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 EmailTemplateUtil 工具类,用于管理邮件模板和发送逻辑 - 在 MainController 中集成 EmailTemplateUtil,用于发送注册成功邮件 - 添加密码重置和通用通知邮件模板 - 实现邮件发送的降级机制,HTML邮件发送失败时自动发送文本邮件 - 添加邮件模板配置和发送设置配置 - 提供异步发送和模板缓存优化建议 --- docs/EMAIL_TEMPLATES.md | 220 +++++++++++ .../system/controller/MainController.java | 13 +- .../common/system/util/EmailTemplateUtil.java | 195 ++++++++++ src/main/resources/email-templates.yml | 75 ++++ .../resources/templates/notification.html | 260 +++++++++++++ .../resources/templates/password-reset.html | 323 ++++++++++++++++ .../resources/templates/register-success.html | 351 ++++++++++++++++++ src/test/java/com/gxwebsoft/TestMain.java | 3 - 8 files changed, 1429 insertions(+), 11 deletions(-) create mode 100644 docs/EMAIL_TEMPLATES.md create mode 100644 src/main/java/com/gxwebsoft/common/system/util/EmailTemplateUtil.java create mode 100644 src/main/resources/email-templates.yml create mode 100644 src/main/resources/templates/notification.html create mode 100644 src/main/resources/templates/password-reset.html create mode 100644 src/main/resources/templates/register-success.html diff --git a/docs/EMAIL_TEMPLATES.md b/docs/EMAIL_TEMPLATES.md new file mode 100644 index 0000000..d0e8bfe --- /dev/null +++ b/docs/EMAIL_TEMPLATES.md @@ -0,0 +1,220 @@ +# WebSoft 邮件模板系统 + +## 概述 + +WebSoft 邮件模板系统提供了一套专业的HTML邮件模板,用于提升企业品牌影响力和用户体验。系统采用Beetl模板引擎,支持动态数据绑定和响应式设计。 + +## 模板列表 + +### 1. 注册成功邮件 (`register-success.html`) +- **用途**: 用户注册成功后发送的欢迎邮件 +- **特点**: + - 专业的品牌展示 + - 账号信息展示 + - 功能特性介绍 + - 安全提醒 +- **变量**: + - `username`: 用户名 + - `phone`: 手机号 + - `password`: 密码 + - `email`: 邮箱(可选) + +### 2. 密码重置邮件 (`password-reset.html`) +- **用途**: 用户密码重置后发送的通知邮件 +- **特点**: + - 安全警告设计 + - 重置信息展示 + - 安全建议 +- **变量**: + - `username`: 用户名 + - `phone`: 手机号 + - `newPassword`: 新密码 + - `resetTime`: 重置时间 + +### 3. 通用通知邮件 (`notification.html`) +- **用途**: 系统通知、公告等通用邮件 +- **特点**: + - 灵活的内容结构 + - 可选的操作按钮 + - 时间戳显示 +- **变量**: + - `title`: 邮件标题 + - `content`: 邮件内容 + - `greeting`: 问候语(可选) + - `infoMessage`: 提示信息(可选) + - `actionUrl`: 操作链接(可选) + - `actionText`: 操作按钮文字(可选) + - `sendTime`: 发送时间 + +## 使用方法 + +### 1. 直接使用EmailRecordService + +```java +@Resource +private EmailRecordService emailRecordService; + +// 发送HTML邮件 +Map data = new HashMap<>(); +data.put("username", "张三"); +data.put("phone", "13800138000"); +data.put("password", "123456"); + +emailRecordService.sendHtmlEmail( + "恭喜!您的WebSoft账号已注册成功", + "register-success.html", + data, + new String[]{"user@example.com"} +); +``` + +### 2. 使用EmailTemplateUtil工具类(推荐) + +```java +@Resource +private EmailTemplateUtil emailTemplateUtil; + +// 发送注册成功邮件 +emailTemplateUtil.sendRegisterSuccessEmail( + "张三", "13800138000", "123456", "user@example.com", 1001 +); + +// 发送密码重置邮件 +emailTemplateUtil.sendPasswordResetEmail( + "张三", "13800138000", "newPassword123", "user@example.com", 1001 +); + +// 发送通用通知邮件 +emailTemplateUtil.sendNotificationEmail( + "系统维护通知", + "系统将在今晚进行维护,请提前保存工作。", + "user@example.com", + 1001 +); + +// 发送带操作按钮的通知邮件 +emailTemplateUtil.sendNotificationEmailWithAction( + "订单状态更新", + "您的订单已发货", + "user@example.com", + 1001, + "https://www.gxwebsoft.com/orders/12345", + "查看订单" +); +``` + +## 模板特性 + +### 1. 响应式设计 +- 支持桌面和移动设备 +- 自适应屏幕尺寸 +- 优化的移动端体验 + +### 2. 品牌一致性 +- 统一的视觉风格 +- 企业Logo和品牌色彩 +- 专业的排版设计 + +### 3. 安全性 +- 密码信息安全展示 +- 安全提醒和建议 +- 防钓鱼设计 + +### 4. 用户体验 +- 清晰的信息层次 +- 明显的操作按钮 +- 友好的提示信息 + +## 自定义模板 + +### 1. 创建新模板 +1. 在 `src/main/resources/templates/` 目录下创建HTML文件 +2. 使用Beetl语法进行变量绑定 +3. 遵循现有模板的样式规范 + +### 2. Beetl语法示例 +```html + +${username!} + + +<% if(email!) { %> +
邮箱:${email!}
+<% } %> + + +<% for(item in items!) { %> +
  • ${item.name!}
  • +<% } %> +``` + +### 3. 样式规范 +- 使用内联CSS确保兼容性 +- 遵循响应式设计原则 +- 保持品牌色彩一致性 + +## 配置说明 + +### 1. 邮件配置 (`application.yml`) +```yaml +spring: + mail: + host: smtp.qq.com + port: 587 + username: your-email@qq.com + password: your-password + properties: + mail: + smtp: + auth: true + starttls: + enable: true +``` + +### 2. 模板配置 (`email-templates.yml`) +- 品牌信息配置 +- 链接地址配置 +- 样式颜色配置 +- 发送设置配置 + +## 最佳实践 + +### 1. 错误处理 +- 实现HTML邮件发送失败时的文本邮件降级 +- 记录邮件发送日志 +- 提供重试机制 + +### 2. 性能优化 +- 使用邮件队列异步发送 +- 缓存模板编译结果 +- 批量发送优化 + +### 3. 安全考虑 +- 验证收件人邮箱格式 +- 防止邮件内容注入 +- 敏感信息脱敏处理 + +## 故障排除 + +### 1. 模板不存在 +- 检查模板文件路径 +- 确认文件名拼写正确 +- 验证classpath配置 + +### 2. 变量未显示 +- 检查变量名是否正确 +- 确认数据是否传递 +- 验证Beetl语法 + +### 3. 样式问题 +- 检查CSS兼容性 +- 验证邮件客户端支持 +- 测试不同设备显示效果 + +## 更新日志 + +### v1.0.0 (2024-08-28) +- 初始版本发布 +- 提供注册成功、密码重置、通用通知三种模板 +- 实现EmailTemplateUtil工具类 +- 支持响应式设计和品牌定制 diff --git a/src/main/java/com/gxwebsoft/common/system/controller/MainController.java b/src/main/java/com/gxwebsoft/common/system/controller/MainController.java index cfa84a1..5bce32c 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/MainController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/MainController.java @@ -38,6 +38,7 @@ import com.gxwebsoft.common.system.param.UserParam; import com.gxwebsoft.common.system.result.CaptchaResult; import com.gxwebsoft.common.system.result.LoginResult; import com.gxwebsoft.common.system.service.*; +import com.gxwebsoft.common.system.util.EmailTemplateUtil; import com.wf.captcha.SpecCaptcha; import io.jsonwebtoken.Claims; import io.swagger.annotations.Api; @@ -95,6 +96,8 @@ public class MainController extends BaseController { private UserRefereeService userRefereeService; @Resource private EmailRecordService emailRecordService; + @Resource + private EmailTemplateUtil emailTemplateUtil; @ApiOperation("用户登录") @@ -644,14 +647,8 @@ public class MainController extends BaseController { String access_token = JwtUtil.buildToken(new JwtSubject(phone, addUser.getTenantId()), tokenExpireTime, configProperties.getTokenKey()); // 发送邮件通知 - String title = "恭喜!您的WebSoft账号已注册成功"; - String appUrl = "\r\n用户名:" + username; - String passwordStr = "\r\n密码:" + password; - String appName = "\r\n手机号码:" + phone; - String content = title + appUrl + appName + passwordStr; - // 发送邮件通知 - if (email != null) { - emailRecordService.sendEmail(title, content, email, addUser.getTenantId()); + if(ObjectUtil.isNotEmpty(addUser) && email != null){ + emailTemplateUtil.sendRegisterSuccessEmail(username, phone, password, email, addUser.getTenantId()); } return success("注册成功", new LoginResult(access_token, addUser)); } diff --git a/src/main/java/com/gxwebsoft/common/system/util/EmailTemplateUtil.java b/src/main/java/com/gxwebsoft/common/system/util/EmailTemplateUtil.java new file mode 100644 index 0000000..10931b6 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/util/EmailTemplateUtil.java @@ -0,0 +1,195 @@ +package com.gxwebsoft.common.system.util; + +import cn.hutool.core.date.DateUtil; +import com.gxwebsoft.common.system.service.EmailRecordService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +/** + * 邮件模板工具类 + * 统一管理邮件模板和发送逻辑 + * + * @author WebSoft + * @since 2024-08-28 + */ +@Component +public class EmailTemplateUtil { + + @Resource + private EmailRecordService emailRecordService; + + /** + * 发送注册成功邮件 + * + * @param username 用户名 + * @param phone 手机号 + * @param password 密码 + * @param email 邮箱 + * @param tenantId 租户ID + */ + public void sendRegisterSuccessEmail(String username, String phone, String password, String email, Integer tenantId) { + try { + String title = "恭喜!您的账号已注册成功"; + Map data = new HashMap<>(); + data.put("username", username); + data.put("phone", phone); + data.put("password", password); + data.put("email", email); + + emailRecordService.sendHtmlEmail(title, "register-success.html", data, new String[]{email}); + } catch (Exception e) { + // 如果HTML邮件发送失败,降级为文本邮件 + String content = "恭喜!您的WebSoft账号已注册成功\r\n用户名:" + username + "\r\n手机号码:" + phone + "\r\n密码:" + password; + emailRecordService.sendEmail("恭喜!您的WebSoft账号已注册成功", content, email, tenantId); + } + } + + /** + * 发送密码重置邮件 + * + * @param username 用户名 + * @param phone 手机号 + * @param newPassword 新密码 + * @param email 邮箱 + * @param tenantId 租户ID + */ + public void sendPasswordResetEmail(String username, String phone, String newPassword, String email, Integer tenantId) { + try { + String title = "WebSoft密码重置通知"; + Map data = new HashMap<>(); + data.put("username", username); + data.put("phone", phone); + data.put("newPassword", newPassword); + data.put("resetTime", DateUtil.now()); + + emailRecordService.sendHtmlEmail(title, "password-reset.html", data, new String[]{email}); + } catch (Exception e) { + // 如果HTML邮件发送失败,降级为文本邮件 + String content = "您的WebSoft账号密码已重置\r\n用户名:" + username + "\r\n手机号码:" + phone + "\r\n新密码:" + newPassword + "\r\n重置时间:" + DateUtil.now(); + emailRecordService.sendEmail("WebSoft密码重置通知", content, email, tenantId); + } + } + + /** + * 发送通用通知邮件 + * + * @param title 邮件标题 + * @param content 邮件内容 + * @param email 收件人邮箱 + * @param tenantId 租户ID + * @param greeting 问候语(可选) + * @param infoMessage 提示信息(可选) + * @param actionUrl 操作链接(可选) + * @param actionText 操作按钮文字(可选) + */ + public void sendNotificationEmail(String title, String content, String email, Integer tenantId, + String greeting, String infoMessage, String actionUrl, String actionText) { + try { + Map data = new HashMap<>(); + data.put("title", title); + data.put("content", content); + data.put("sendTime", DateUtil.now()); + + if (greeting != null) { + data.put("greeting", greeting); + } + if (infoMessage != null) { + data.put("infoMessage", infoMessage); + } + if (actionUrl != null) { + data.put("actionUrl", actionUrl); + } + if (actionText != null) { + data.put("actionText", actionText); + } + + emailRecordService.sendHtmlEmail(title, "notification.html", data, new String[]{email}); + } catch (Exception e) { + // 如果HTML邮件发送失败,降级为文本邮件 + emailRecordService.sendEmail(title, content, email, tenantId); + } + } + + /** + * 发送简单通知邮件 + * + * @param title 邮件标题 + * @param content 邮件内容 + * @param email 收件人邮箱 + * @param tenantId 租户ID + */ + public void sendNotificationEmail(String title, String content, String email, Integer tenantId) { + sendNotificationEmail(title, content, email, tenantId, null, null, null, null); + } + + /** + * 发送带操作按钮的通知邮件 + * + * @param title 邮件标题 + * @param content 邮件内容 + * @param email 收件人邮箱 + * @param tenantId 租户ID + * @param actionUrl 操作链接 + * @param actionText 操作按钮文字 + */ + public void sendNotificationEmailWithAction(String title, String content, String email, Integer tenantId, + String actionUrl, String actionText) { + sendNotificationEmail(title, content, email, tenantId, null, null, actionUrl, actionText); + } + + /** + * 发送账户安全提醒邮件 + * + * @param username 用户名 + * @param phone 手机号 + * @param email 邮箱 + * @param tenantId 租户ID + * @param event 安全事件描述 + */ + public void sendSecurityAlertEmail(String username, String phone, String email, Integer tenantId, String event) { + String title = "WebSoft账户安全提醒"; + String content = "您的账户发生了以下安全事件:" + event + "。如果这不是您本人的操作,请立即联系客服并修改密码。"; + String infoMessage = "为了保障您的账户安全,建议您定期修改密码并开启双重验证。"; + String actionUrl = "https://www.gxwebsoft.com/security"; + String actionText = "查看安全设置"; + + sendNotificationEmail(title, content, email, tenantId, "尊敬的用户", infoMessage, actionUrl, actionText); + } + + /** + * 发送系统维护通知邮件 + * + * @param email 收件人邮箱 + * @param tenantId 租户ID + * @param maintenanceTime 维护时间 + * @param duration 维护时长 + */ + public void sendMaintenanceNotificationEmail(String email, Integer tenantId, String maintenanceTime, String duration) { + String title = "WebSoft系统维护通知"; + String content = "为了提供更好的服务,我们将在 " + maintenanceTime + " 进行系统维护,预计维护时长:" + duration + "。维护期间可能会影响系统的正常使用,给您带来的不便敬请谅解。"; + String infoMessage = "维护完成后,系统将自动恢复正常服务。"; + + sendNotificationEmail(title, content, email, tenantId, "尊敬的用户", infoMessage, null, null); + } + + /** + * 发送订单状态变更邮件 + * + * @param username 用户名 + * @param orderNo 订单号 + * @param status 订单状态 + * @param email 邮箱 + * @param tenantId 租户ID + */ + public void sendOrderStatusEmail(String username, String orderNo, String status, String email, Integer tenantId) { + String title = "WebSoft订单状态更新"; + String content = "您的订单 " + orderNo + " 状态已更新为:" + status + "。"; + String actionUrl = "https://www.gxwebsoft.com/orders/" + orderNo; + String actionText = "查看订单详情"; + + sendNotificationEmailWithAction(title, content, email, tenantId, actionUrl, actionText); + } +} diff --git a/src/main/resources/email-templates.yml b/src/main/resources/email-templates.yml new file mode 100644 index 0000000..dac93af --- /dev/null +++ b/src/main/resources/email-templates.yml @@ -0,0 +1,75 @@ +# 邮件模板配置文件 +# 用于管理邮件模板的基本信息和品牌设置 + +email: + templates: + # 品牌信息 + brand: + name: "WebSoft" + company: "南宁网宿信息科技有限公司" + description: "企业级数字化解决方案" + website: "https://www.gxwebsoft.com" + support_email: "170083662@qq.com" + logo_url: "https://www.gxwebsoft.com/logo.png" + + # 链接配置 + links: + login: "https://www.gxwebsoft.com/login" + help: "https://www.gxwebsoft.com/help" + contact: "https://www.gxwebsoft.com/contact" + security: "https://www.gxwebsoft.com/security" + + # 模板列表 + templates: + register-success: + name: "注册成功邮件" + description: "用户注册成功后发送的欢迎邮件" + file: "register-success.html" + subject: "恭喜!您的WebSoft账号已注册成功" + + password-reset: + name: "密码重置邮件" + description: "用户密码重置后发送的通知邮件" + file: "password-reset.html" + subject: "WebSoft密码重置通知" + + notification: + name: "通用通知邮件" + description: "系统通知、公告等通用邮件模板" + file: "notification.html" + subject: "WebSoft系统通知" + + security-alert: + name: "安全提醒邮件" + description: "账户安全相关的提醒邮件" + file: "notification.html" + subject: "WebSoft账户安全提醒" + + maintenance: + name: "系统维护通知" + description: "系统维护时发送的通知邮件" + file: "notification.html" + subject: "WebSoft系统维护通知" + + order-status: + name: "订单状态更新" + description: "订单状态变更时发送的通知邮件" + file: "notification.html" + subject: "WebSoft订单状态更新" + + # 邮件样式配置 + styles: + primary_color: "#667eea" + secondary_color: "#764ba2" + success_color: "#4CAF50" + warning_color: "#ffa502" + danger_color: "#ff6b6b" + info_color: "#4facfe" + + # 邮件发送配置 + settings: + retry_times: 3 + timeout: 30000 + fallback_to_text: true + track_opens: true + track_clicks: true diff --git a/src/main/resources/templates/notification.html b/src/main/resources/templates/notification.html new file mode 100644 index 0000000..083d0ba --- /dev/null +++ b/src/main/resources/templates/notification.html @@ -0,0 +1,260 @@ + + + + + + WebSoft通知 + + + + + + diff --git a/src/main/resources/templates/password-reset.html b/src/main/resources/templates/password-reset.html new file mode 100644 index 0000000..830c77d --- /dev/null +++ b/src/main/resources/templates/password-reset.html @@ -0,0 +1,323 @@ + + + + + + WebSoft密码重置 + + + + + + diff --git a/src/main/resources/templates/register-success.html b/src/main/resources/templates/register-success.html new file mode 100644 index 0000000..718aa00 --- /dev/null +++ b/src/main/resources/templates/register-success.html @@ -0,0 +1,351 @@ + + + + + + WebSoft账号注册成功 + + + + + + diff --git a/src/test/java/com/gxwebsoft/TestMain.java b/src/test/java/com/gxwebsoft/TestMain.java index 8bcc707..3b0da5c 100644 --- a/src/test/java/com/gxwebsoft/TestMain.java +++ b/src/test/java/com/gxwebsoft/TestMain.java @@ -1,12 +1,9 @@ package com.gxwebsoft; import com.gxwebsoft.common.core.security.JwtUtil; -import com.gxwebsoft.common.core.utils.DomainUtil; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import static com.gxwebsoft.common.core.constants.DomainConstants.DOMAIN; - /** * Created by WebSoft on 2020-03-23 23:37 */