feat(邮件): 发送简单邮件和带附件邮件

This commit is contained in:
bunny 2024-05-07 14:15:49 +08:00
parent 64cd44dc8c
commit 6ff2a0a6c4
21 changed files with 411 additions and 164 deletions

View File

@ -28,7 +28,7 @@
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<!-- 数据库代码生成器 -->
<!-- 数据库代码生成器 - 新版 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
@ -39,6 +39,7 @@
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!-- 数据库代码生成器 - 旧版 -->
<!-- <dependency> -->
<!-- <groupId>com.baomidou</groupId> -->
<!-- <artifactId>mybatis-plus-generator</artifactId> -->

View File

@ -15,6 +15,7 @@
<module>service-utils</module>
<module>common-utils</module>
<module>spring-security</module>
<module>service-mail</module>
</modules>
<dependencies>

View File

@ -0,0 +1,33 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>service-mail</artifactId>
<packaging>jar</packaging>
<name>service-mail</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 邮箱 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,4 @@
package cn.bunny.common.email.config;
public class EmailConfig {
}

View File

@ -0,0 +1,75 @@
package cn.bunny.common.email.utils;
import cn.bunny.entity.email.EmailSend;
import cn.bunny.entity.email.EmailSendInit;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.web.multipart.MultipartFile;
import java.util.Objects;
public class MailSender {
private final String username;
private final JavaMailSenderImpl javaMailSender;
/**
* 初始化构造函数进行当前类赋值
*/
public MailSender(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.setDefaultEncoding("UTF-8");
this.username = emailSendInit.getUsername();
this.javaMailSender = javaMailSender;
}
/**
* 发送邮件-简单
*
* @param emailSend 邮件消息
*/
public void sendSimpleEmail(EmailSend emailSend) {
// 创建邮件消息体 SimpleMailMessage 发送简单邮件
SimpleMailMessage mailMessage = new SimpleMailMessage();
// 设置邮件发送人
mailMessage.setFrom(username);
// 设置邮件接受者
mailMessage.setTo(emailSend.getSendTo());
// 设置邮件主题
mailMessage.setSubject(emailSend.getSubject());
// 设置邮件消息
mailMessage.setText(emailSend.getMessage());
javaMailSender.send(mailMessage);
}
public void sendAttachmentEmail(EmailSend emailSend, MultipartFile file) throws MessagingException {
// 创建 MimeMessage 对象用户发送附件或者是富文本内容
MimeMessage mailMessage = javaMailSender.createMimeMessage();
// 创建 MimeMessageHelper
MimeMessageHelper helper = new MimeMessageHelper(mailMessage, true);
// 奢姿邮件发送人
helper.setFrom(username);
// 设置邮件接受者
helper.setTo(emailSend.getSendTo());
// 设置邮件消息
helper.setText(emailSend.getMessage());
// 设置邮件主题
helper.setSubject(emailSend.getSubject());
// 邮件添加附件
helper.addAttachment(Objects.requireNonNull(file.getOriginalFilename()), file);
// 发送邮件
javaMailSender.send(mailMessage);
}
}

View File

@ -0,0 +1,19 @@
package cn.bunny.entity.email;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.File;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmailSend {
private String sendTo;
private String subject;
private String message;
private File file;
}

View File

@ -0,0 +1,20 @@
package cn.bunny.entity.email;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 邮箱发送初始化参数
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmailSendInit {
private Integer port;
private String host;
private String username;
private String password;
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<version>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.bunny</groupId>

View File

@ -25,6 +25,11 @@
<artifactId>spring-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-mail</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- service-utils -->
<dependency>
<groupId>cn.bunny</groupId>

View File

@ -1,70 +0,0 @@
package cn.bunny.service.Bunny;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* <p>
* 菜单表
* </p>
*
* @author Bunny
* @since 2024-05-06
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("sys_menu")
@ApiModel(value = "SysMenu对象", description = "菜单表")
public class SysMenu implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("所属上级")
private Long parentId;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("类型(0:目录,1:菜单,2:按钮)")
private Byte type;
@ApiModelProperty("路由地址")
private String path;
@ApiModelProperty("组件路径")
private String component;
@ApiModelProperty("权限标识")
private String perms;
@ApiModelProperty("图标")
private String icon;
@ApiModelProperty("排序")
private Integer sortValue;
@ApiModelProperty("状态(0:禁止,1:正常)")
private Byte status;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("删除标记0:不可用 1:可用)")
private Byte isDeleted;
}

View File

@ -1,4 +1,4 @@
package cn.bunny.service.annotation;
package cn.bunny.service.aop.annotation;
import cn.bunny.enums.OperationType;

View File

