feat: 添加短信和邮件发送
This commit is contained in:
51
src/main/java/com/youlai/system/config/MailConfig.java
Normal file
51
src/main/java/com/youlai/system/config/MailConfig.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package com.youlai.system.config;
|
||||||
|
|
||||||
|
import com.youlai.system.config.property.MailProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MailConfig 配置类,用于手动配置和注入 JavaMailSender。
|
||||||
|
* 通过读取 MailProperties 类中配置的邮件相关属性来初始化 JavaMailSender。
|
||||||
|
* <p>
|
||||||
|
* 手动注入的原因是为了避免在使用 application-dev.yml 或其他非 application.yml 配置文件时,
|
||||||
|
* IDEA 提示无法找到 JavaMailSender 的 bean。
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(MailProperties.class)
|
||||||
|
public class MailConfig {
|
||||||
|
|
||||||
|
private final MailProperties mailProperties;
|
||||||
|
|
||||||
|
public MailConfig(MailProperties mailProperties) {
|
||||||
|
this.mailProperties = mailProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建并配置 JavaMailSender bean。
|
||||||
|
*
|
||||||
|
* @return 配置好的 JavaMailSender 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public JavaMailSender javaMailSender() {
|
||||||
|
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||||
|
mailSender.setHost(mailProperties.getHost());
|
||||||
|
mailSender.setPort(mailProperties.getPort());
|
||||||
|
mailSender.setUsername(mailProperties.getUsername());
|
||||||
|
mailSender.setPassword(mailProperties.getPassword());
|
||||||
|
|
||||||
|
Properties properties = mailSender.getJavaMailProperties();
|
||||||
|
properties.put("mail.smtp.auth", mailProperties.getProperties().getSmtp().isAuth());
|
||||||
|
properties.put("mail.smtp.starttls.enable", mailProperties.getProperties().getSmtp().getStarttls().isEnable());
|
||||||
|
|
||||||
|
return mailSender;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.youlai.system.config.property;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云短信配置
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "sms.aliyun")
|
||||||
|
@Data
|
||||||
|
public class AliyunSmsProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云账户的Access Key ID,用于API请求认证
|
||||||
|
*/
|
||||||
|
private String accessKeyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*阿里云账户的Access Key Secret,用于API请求认证
|
||||||
|
*/
|
||||||
|
private String accessKeySecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云短信服务API的域名 eg: dysmsapi.aliyuncs.com
|
||||||
|
*/
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云服务的区域ID,如cn-shanghai
|
||||||
|
*/
|
||||||
|
private String regionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信签名,必须是已经在阿里云短信服务中注册并通过审核的
|
||||||
|
*/
|
||||||
|
private String signName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板编码
|
||||||
|
*/
|
||||||
|
private Map<String, String> templateCodes;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.youlai.system.config.property;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件配置类,用于接收和存储邮件相关的配置属性。
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "spring.mail")
|
||||||
|
@Data
|
||||||
|
public class MailProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务器主机名或 IP 地址。
|
||||||
|
* 例如:smtp.example.com
|
||||||
|
*/
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务器端口号。
|
||||||
|
* 例如:587
|
||||||
|
*/
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于连接邮件服务器的用户名。
|
||||||
|
* 例如:your_email@example.com
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于连接邮件服务器的密码。
|
||||||
|
* 该密码应安全存储,不应在代码中硬编码。
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件发送者地址。
|
||||||
|
*/
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务器的其他属性配置。
|
||||||
|
* 这些配置通常用于进一步定制邮件发送行为。
|
||||||
|
*/
|
||||||
|
private Properties properties = new Properties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部类,用于封装邮件服务器的详细配置。
|
||||||
|
* 包含 SMTP 相关的配置选项。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Properties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP 配置选项类。
|
||||||
|
* 包含认证、加密等与 SMTP 协议相关的配置。
|
||||||
|
*/
|
||||||
|
private Smtp smtp = new Smtp();
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Smtp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 SMTP 认证。
|
||||||
|
* 如果为 `true`,则需要提供有效的用户名和密码进行认证。
|
||||||
|
*/
|
||||||
|
private boolean auth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STARTTLS 加密配置选项。
|
||||||
|
*/
|
||||||
|
private StartTls starttls = new StartTls();
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class StartTls {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用 STARTTLS 加密。
|
||||||
|
* 如果为 `true`,在发送邮件时将启用 STARTTLS 协议进行加密传输。
|
||||||
|
*/
|
||||||
|
private boolean enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.youlai.system.common.result.PageResult;
|
import com.youlai.system.common.result.PageResult;
|
||||||
import com.youlai.system.common.result.Result;
|
import com.youlai.system.common.result.Result;
|
||||||
|
import com.youlai.system.enums.ContactType;
|
||||||
import com.youlai.system.model.form.PasswordChangeForm;
|
import com.youlai.system.model.form.PasswordChangeForm;
|
||||||
import com.youlai.system.model.form.PasswordResetForm;
|
|
||||||
import com.youlai.system.model.form.UserProfileForm;
|
import com.youlai.system.model.form.UserProfileForm;
|
||||||
import com.youlai.system.model.vo.UserProfileVO;
|
import com.youlai.system.model.vo.UserProfileVO;
|
||||||
import com.youlai.system.security.util.SecurityUtils;
|
import com.youlai.system.security.util.SecurityUtils;
|
||||||
@@ -167,7 +167,7 @@ public class SysUserController {
|
|||||||
@Operation(summary = "获取个人中心用户信息")
|
@Operation(summary = "获取个人中心用户信息")
|
||||||
@GetMapping("/{userId}/profile")
|
@GetMapping("/{userId}/profile")
|
||||||
public Result<UserProfileVO> getUserProfile(
|
public Result<UserProfileVO> getUserProfile(
|
||||||
@PathVariable Long userId
|
@Parameter(description = "用户ID") @PathVariable Long userId
|
||||||
) {
|
) {
|
||||||
UserProfileVO userProfile = userService.getUserProfile(userId);
|
UserProfileVO userProfile = userService.getUserProfile(userId);
|
||||||
return Result.success(userProfile);
|
return Result.success(userProfile);
|
||||||
@@ -188,20 +188,31 @@ public class SysUserController {
|
|||||||
@PreAuthorize("@ss.hasPerm('sys:user:password:reset')")
|
@PreAuthorize("@ss.hasPerm('sys:user:password:reset')")
|
||||||
public Result<?> resetPassword(
|
public Result<?> resetPassword(
|
||||||
@Parameter(description = "用户ID") @PathVariable Long userId,
|
@Parameter(description = "用户ID") @PathVariable Long userId,
|
||||||
@RequestParam String password
|
@RequestParam String password
|
||||||
) {
|
) {
|
||||||
boolean result = userService.resetPassword(userId, password);
|
boolean result = userService.resetPassword(userId, password);
|
||||||
return Result.judge(result);
|
return Result.judge(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "修改用户密码")
|
@Operation(summary = "修改密码")
|
||||||
@PutMapping(value = "/password")
|
@PutMapping(value = "/password")
|
||||||
public Result<?> changePassword(
|
public Result<?> changePassword(
|
||||||
@RequestParam PasswordChangeForm data
|
@RequestBody PasswordChangeForm data
|
||||||
) {
|
) {
|
||||||
Long currUserId = SecurityUtils.getUserId();
|
Long currUserId = SecurityUtils.getUserId();
|
||||||
boolean result = userService.changePassword(currUserId, data);
|
boolean result = userService.changePassword(currUserId, data);
|
||||||
return Result.judge(result);
|
return Result.judge(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "发送短信/邮箱验证码")
|
||||||
|
@PostMapping(value = "/send-verification-code")
|
||||||
|
public Result<?> sendVerificationCode(
|
||||||
|
@Parameter(description = "联系方式(手机号码或邮箱地址)", required = true) @RequestParam String contact,
|
||||||
|
@Parameter(description = "联系方式类型(Mobile或Email)", required = true) @RequestParam ContactType contactType
|
||||||
|
) {
|
||||||
|
boolean result = userService.sendVerificationCode(contact, contactType);
|
||||||
|
return Result.judge(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/main/java/com/youlai/system/enums/ContactType.java
Normal file
19
src/main/java/com/youlai/system/enums/ContactType.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.youlai.system.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系方式类型
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2.10.0
|
||||||
|
*/
|
||||||
|
public enum ContactType {
|
||||||
|
/**
|
||||||
|
* 手机
|
||||||
|
*/
|
||||||
|
MOBILE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
*/
|
||||||
|
EMAIL
|
||||||
|
}
|
||||||
31
src/main/java/com/youlai/system/service/MailService.java
Normal file
31
src/main/java/com/youlai/system/service/MailService.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package com.youlai.system.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务接口层
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
public interface MailService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送简单文本邮件
|
||||||
|
*
|
||||||
|
* @param to 收件人地址
|
||||||
|
* @param subject 邮件主题
|
||||||
|
* @param text 邮件内容
|
||||||
|
*/
|
||||||
|
boolean sendSimpleMail(String to, String subject, String text) ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送带附件的邮件
|
||||||
|
*
|
||||||
|
* @param to 收件人地址
|
||||||
|
* @param subject 邮件主题
|
||||||
|
* @param text 邮件内容
|
||||||
|
* @param filePath 附件路径
|
||||||
|
*/
|
||||||
|
boolean sendMailWithAttachment(String to, String subject, String text, String filePath);
|
||||||
|
|
||||||
|
}
|
||||||
22
src/main/java/com/youlai/system/service/SmsService.java
Normal file
22
src/main/java/com/youlai/system/service/SmsService.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.youlai.system.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信服务接口层
|
||||||
|
* <p>
|
||||||
|
* SMS = Short Message Service 短信服务
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
public interface SmsService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信
|
||||||
|
*
|
||||||
|
* @param mobile 手机号 13388886666
|
||||||
|
* @param templateCode 短信模板 SMS_194640010
|
||||||
|
* @param templateParam 模板参数 "[{"code":"123456"}]"
|
||||||
|
* @return boolean 是否发送成功
|
||||||
|
*/
|
||||||
|
boolean sendSms(String mobile, String templateCode, String templateParam);
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@ package com.youlai.system.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.youlai.system.enums.ContactType;
|
||||||
import com.youlai.system.model.entity.SysUser;
|
import com.youlai.system.model.entity.SysUser;
|
||||||
import com.youlai.system.model.form.PasswordChangeForm;
|
import com.youlai.system.model.form.PasswordChangeForm;
|
||||||
import com.youlai.system.model.form.PasswordResetForm;
|
|
||||||
import com.youlai.system.model.form.UserForm;
|
import com.youlai.system.model.form.UserForm;
|
||||||
import com.youlai.system.model.dto.UserAuthInfo;
|
import com.youlai.system.model.dto.UserAuthInfo;
|
||||||
import com.youlai.system.model.form.UserProfileForm;
|
import com.youlai.system.model.form.UserProfileForm;
|
||||||
@@ -127,4 +127,13 @@ public interface SysUserService extends IService<SysUser> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean resetPassword(Long userId, String password);
|
boolean resetPassword(Long userId, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送验证码
|
||||||
|
*
|
||||||
|
* @param contact 联系方式
|
||||||
|
* @param type 联系方式类型
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean sendVerificationCode(String contact, ContactType type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.youlai.system.common.constant.RedisConstants;
|
||||||
import com.youlai.system.common.constant.SystemConstants;
|
import com.youlai.system.common.constant.SystemConstants;
|
||||||
|
import com.youlai.system.config.property.AliyunSmsProperties;
|
||||||
import com.youlai.system.converter.UserConverter;
|
import com.youlai.system.converter.UserConverter;
|
||||||
|
import com.youlai.system.enums.ContactType;
|
||||||
import com.youlai.system.exception.BusinessException;
|
import com.youlai.system.exception.BusinessException;
|
||||||
import com.youlai.system.model.form.PasswordChangeForm;
|
import com.youlai.system.model.form.PasswordChangeForm;
|
||||||
import com.youlai.system.model.form.PasswordResetForm;
|
import com.youlai.system.model.form.PasswordResetForm;
|
||||||
@@ -28,6 +31,8 @@ import com.youlai.system.model.vo.UserPageVO;
|
|||||||
import com.youlai.system.security.service.PermissionService;
|
import com.youlai.system.security.service.PermissionService;
|
||||||
import com.youlai.system.service.*;
|
import com.youlai.system.service.*;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -35,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,6 +65,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
|
|
||||||
private final PermissionService permissionService;
|
private final PermissionService permissionService;
|
||||||
|
|
||||||
|
private final SmsService smsService;
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
|
||||||
|
private final AliyunSmsProperties aliyunSmsProperties;
|
||||||
|
|
||||||
|
private final StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户分页列表
|
* 获取用户分页列表
|
||||||
*
|
*
|
||||||
@@ -286,6 +300,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
|
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
|
||||||
throw new BusinessException("原密码错误");
|
throw new BusinessException("原密码错误");
|
||||||
}
|
}
|
||||||
|
// 新旧密码不能相同
|
||||||
|
if (passwordEncoder.matches(data.getNewPassword(), user.getPassword())) {
|
||||||
|
throw new BusinessException("新密码不能与原密码相同");
|
||||||
|
}
|
||||||
|
|
||||||
String newPassword = data.getNewPassword();
|
String newPassword = data.getNewPassword();
|
||||||
return this.update(new LambdaUpdateWrapper<SysUser>()
|
return this.update(new LambdaUpdateWrapper<SysUser>()
|
||||||
@@ -297,8 +315,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
/**
|
/**
|
||||||
* 重置密码
|
* 重置密码
|
||||||
*
|
*
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
* @param password 密码重置表单数据
|
* @param password 密码重置表单数据
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -308,4 +326,38 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
.set(SysUser::getPassword, passwordEncoder.encode(password))
|
.set(SysUser::getPassword, passwordEncoder.encode(password))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送验证码
|
||||||
|
*
|
||||||
|
* @param contact 联系方式 手机号/邮箱
|
||||||
|
* @param type 联系方式类型 {@link ContactType}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean sendVerificationCode(String contact, ContactType type) {
|
||||||
|
|
||||||
|
// 随机生成4位验证码
|
||||||
|
String code = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
|
||||||
|
// 发送验证码
|
||||||
|
|
||||||
|
String verificationCodePrefix = null;
|
||||||
|
switch (type) {
|
||||||
|
case MOBILE:
|
||||||
|
// 获取修改密码的模板code
|
||||||
|
String changePasswordSmsTemplateCode = aliyunSmsProperties.getTemplateCodes().get("changePassword");
|
||||||
|
smsService.sendSms(contact, changePasswordSmsTemplateCode, "[{\"code\":\"" + code + "\"}]");
|
||||||
|
verificationCodePrefix = RedisConstants.MOBILE_VERIFICATION_CODE_PREFIX;
|
||||||
|
break;
|
||||||
|
case EMAIL:
|
||||||
|
mailService.sendSimpleMail(contact, "验证码", "您的验证码是:" + code);
|
||||||
|
verificationCodePrefix = RedisConstants.EMAIL_VERIFICATION_CODE_PREFIX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new BusinessException("不支持的联系方式类型");
|
||||||
|
}
|
||||||
|
// 存入 redis 用于校验, 5分钟有效
|
||||||
|
redisTemplate.opsForValue().set(verificationCodePrefix + contact, code, 5, TimeUnit.MINUTES );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package com.youlai.system.service.impl.mail;
|
||||||
|
|
||||||
|
import com.youlai.system.config.property.MailProperties;
|
||||||
|
import com.youlai.system.service.MailService;
|
||||||
|
import jakarta.mail.MessagingException;
|
||||||
|
import jakarta.mail.internet.MimeMessage;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件服务实现类
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class MailServiceImpl implements MailService {
|
||||||
|
|
||||||
|
private final JavaMailSender mailSender;
|
||||||
|
|
||||||
|
private final MailProperties mailProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送简单文本邮件
|
||||||
|
*
|
||||||
|
* @param to 收件人地址
|
||||||
|
* @param subject 邮件主题
|
||||||
|
* @param text 邮件内容
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean sendSimpleMail(String to, String subject, String text) {
|
||||||
|
try {
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setFrom(mailProperties.getFrom());
|
||||||
|
message.setTo(to);
|
||||||
|
message.setSubject(subject);
|
||||||
|
message.setText(text);
|
||||||
|
mailSender.send(message);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("发送邮件失败{}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送带附件的邮件
|
||||||
|
*
|
||||||
|
* @param to 收件人地址
|
||||||
|
* @param subject 邮件主题
|
||||||
|
* @param text 邮件内容
|
||||||
|
* @param filePath 附件路径
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean sendMailWithAttachment(String to, String subject, String text, String filePath) {
|
||||||
|
MimeMessage message = mailSender.createMimeMessage();
|
||||||
|
try {
|
||||||
|
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||||
|
helper.setFrom(mailProperties.getFrom());
|
||||||
|
helper.setTo(to);
|
||||||
|
helper.setSubject(subject);
|
||||||
|
helper.setText(text, true); // true表示支持HTML内容
|
||||||
|
|
||||||
|
FileSystemResource file = new FileSystemResource(new File(filePath));
|
||||||
|
helper.addAttachment(file.getFilename(), file);
|
||||||
|
|
||||||
|
mailSender.send(message);
|
||||||
|
return true;
|
||||||
|
} catch (MessagingException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.youlai.system.service.impl.sms;
|
||||||
|
|
||||||
|
import com.aliyuncs.CommonRequest;
|
||||||
|
import com.aliyuncs.CommonResponse;
|
||||||
|
import com.aliyuncs.DefaultAcsClient;
|
||||||
|
import com.aliyuncs.IAcsClient;
|
||||||
|
import com.aliyuncs.exceptions.ClientException;
|
||||||
|
import com.aliyuncs.exceptions.ServerException;
|
||||||
|
import com.aliyuncs.http.MethodType;
|
||||||
|
import com.aliyuncs.profile.DefaultProfile;
|
||||||
|
import com.youlai.system.config.property.AliyunSmsProperties;
|
||||||
|
import com.youlai.system.service.SmsService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云短信业务类
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2024/8/17
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AliyunSmsService implements SmsService {
|
||||||
|
|
||||||
|
private final AliyunSmsProperties aliyunSmsProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信验证码
|
||||||
|
*
|
||||||
|
* @param mobile 手机号 13388886666
|
||||||
|
* @param templateCode 短信模板 SMS_194640010
|
||||||
|
* @param templateParam 模板参数 "[{"code":"123456"}]"
|
||||||
|
*
|
||||||
|
* @return boolean 是否发送成功
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean sendSms(String mobile,String templateCode,String templateParam) {
|
||||||
|
|
||||||
|
DefaultProfile profile = DefaultProfile.getProfile(aliyunSmsProperties.getRegionId(),
|
||||||
|
aliyunSmsProperties.getAccessKeyId(), aliyunSmsProperties.getAccessKeySecret());
|
||||||
|
IAcsClient client = new DefaultAcsClient(profile);
|
||||||
|
|
||||||
|
// 创建通用的请求对象
|
||||||
|
CommonRequest request = new CommonRequest();
|
||||||
|
// 指定请求方式
|
||||||
|
request.setSysMethod(MethodType.POST);
|
||||||
|
// 短信api的请求地址(固定)
|
||||||
|
request.setSysDomain(aliyunSmsProperties.getDomain());
|
||||||
|
// 签名算法版(固定)
|
||||||
|
request.setSysVersion("2017-05-25");
|
||||||
|
// 请求 API 的名称(固定)
|
||||||
|
request.setSysAction("SendSms");
|
||||||
|
// 指定地域名称
|
||||||
|
request.putQueryParameter("RegionId", aliyunSmsProperties.getRegionId());
|
||||||
|
// 要给哪个手机号发送短信 指定手机号
|
||||||
|
request.putQueryParameter("PhoneNumbers", mobile);
|
||||||
|
// 您的申请签名
|
||||||
|
request.putQueryParameter("SignName", aliyunSmsProperties.getSignName());
|
||||||
|
// 您申请的模板 code
|
||||||
|
request.putQueryParameter("TemplateCode", templateCode);
|
||||||
|
|
||||||
|
request.putQueryParameter("TemplateParam", templateParam);
|
||||||
|
|
||||||
|
try {
|
||||||
|
CommonResponse response = client.getCommonResponse(request);
|
||||||
|
return response.getHttpResponse().isSuccess();
|
||||||
|
} catch (ServerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClientException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user