@ -0,0 +1,27 @@
package cn.bunny.service.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Pointcut("execution(* cn.bunny.service.*.*(..))")
public void autoFillPointcut() {
}
/**
* 之前操作
*
* @param joinPoint 参数
*/
@Before("autoFillPointcut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行自动填充");
}
}

View File

@ -1,74 +0,0 @@
package cn.bunny.service.aspect;
import cn.bunny.common.constant.SQLAutoFillConstant;
import cn.bunny.common.service.context.BaseContext;
import cn.bunny.enums.OperationType;
import cn.bunny.service.annotation.AutoFill;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Pointcut("execution(* cn.bunny.service.*.*(..))")
public void autoFillPointcut() {
}
/**
* 之前操作
*
* @param joinPoint 参数
*/
@Before("autoFillPointcut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行自动填充");
// 获取当前被拦截数据库操作
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
OperationType operationType = autoFill.value();
// 获取实体对象
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
Object entity = args[0];
// 准备赋值数据
LocalDateTime localDateTime = LocalDateTime.now();
Long id = BaseContext.getUserId();
// 根据当前不同的操作类型为对应属性来反射赋值
if (operationType == OperationType.INSERT) {
try {
Method setCreateTime = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getMethod(SQLAutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getMethod(SQLAutoFillConstant.SET_UPDATE_USER, Long.class);
setCreateTime.invoke(entity, localDateTime);
setCreateUser.invoke(entity, id);
setUpdateTime.invoke(entity, localDateTime);
setUpdateUser.invoke(entity, id);
} catch (Exception e) {
e.printStackTrace();
}
} else if (operationType == OperationType.UPDATE) {
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_UPDATE_USER, Long.class);
setUpdateTime.invoke(entity, localDateTime);
setUpdateUser.invoke(entity, id);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,41 @@
package cn.bunny.service.controller;
import cn.bunny.common.result.Result;
import cn.bunny.entity.email.EmailSend;
import cn.bunny.service.service.EmailService;
import com.alibaba.fastjson2.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@Tag(name = "发送邮件")
@RequestMapping("/test/mail")
@Slf4j
public class MailController {
@Autowired
private EmailService emailService;
@Operation(summary = "发送简单邮件", description = "发送简单邮件")
@PostMapping("/send-text")
public Result<String> sendText(@RequestBody EmailSend emailSend) {
log.info("发送简单邮件");
emailService.sendSimpleEmail(emailSend);
return Result.success();
}
@Operation(summary = "发送带附件邮件", description = "发送带附件邮件")
@PostMapping("send-attachment")
public Result<String> sendAttachment(@RequestBody MultipartFile file, String emailSend) {
log.info("发送带附件邮件");
EmailSend send = JSON.parseObject(emailSend, EmailSend.class);
boolean isSuccess = emailService.sendAttachmentEmail(send, file);
return isSuccess ? Result.success() : Result.error();
}
}

View File

@ -1,6 +1,6 @@
package cn.bunny.service.mapper;
import cn.bunny.service.Bunny.SysMenu;
import cn.bunny.entity.system.SysMenu;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**

View File

@ -0,0 +1,38 @@
package cn.bunny.service.service;
import cn.bunny.entity.email.EmailSend;
import jakarta.mail.MessagingException;
import org.springframework.web.multipart.MultipartFile;
public interface EmailService {
/**
* 发送邮件-简单
*
* @param emailSend 邮件消息
*/
void sendSimpleEmail(EmailSend emailSend);
/**
* 发送带附件邮件
*
* @param emailSend 邮件消息
* @return 是否成功
*/
boolean sendAttachmentEmail(EmailSend emailSend, MultipartFile file);
/**
* 发送富文本邮件
*
* @param emailSend 邮件消息
*/
void sendRich(EmailSend emailSend) throws MessagingException;
/**
* 发送带抄送的邮件
*
* @param emailSend 邮件消息
* @param ccParam 抄送人
*/
void sendCC(EmailSend emailSend, String ccParam) throws MessagingException;
}

View File

@ -1,6 +1,6 @@
package cn.bunny.service.service;
import cn.bunny.service.Bunny.SysMenu;
import cn.bunny.entity.system.SysMenu;
import com.baomidou.mybatisplus.extension.service.IService;
/**

View File

@ -0,0 +1,106 @@
package cn.bunny.service.service.impl;
import cn.bunny.common.email.utils.MailSender;
import cn.bunny.entity.email.EmailSend;
import cn.bunny.entity.email.EmailSendInit;
import cn.bunny.service.service.EmailService;
import jakarta.mail.MessagingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
@Slf4j
public class EmailServiceImpl implements EmailService {
/**
* 发送邮件-简单
*
* @param emailSend 邮件消息
*/
@Override
public void sendSimpleEmail(EmailSend emailSend) {
EmailSendInit emailSendInit = new EmailSendInit();
emailSendInit.setHost("smtp.qq.com");
emailSendInit.setPort(465);
emailSendInit.setUsername("3324855376@qq.com");
emailSendInit.setPassword("axyqbvfuxkdqdaai");
MailSender mailSender = new MailSender(emailSendInit);
mailSender.sendSimpleEmail(emailSend);
}
/**
* 发送带附件邮件
*
* @param emailSend 邮件消息
* @return 是否成功
*/
@Override
public boolean sendAttachmentEmail(EmailSend emailSend, MultipartFile file) {
try {
EmailSendInit emailSendInit = new EmailSendInit();
emailSendInit.setHost("smtp.qq.com");
emailSendInit.setPort(465);
emailSendInit.setUsername("3324855376@qq.com");
emailSendInit.setPassword("axyqbvfuxkdqdaai");
MailSender mailSender = new MailSender(emailSendInit);
mailSender.sendAttachmentEmail(emailSend, file);
return true;
} catch (MessagingException e) {
return false;
}
}
/**
* 发送富文本邮件
*
* @param emailSend 邮件消息
*/
@Override
public void sendRich(EmailSend emailSend) {
// // 创建 MimeMessage 对象用于发送邮件富文本或者附件
// MimeMessage message = javaMailSender.createMimeMessage();
// // 创建 MimeMessageHelper
// MimeMessageHelper helper = new MimeMessageHelper(message, true);
//
// // 设置邮件发送者
// helper.setFrom(emailFrom);
// // 设置邮件接受者
// helper.setTo(emailSend.getSendTo());
// // 设置邮件主题
// helper.setSubject(emailSend.getSubject());
// // 设置邮件富文本后面跟true 表示HTML格式发送
// helper.setText(emailSend.getMessage(), true);
//
// // 发送邮件
// javaMailSender.send(message);
}
/**
* 发送带抄送的邮件
*
* @param emailSend 邮件消息
* @param ccParam 抄送人
*/
@Override
public void sendCC(EmailSend emailSend, String ccParam) {
// // 创建 MimeMessage 对象用于发送邮件富文本或者附件
// MimeMessage message = javaMailSender.createMimeMessage();
// // 创建 MimeMessageHelper
// MimeMessageHelper helper = new MimeMessageHelper(message, true);
//
// // 设置发送人
// helper.setFrom(emailFrom);
// // 设置邮件接受者
// helper.setTo(emailSend.getSendTo());
// // 设置邮件主题
// helper.setSubject(emailSend.getSubject());
// // 设置发送消息 为富文本
// helper.setText(emailSend.getMessage(), true);
// // 设置抄送人
// helper.setCc(ccParam.split(","));
//
// // 发送邮件
// javaMailSender.send(message);
}
}

View File

@ -1,6 +1,6 @@
package cn.bunny.service.service.impl;
import cn.bunny.service.Bunny.SysMenu;
import cn.bunny.entity.system.SysMenu;
import cn.bunny.service.mapper.SysMenuMapper;
import cn.bunny.service.service.SysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

View File

@ -35,6 +35,28 @@ spring:
name: user
password: 1
mail:
host: smtp.qq.com # 邮箱地址
port: 465 # 邮箱端口号
username: 3324855376@qq.com # 设置发送邮箱
password: axyqbvfuxkdqdaai # 如果是纯数字要加引号
default-encoding: UTF-8 # 设置编码格式
protocol: smtps
properties:
mail:
debug: true # 是否开启debug模式发送邮件
smtp:
auth: true
connectionTimeout: 5000 # 设置连接延迟
timeout: 5000 # 延迟时间
writeTimeout: 5000 # 写入邮箱延迟
allow8BitMime: true
sendPartial: true
ssl:
enabled: true # 是否开启SSL连接
socketFactory:
class: javax.net.ssl.SSLSocketFactory # 必要设置!!!
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:

View File

@ -3,20 +3,19 @@
<mapper namespace="cn.bunny.service.mapper.SysMenuMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.bunny.service.Bunny.SysMenu">
<id column="id" property="id" />
<result column="parent_id" property="parentId" />
<result column="name" property="name" />
<result column="type" property="type" />
<result column="path" property="path" />
<result column="component" property="component" />
<result column="perms" property="perms" />
<result column="icon" property="icon" />
<result column="sort_value" property="sortValue" />
<result column="status" property="status" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
<result column="is_deleted" property="isDeleted" />
<resultMap id="BaseResultMap" type="cn.bunny.entity.system.SysMenu">
<id column="id" property="id"/>
<result column="parent_id" property="parentId"/>
<result column="name" property="name"/>
<result column="type" property="type"/>
<result column="path" property="path"/>
<result column="component" property="component"/>
<result column="perms" property="perms"/>
<result column="icon" property="icon"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<!-- 通用查询结果列 -->