1111
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.biz.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 邮件账户配置表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/biz/mailAccount")
|
||||
public class MailAccountController {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.biz.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 附件表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/biz/mailAttachment")
|
||||
public class MailAttachmentController {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.biz.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接收邮件表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/biz/mailReceived")
|
||||
public class MailReceivedController {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.biz.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 发送邮件表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/biz/mailSent")
|
||||
public class MailSentController {
|
||||
|
||||
}
|
||||
125
src/main/java/com/mini/capi/biz/domain/MailAccount.java
Normal file
125
src/main/java/com/mini/capi/biz/domain/MailAccount.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package com.mini.capi.biz.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 邮件账户配置表
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("biz_mail_account")
|
||||
public class MailAccount implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 邮件服务器地址
|
||||
*/
|
||||
@TableField("host")
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* SMTP端口
|
||||
*/
|
||||
@TableField("smtp_port")
|
||||
private Integer smtpPort;
|
||||
|
||||
/**
|
||||
* IMAP端口
|
||||
*/
|
||||
@TableField("imap_port")
|
||||
private Integer imapPort;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@TableField("username")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@TableField("password")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 发件人地址
|
||||
*/
|
||||
@TableField("from_address")
|
||||
private String fromAddress;
|
||||
|
||||
/**
|
||||
* 是否启用SSL
|
||||
*/
|
||||
@TableField("ssl_enable")
|
||||
private Boolean sslEnable;
|
||||
|
||||
/**
|
||||
* 状态:0-禁用,1-启用
|
||||
*/
|
||||
@TableField("status")
|
||||
private Boolean status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField("f_tenant_id")
|
||||
private String fTenantId;
|
||||
|
||||
/**
|
||||
* 流程id
|
||||
*/
|
||||
@TableField("f_flow_id")
|
||||
private String fFlowId;
|
||||
|
||||
/**
|
||||
* 流程任务主键
|
||||
*/
|
||||
@TableField("f_flow_task_id")
|
||||
private String fFlowTaskId;
|
||||
|
||||
/**
|
||||
* 流程任务状态
|
||||
*/
|
||||
@TableField("f_flow_state")
|
||||
private Integer fFlowState;
|
||||
}
|
||||
122
src/main/java/com/mini/capi/biz/domain/MailAttachment.java
Normal file
122
src/main/java/com/mini/capi/biz/domain/MailAttachment.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.mini.capi.biz.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 附件表
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("biz_mail_attachment")
|
||||
public class MailAttachment implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 文件编号
|
||||
*/
|
||||
@TableField("file_no")
|
||||
private String fileNo;
|
||||
|
||||
/**
|
||||
* 目录
|
||||
*/
|
||||
@TableField("directory")
|
||||
private String directory;
|
||||
|
||||
/**
|
||||
* 原始文件名
|
||||
*/
|
||||
@TableField("original_file_name")
|
||||
private String originalFileName;
|
||||
|
||||
/**
|
||||
* 存储地址(目录+32位随机字符+拓展名)
|
||||
*/
|
||||
@TableField("storage_path")
|
||||
private String storagePath;
|
||||
|
||||
/**
|
||||
* 文件大小(字节)
|
||||
*/
|
||||
@TableField("file_size")
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 类型:1-收件附件,2-发件附件
|
||||
*/
|
||||
@TableField("type")
|
||||
private Boolean type;
|
||||
|
||||
/**
|
||||
* 关联的收件或发件ID
|
||||
*/
|
||||
@TableField("ref_id")
|
||||
private Long refId;
|
||||
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
@TableField("content_type")
|
||||
private String contentType;
|
||||
|
||||
/**
|
||||
* 下载次数
|
||||
*/
|
||||
@TableField("download_count")
|
||||
private Integer downloadCount;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField("f_tenant_id")
|
||||
private String fTenantId;
|
||||
|
||||
/**
|
||||
* 流程id
|
||||
*/
|
||||
@TableField("f_flow_id")
|
||||
private String fFlowId;
|
||||
|
||||
/**
|
||||
* 流程任务主键
|
||||
*/
|
||||
@TableField("f_flow_task_id")
|
||||
private String fFlowTaskId;
|
||||
|
||||
/**
|
||||
* 流程任务状态
|
||||
*/
|
||||
@TableField("f_flow_state")
|
||||
private Integer fFlowState;
|
||||
}
|
||||
146
src/main/java/com/mini/capi/biz/domain/MailReceived.java
Normal file
146
src/main/java/com/mini/capi/biz/domain/MailReceived.java
Normal file
@@ -0,0 +1,146 @@
|
||||
package com.mini.capi.biz.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接收邮件表
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("biz_mail_received")
|
||||
public class MailReceived implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 邮件服务器消息ID
|
||||
*/
|
||||
@TableField("message_id")
|
||||
private String messageId;
|
||||
|
||||
/**
|
||||
* 关联的邮件账户ID
|
||||
*/
|
||||
@TableField("account_id")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 发件人地址
|
||||
*/
|
||||
@TableField("from_address")
|
||||
private String fromAddress;
|
||||
|
||||
/**
|
||||
* 发件人名称
|
||||
*/
|
||||
@TableField("from_name")
|
||||
private String fromName;
|
||||
|
||||
/**
|
||||
* 收件人地址,多个用逗号分隔
|
||||
*/
|
||||
@TableField("to_addresses")
|
||||
private String toAddresses;
|
||||
|
||||
/**
|
||||
* 抄送地址,多个用逗号分隔
|
||||
*/
|
||||
@TableField("cc_addresses")
|
||||
private String ccAddresses;
|
||||
|
||||
/**
|
||||
* 邮件主题
|
||||
*/
|
||||
@TableField("subject")
|
||||
private String subject;
|
||||
|
||||
/**
|
||||
* 邮件内容
|
||||
*/
|
||||
@TableField("content")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@TableField("send_time")
|
||||
private LocalDateTime sendTime;
|
||||
|
||||
/**
|
||||
* 接收时间
|
||||
*/
|
||||
@TableField("receive_time")
|
||||
private LocalDateTime receiveTime;
|
||||
|
||||
/**
|
||||
* 是否已读:0-未读,1-已读
|
||||
*/
|
||||
@TableField("is_read")
|
||||
private Boolean isRead;
|
||||
|
||||
/**
|
||||
* 是否有附件:0-无,1-有
|
||||
*/
|
||||
@TableField("has_attachment")
|
||||
private Boolean hasAttachment;
|
||||
|
||||
/**
|
||||
* 邮件文件夹
|
||||
*/
|
||||
@TableField("folder")
|
||||
private String folder;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField("f_tenant_id")
|
||||
private String fTenantId;
|
||||
|
||||
/**
|
||||
* 流程id
|
||||
*/
|
||||
@TableField("f_flow_id")
|
||||
private String fFlowId;
|
||||
|
||||
/**
|
||||
* 流程任务主键
|
||||
*/
|
||||
@TableField("f_flow_task_id")
|
||||
private String fFlowTaskId;
|
||||
|
||||
/**
|
||||
* 流程任务状态
|
||||
*/
|
||||
@TableField("f_flow_state")
|
||||
private Integer fFlowState;
|
||||
}
|
||||
134
src/main/java/com/mini/capi/biz/domain/MailSent.java
Normal file
134
src/main/java/com/mini/capi/biz/domain/MailSent.java
Normal file
@@ -0,0 +1,134 @@
|
||||
package com.mini.capi.biz.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 发送邮件表
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("biz_mail_sent")
|
||||
public class MailSent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 邮件服务器消息ID
|
||||
*/
|
||||
@TableField("message_id")
|
||||
private String messageId;
|
||||
|
||||
/**
|
||||
* 关联的邮件账户ID
|
||||
*/
|
||||
@TableField("account_id")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 发件人地址
|
||||
*/
|
||||
@TableField("from_address")
|
||||
private String fromAddress;
|
||||
|
||||
/**
|
||||
* 收件人地址,多个用逗号分隔
|
||||
*/
|
||||
@TableField("to_addresses")
|
||||
private String toAddresses;
|
||||
|
||||
/**
|
||||
* 抄送地址,多个用逗号分隔
|
||||
*/
|
||||
@TableField("cc_addresses")
|
||||
private String ccAddresses;
|
||||
|
||||
/**
|
||||
* 邮件主题
|
||||
*/
|
||||
@TableField("subject")
|
||||
private String subject;
|
||||
|
||||
/**
|
||||
* 邮件内容
|
||||
*/
|
||||
@TableField("content")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@TableField("send_time")
|
||||
private LocalDateTime sendTime;
|
||||
|
||||
/**
|
||||
* 发送状态:0-待发送,1-发送成功,2-发送失败
|
||||
*/
|
||||
@TableField("send_status")
|
||||
private Boolean sendStatus;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
@TableField("error_msg")
|
||||
private String errorMsg;
|
||||
|
||||
/**
|
||||
* 是否有附件:0-无,1-有
|
||||
*/
|
||||
@TableField("has_attachment")
|
||||
private Boolean hasAttachment;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField("f_tenant_id")
|
||||
private String fTenantId;
|
||||
|
||||
/**
|
||||
* 流程id
|
||||
*/
|
||||
@TableField("f_flow_id")
|
||||
private String fFlowId;
|
||||
|
||||
/**
|
||||
* 流程任务主键
|
||||
*/
|
||||
@TableField("f_flow_task_id")
|
||||
private String fFlowTaskId;
|
||||
|
||||
/**
|
||||
* 流程任务状态
|
||||
*/
|
||||
@TableField("f_flow_state")
|
||||
private Integer fFlowState;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.mapper;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAccount;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 邮件账户配置表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailAccountMapper extends BaseMapper<MailAccount> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.mapper;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAttachment;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 附件表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailAttachmentMapper extends BaseMapper<MailAttachment> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.mapper;
|
||||
|
||||
import com.mini.capi.biz.domain.MailReceived;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接收邮件表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailReceivedMapper extends BaseMapper<MailReceived> {
|
||||
|
||||
}
|
||||
16
src/main/java/com/mini/capi/biz/mapper/MailSentMapper.java
Normal file
16
src/main/java/com/mini/capi/biz/mapper/MailSentMapper.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.mapper;
|
||||
|
||||
import com.mini.capi.biz.domain.MailSent;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 发送邮件表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailSentMapper extends BaseMapper<MailSent> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.service;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAccount;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 邮件账户配置表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailAccountService extends IService<MailAccount> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.service;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAttachment;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 附件表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailAttachmentService extends IService<MailAttachment> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.service;
|
||||
|
||||
import com.mini.capi.biz.domain.MailReceived;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接收邮件表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailReceivedService extends IService<MailReceived> {
|
||||
|
||||
}
|
||||
16
src/main/java/com/mini/capi/biz/service/MailSentService.java
Normal file
16
src/main/java/com/mini/capi/biz/service/MailSentService.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.service;
|
||||
|
||||
import com.mini.capi.biz.domain.MailSent;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 发送邮件表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
public interface MailSentService extends IService<MailSent> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mini.capi.biz.service.impl;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAccount;
|
||||
import com.mini.capi.biz.mapper.MailAccountMapper;
|
||||
import com.mini.capi.biz.service.MailAccountService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 邮件账户配置表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Service
|
||||
public class MailAccountServiceImpl extends ServiceImpl<MailAccountMapper, MailAccount> implements MailAccountService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mini.capi.biz.service.impl;
|
||||
|
||||
import com.mini.capi.biz.domain.MailAttachment;
|
||||
import com.mini.capi.biz.mapper.MailAttachmentMapper;
|
||||
import com.mini.capi.biz.service.MailAttachmentService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 附件表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Service
|
||||
public class MailAttachmentServiceImpl extends ServiceImpl<MailAttachmentMapper, MailAttachment> implements MailAttachmentService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mini.capi.biz.service.impl;
|
||||
|
||||
import com.mini.capi.biz.domain.MailReceived;
|
||||
import com.mini.capi.biz.mapper.MailReceivedMapper;
|
||||
import com.mini.capi.biz.service.MailReceivedService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接收邮件表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Service
|
||||
public class MailReceivedServiceImpl extends ServiceImpl<MailReceivedMapper, MailReceived> implements MailReceivedService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mini.capi.biz.service.impl;
|
||||
|
||||
import com.mini.capi.biz.domain.MailSent;
|
||||
import com.mini.capi.biz.mapper.MailSentMapper;
|
||||
import com.mini.capi.biz.service.MailSentService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 发送邮件表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-09-22
|
||||
*/
|
||||
@Service
|
||||
public class MailSentServiceImpl extends ServiceImpl<MailSentMapper, MailSent> implements MailSentService {
|
||||
|
||||
}
|
||||
57
src/main/java/com/mini/capi/mail/config/MailConfig.java
Normal file
57
src/main/java/com/mini/capi/mail/config/MailConfig.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.mini.capi.mail.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
public class MailConfig {
|
||||
|
||||
@Bean
|
||||
public JavaMailSenderImpl javaMailSender() {
|
||||
return new JavaMailSenderImpl();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置SMTP属性
|
||||
*/
|
||||
public Properties getSmtpProperties(String host, int port, boolean ssl, boolean auth) {
|
||||
Properties props = new Properties();
|
||||
props.put("mail.smtp.host", host);
|
||||
props.put("mail.smtp.port", port);
|
||||
props.put("mail.smtp.auth", auth);
|
||||
|
||||
if (ssl) {
|
||||
props.put("mail.smtp.ssl.enable", "true");
|
||||
} else {
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
}
|
||||
|
||||
props.put("mail.smtp.connectiontimeout", 5000);
|
||||
props.put("mail.smtp.timeout", 5000);
|
||||
props.put("mail.smtp.writetimeout", 5000);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置IMAP属性
|
||||
*/
|
||||
public Properties getImapProperties(String host, int port, boolean ssl) {
|
||||
Properties props = new Properties();
|
||||
props.put("mail.imap.host", host);
|
||||
props.put("mail.imap.port", port);
|
||||
|
||||
if (ssl) {
|
||||
props.put("mail.imap.ssl.enable", "true");
|
||||
}
|
||||
|
||||
props.put("mail.imap.connectiontimeout", 5000);
|
||||
props.put("mail.imap.timeout", 5000);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.mini.capi.mail.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
/**
|
||||
* 附件处理线程池
|
||||
*/
|
||||
@Bean(name = "attachmentExecutor")
|
||||
public Executor attachmentExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
// 核心线程数
|
||||
executor.setCorePoolSize(5);
|
||||
// 最大线程数
|
||||
executor.setMaxPoolSize(10);
|
||||
// 队列容量
|
||||
executor.setQueueCapacity(50);
|
||||
// 线程名称前缀
|
||||
executor.setThreadNamePrefix("attachment-");
|
||||
// 拒绝策略:由调用线程处理
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 初始化
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
102
src/main/java/com/mini/capi/mail/controller/MailController.java
Normal file
102
src/main/java/com/mini/capi/mail/controller/MailController.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.mini.capi.mail.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/mail")
|
||||
public class MailController {
|
||||
|
||||
@Autowired
|
||||
private MailReceiveService mailReceiveService;
|
||||
|
||||
@Autowired
|
||||
private MailSendService mailSendService;
|
||||
|
||||
@Autowired
|
||||
private MailAccountMapper mailAccountMapper;
|
||||
|
||||
@Autowired
|
||||
private MailReceivedMapper mailReceivedMapper;
|
||||
|
||||
@Autowired
|
||||
private MailSentMapper mailSentMapper;
|
||||
|
||||
/**
|
||||
* 接收邮件
|
||||
*/
|
||||
@PostMapping("/receive/{accountId}")
|
||||
public ResponseVO<Integer> receiveEmails(@PathVariable Long accountId) {
|
||||
try {
|
||||
int count = mailReceiveService.syncNewEmails(accountId);
|
||||
return ResponseVO.success(count, "接收邮件成功");
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.error("接收邮件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
*/
|
||||
@PostMapping("/send/{accountId}")
|
||||
public ResponseVO<Long> sendEmail(
|
||||
@PathVariable Long accountId,
|
||||
@ModelAttribute MailSendVO mailSendVO) {
|
||||
try {
|
||||
MailAccount account = mailAccountMapper.selectById(accountId);
|
||||
if (account == null) {
|
||||
return ResponseVO.error("未找到邮件账户");
|
||||
}
|
||||
|
||||
Long mailId = mailSendService.sendEmail(account, mailSendVO);
|
||||
return ResponseVO.success(mailId, "发送邮件成功");
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.error("发送邮件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收件箱邮件
|
||||
*/
|
||||
@GetMapping("/received/{accountId}")
|
||||
public ResponseVO<List<MailReceived>> getReceivedEmails(
|
||||
@PathVariable Long accountId,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
try {
|
||||
QueryWrapper<MailReceived> query = new QueryWrapper<>();
|
||||
query.eq("account_id", accountId)
|
||||
.orderByDesc("received_date")
|
||||
.last("LIMIT " + page * size + "," + size);
|
||||
|
||||
List<MailReceived> emails = mailReceivedMapper.selectList(query);
|
||||
return ResponseVO.success(emails);
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.error("获取收件箱邮件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已发送邮件
|
||||
*/
|
||||
@GetMapping("/sent/{accountId}")
|
||||
public ResponseVO<List<MailSent>> getSentEmails(
|
||||
@PathVariable Long accountId,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
try {
|
||||
QueryWrapper<MailSent> query = new QueryWrapper<>();
|
||||
query.eq("account_id", accountId)
|
||||
.orderByDesc("send_date")
|
||||
.last("LIMIT " + page * size + "," + size);
|
||||
|
||||
List<MailSent> emails = mailSentMapper.selectList(query);
|
||||
return ResponseVO.success(emails);
|
||||
} catch (Exception e) {
|
||||
return ResponseVO.error("获取已发送邮件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
src/main/java/com/mini/capi/mail/dc.java
Normal file
4
src/main/java/com/mini/capi/mail/dc.java
Normal file
@@ -0,0 +1,4 @@
|
||||
package com.mini.capi.mail;
|
||||
|
||||
public class dc {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.mail.service;
|
||||
|
||||
public interface MailReceiveService {
|
||||
|
||||
/**
|
||||
* 接收邮件
|
||||
* @param account 邮件账户
|
||||
* @return 接收成功的邮件数量
|
||||
*/
|
||||
int receiveEmails(MailAccount account);
|
||||
|
||||
/**
|
||||
* 同步接收最新的未读邮件
|
||||
* @param accountId 邮件账户ID
|
||||
* @return 接收成功的邮件数量
|
||||
*/
|
||||
int syncNewEmails(Long accountId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mini.capi.mail.service;
|
||||
|
||||
public interface MailSendService {
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @param account 邮件账户
|
||||
* @param mailSendVO 邮件发送参数
|
||||
* @return 发送成功的邮件ID
|
||||
*/
|
||||
Long sendEmail(MailAccount account, MailSendVO mailSendVO);
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package com.mini.capi.mail.service.impl;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Service
|
||||
public class MailReceiveServiceImpl implements MailReceiveService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailReceiveServiceImpl.class);
|
||||
|
||||
// 邮件存储目录
|
||||
private static final String MAIL_FILES_DIR = "/ogsapp/mailfiles";
|
||||
|
||||
@Autowired
|
||||
private MailAccountMapper mailAccountMapper;
|
||||
|
||||
@Autowired
|
||||
private MailReceivedMapper mailReceivedMapper;
|
||||
|
||||
@Autowired
|
||||
private MailAttachmentMapper mailAttachmentMapper;
|
||||
|
||||
@Autowired
|
||||
private MailConfig mailConfig;
|
||||
|
||||
@Autowired
|
||||
private Executor attachmentExecutor;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int receiveEmails(MailAccount account) {
|
||||
if (account == null) {
|
||||
logger.error("邮件账户不能为空");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Store store = null;
|
||||
Folder inbox = null;
|
||||
int receivedCount = 0;
|
||||
|
||||
try {
|
||||
// 初始化IMAP连接
|
||||
Properties props = mailConfig.getImapProperties(
|
||||
account.getImapHost(),
|
||||
account.getImapPort(),
|
||||
account.isImapSsl()
|
||||
);
|
||||
|
||||
Session session = Session.getInstance(props);
|
||||
store = session.getStore("imap");
|
||||
store.connect(
|
||||
account.getImapHost(),
|
||||
account.getUsername(),
|
||||
account.getPassword()
|
||||
);
|
||||
|
||||
// 打开收件箱,只获取未读邮件
|
||||
inbox = store.getFolder("INBOX");
|
||||
inbox.open(Folder.READ_WRITE);
|
||||
|
||||
// 搜索未读邮件
|
||||
Message[] messages = inbox.search(
|
||||
new FlagTerm(new Flags(Flags.Flag.SEEN), false)
|
||||
);
|
||||
|
||||
logger.info("找到 {} 封未读邮件", messages.length);
|
||||
|
||||
// 处理每封邮件
|
||||
for (Message message : messages) {
|
||||
if (message instanceof MimeMessage) {
|
||||
// 保存邮件基本信息
|
||||
MailReceived mailReceived = saveMailInfo((MimeMessage) message, account);
|
||||
if (mailReceived != null) {
|
||||
receivedCount++;
|
||||
|
||||
// 异步处理附件
|
||||
attachmentExecutor.execute(() -> {
|
||||
try {
|
||||
handleAttachments((MimeMessage) message, mailReceived.getId());
|
||||
// 标记为已读
|
||||
message.setFlag(Flags.Flag.SEEN, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("处理邮件附件失败", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("接收邮件失败", e);
|
||||
} finally {
|
||||
try {
|
||||
if (inbox != null && inbox.isOpen()) {
|
||||
inbox.close(false);
|
||||
}
|
||||
if (store != null && store.isConnected()) {
|
||||
store.close();
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
logger.error("关闭邮件连接失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
return receivedCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int syncNewEmails(Long accountId) {
|
||||
if (accountId == null) {
|
||||
logger.error("账户ID不能为空");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MailAccount account = mailAccountMapper.selectById(accountId);
|
||||
if (account == null) {
|
||||
logger.error("未找到ID为 {} 的邮件账户", accountId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return receiveEmails(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存邮件基本信息到数据库
|
||||
*/
|
||||
private MailReceived saveMailInfo(MimeMessage message, MailAccount account) throws MessagingException {
|
||||
try {
|
||||
MailReceived mailReceived = new MailReceived();
|
||||
|
||||
// 设置邮件基本信息
|
||||
mailReceived.setAccountId(account.getId());
|
||||
mailReceived.setSubject(message.getSubject());
|
||||
mailReceived.setSentDate(message.getSentDate());
|
||||
mailReceived.setReceivedDate(new Date());
|
||||
|
||||
// 设置发件人
|
||||
Address[] fromAddresses = message.getFrom();
|
||||
if (fromAddresses != null && fromAddresses.length > 0) {
|
||||
mailReceived.setFromAddress(((InternetAddress) fromAddresses[0]).getAddress());
|
||||
}
|
||||
|
||||
// 设置收件人
|
||||
Address[] toAddresses = message.getRecipients(Message.RecipientType.TO);
|
||||
if (toAddresses != null && toAddresses.length > 0) {
|
||||
List<String> toList = new ArrayList<>();
|
||||
for (Address addr : toAddresses) {
|
||||
toList.add(((InternetAddress) addr).getAddress());
|
||||
}
|
||||
mailReceived.setToAddresses(String.join(",", toList));
|
||||
}
|
||||
|
||||
// 设置抄送人
|
||||
Address[] ccAddresses = message.getRecipients(Message.RecipientType.CC);
|
||||
if (ccAddresses != null && ccAddresses.length > 0) {
|
||||
List<String> ccList = new ArrayList<>();
|
||||
for (Address addr : ccAddresses) {
|
||||
ccList.add(((InternetAddress) addr).getAddress());
|
||||
}
|
||||
mailReceived.setCcAddresses(String.join(",", ccList));
|
||||
}
|
||||
|
||||
// 获取邮件内容
|
||||
String content = MailUtil.getEmailContent(message);
|
||||
mailReceived.setContent(content);
|
||||
|
||||
// 保存到数据库
|
||||
mailReceivedMapper.insert(mailReceived);
|
||||
return mailReceived;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("保存邮件信息失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理并保存邮件附件
|
||||
*/
|
||||
@Async("attachmentExecutor")
|
||||
@Transactional
|
||||
public void handleAttachments(MimeMessage message, Long mailReceivedId) throws MessagingException {
|
||||
try {
|
||||
Object content = message.getContent();
|
||||
|
||||
if (content instanceof MimeMultipart) {
|
||||
MimeMultipart multipart = (MimeMultipart) content;
|
||||
|
||||
// 遍历所有部分寻找附件
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
|
||||
// 判断是否为附件
|
||||
if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) ||
|
||||
bodyPart.getFileName() != null) {
|
||||
|
||||
// 处理附件
|
||||
String originalFileName = bodyPart.getFileName();
|
||||
if (originalFileName != null) {
|
||||
// 生成存储文件名(32位随机字符+扩展名)
|
||||
String fileExt = originalFileName.contains(".") ?
|
||||
originalFileName.substring(originalFileName.lastIndexOf(".")) : "";
|
||||
String storedFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileExt;
|
||||
|
||||
// 确保存储目录存在
|
||||
File dir = new File(MAIL_FILES_DIR);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 保存附件
|
||||
String filePath = MAIL_FILES_DIR + File.separator + storedFileName;
|
||||
FileUtil.saveFile(bodyPart.getInputStream(), filePath);
|
||||
|
||||
// 获取文件大小
|
||||
File savedFile = new File(filePath);
|
||||
long fileSize = savedFile.length();
|
||||
|
||||
// 保存附件信息到数据库
|
||||
MailAttachment attachment = new MailAttachment();
|
||||
attachment.setFileNo(UUID.randomUUID().toString());
|
||||
attachment.setDirectory(MAIL_FILES_DIR);
|
||||
attachment.setFileName(originalFileName);
|
||||
attachment.setStoredPath(filePath);
|
||||
attachment.setFileSize(fileSize);
|
||||
attachment.setType(1); // 1表示收件
|
||||
attachment.setRelatedId(mailReceivedId);
|
||||
attachment.setCreateTime(new Date());
|
||||
|
||||
mailAttachmentMapper.insert(attachment);
|
||||
|
||||
logger.info("保存附件成功: {} -> {}", originalFileName, storedFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理邮件附件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package com.mini.capi.mail.service.impl;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Service
|
||||
public class MailSendServiceImpl implements MailSendService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailSendServiceImpl.class);
|
||||
|
||||
// 邮件存储目录
|
||||
private static final String MAIL_FILES_DIR = "/ogsapp/mailfiles";
|
||||
|
||||
@Autowired
|
||||
private JavaMailSenderImpl mailSender;
|
||||
|
||||
@Autowired
|
||||
private MailConfig mailConfig;
|
||||
|
||||
@Autowired
|
||||
private MailSentMapper mailSentMapper;
|
||||
|
||||
@Autowired
|
||||
private MailAttachmentMapper mailAttachmentMapper;
|
||||
|
||||
@Autowired
|
||||
private Executor attachmentExecutor;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long sendEmail(MailAccount account, MailSendVO mailSendVO) {
|
||||
if (account == null || mailSendVO == null) {
|
||||
logger.error("邮件账户或发送参数不能为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mailSendVO.getTo() == null || mailSendVO.getTo().isEmpty()) {
|
||||
logger.error("收件人不能为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 配置邮件发送器
|
||||
mailSender.setHost(account.getSmtpHost());
|
||||
mailSender.setPort(account.getSmtpPort());
|
||||
mailSender.setUsername(account.getUsername());
|
||||
mailSender.setPassword(account.getPassword());
|
||||
mailSender.setJavaMailProperties(mailConfig.getSmtpProperties(
|
||||
account.getSmtpHost(),
|
||||
account.getSmtpPort(),
|
||||
account.isSmtpSsl(),
|
||||
true
|
||||
));
|
||||
|
||||
// 创建邮件消息
|
||||
MimeMessage message = mailSender.createMimeMessage();
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
|
||||
|
||||
// 设置发件人
|
||||
helper.setFrom(account.getUsername());
|
||||
|
||||
// 设置收件人
|
||||
helper.setTo(mailSendVO.getTo().toArray(new String[0]));
|
||||
|
||||
// 设置抄送
|
||||
if (!CollectionUtils.isEmpty(mailSendVO.getCc())) {
|
||||
helper.setCc(mailSendVO.getCc().toArray(new String[0]));
|
||||
}
|
||||
|
||||
// 设置邮件主题和内容
|
||||
helper.setSubject(mailSendVO.getSubject());
|
||||
helper.setText(mailSendVO.getContent(), mailSendVO.isHtml());
|
||||
|
||||
// 设置发送时间
|
||||
Date sendDate = new Date();
|
||||
helper.setSentDate(sendDate);
|
||||
|
||||
// 处理附件
|
||||
List<MailAttachment> attachments = new ArrayList<>();
|
||||
if (mailSendVO.getAttachments() != null && !mailSendVO.getAttachments().isEmpty()) {
|
||||
for (MultipartFile file : mailSendVO.getAttachments()) {
|
||||
if (!file.isEmpty()) {
|
||||
// 保存附件到服务器
|
||||
String originalFileName = file.getOriginalFilename();
|
||||
String fileExt = originalFileName.contains(".") ?
|
||||
originalFileName.substring(originalFileName.lastIndexOf(".")) : "";
|
||||
String storedFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileExt;
|
||||
|
||||
// 确保存储目录存在
|
||||
File dir = new File(MAIL_FILES_DIR);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 保存文件
|
||||
String filePath = MAIL_FILES_DIR + File.separator + storedFileName;
|
||||
file.transferTo(new File(filePath));
|
||||
|
||||
// 添加到邮件
|
||||
helper.addAttachment(originalFileName, new File(filePath));
|
||||
|
||||
// 记录附件信息
|
||||
MailAttachment attachment = new MailAttachment();
|
||||
attachment.setFileNo(UUID.randomUUID().toString());
|
||||
attachment.setDirectory(MAIL_FILES_DIR);
|
||||
attachment.setFileName(originalFileName);
|
||||
attachment.setStoredPath(filePath);
|
||||
attachment.setFileSize(file.getSize());
|
||||
attachment.setType(2); // 2表示发件
|
||||
attachment.setCreateTime(new Date());
|
||||
|
||||
attachments.add(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 发送邮件
|
||||
mailSender.send(message);
|
||||
logger.info("邮件发送成功,主题: {}", mailSendVO.getSubject());
|
||||
|
||||
// 保存发送记录
|
||||
MailSent mailSent = new MailSent();
|
||||
mailSent.setAccountId(account.getId());
|
||||
mailSent.setSubject(mailSendVO.getSubject());
|
||||
mailSent.setContent(mailSendVO.getContent());
|
||||
mailSent.setFromAddress(account.getUsername());
|
||||
mailSent.setToAddresses(String.join(",", mailSendVO.getTo()));
|
||||
|
||||
if (!CollectionUtils.isEmpty(mailSendVO.getCc())) {
|
||||
mailSent.setCcAddresses(String.join(",", mailSendVO.getCc()));
|
||||
}
|
||||
|
||||
mailSent.setSendDate(sendDate);
|
||||
mailSent.setIsHtml(mailSendVO.isHtml() ? 1 : 0);
|
||||
|
||||
mailSentMapper.insert(mailSent);
|
||||
|
||||
// 保存附件关联信息
|
||||
for (MailAttachment attachment : attachments) {
|
||||
attachment.setRelatedId(mailSent.getId());
|
||||
mailAttachmentMapper.insert(attachment);
|
||||
}
|
||||
|
||||
return mailSent.getId();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("发送邮件失败", e);
|
||||
throw new RuntimeException("发送邮件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/mini/capi/mail/vo/MailSendVO.java
Normal file
22
src/main/java/com/mini/capi/mail/vo/MailSendVO.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.mini.capi.mail.vo;
|
||||
|
||||
public class MailSendVO {
|
||||
|
||||
// 收件人列表
|
||||
private List<String> to;
|
||||
|
||||
// 抄送列表
|
||||
private List<String> cc;
|
||||
|
||||
// 邮件主题
|
||||
private String subject;
|
||||
|
||||
// 邮件内容
|
||||
private String content;
|
||||
|
||||
// 是否为HTML内容
|
||||
private boolean isHtml = false;
|
||||
|
||||
// 附件列表
|
||||
private List<MultipartFile> attachments;
|
||||
}
|
||||
38
src/main/java/com/mini/capi/mail/vo/ResponseVO.java
Normal file
38
src/main/java/com/mini/capi/mail/vo/ResponseVO.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.mini.capi.mail.vo;
|
||||
|
||||
|
||||
public class ResponseVO<T> {
|
||||
|
||||
// 状态码:0表示成功,其他表示失败
|
||||
private int code;
|
||||
|
||||
// 消息
|
||||
private String message;
|
||||
|
||||
// 数据
|
||||
private T data;
|
||||
|
||||
// 成功响应
|
||||
public static <T> ResponseVO<T> success(T data, String message) {
|
||||
ResponseVO<T> response = new ResponseVO<>();
|
||||
response.code = 0;
|
||||
response.message = message;
|
||||
response.data = data;
|
||||
return response;
|
||||
}
|
||||
|
||||
// 成功响应(默认消息)
|
||||
public static <T> ResponseVO<T> success(T data) {
|
||||
return success(data, "操作成功");
|
||||
}
|
||||
|
||||
// 错误响应
|
||||
public static <T> ResponseVO<T> error(String message) {
|
||||
ResponseVO<T> response = new ResponseVO<>();
|
||||
response.code = 1;
|
||||
response.message = message;
|
||||
response.data = null;
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class demo {
|
||||
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
|
||||
})
|
||||
.strategyConfig(builder -> {
|
||||
builder.addInclude("biz_ssh_servers")
|
||||
builder.addInclude("biz_mail_account,biz_mail_received,biz_mail_sent,biz_mail_attachment")
|
||||
.addTablePrefix("biz_")
|
||||
.entityBuilder()
|
||||
.enableLombok()
|
||||
|
||||
17
src/main/java/com/mini/capi/sys/domain/SendMailDTO.java
Normal file
17
src/main/java/com/mini/capi/sys/domain/SendMailDTO.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.mini.capi.sys.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SendMailDTO implements Serializable {
|
||||
private Long accountId; // 邮件账户ID
|
||||
private List<String> toAddresses; // 收件人地址列表
|
||||
private List<String> ccAddresses; // 抄送地址列表
|
||||
private String subject; // 邮件主题
|
||||
private String content; // 邮件内容
|
||||
private List<MultipartFile> attachments; // 附件列表
|
||||
}
|
||||
29
src/main/java/com/mini/capi/utils/DateUtils.java
Normal file
29
src/main/java/com/mini/capi/utils/DateUtils.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.mini.capi.utils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class DateUtils {
|
||||
|
||||
/**
|
||||
* 格式化当前日期
|
||||
* @param pattern 格式模式
|
||||
* @return 格式化后的日期字符串
|
||||
*/
|
||||
public static String formatCurrentDate(String pattern) {
|
||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化指定日期
|
||||
* @param date 日期
|
||||
* @param pattern 格式模式
|
||||
* @return 格式化后的日期字符串
|
||||
*/
|
||||
public static String formatDate(LocalDateTime date, String pattern) {
|
||||
if (date == null) {
|
||||
return "";
|
||||
}
|
||||
return date.format(DateTimeFormatter.ofPattern(pattern));
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/mini/capi/utils/FileUtils.java
Normal file
61
src/main/java/com/mini/capi/utils/FileUtils.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.mini.capi.utils;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
public class FileUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
|
||||
|
||||
/**
|
||||
* 保存输入流到文件
|
||||
*/
|
||||
public static void saveFile(InputStream inputStream, String filePath) {
|
||||
try (OutputStream outputStream = new FileOutputStream(filePath)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
logger.info("文件保存成功: {}", filePath);
|
||||
} catch (Exception e) {
|
||||
logger.error("保存文件失败: " + filePath, e);
|
||||
throw new RuntimeException("保存文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文件
|
||||
*/
|
||||
public static void copyFile(File source, File dest) {
|
||||
try {
|
||||
Files.copy(source.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
logger.error("复制文件失败: {} -> {}", source.getPath(), dest.getPath(), e);
|
||||
throw new RuntimeException("复制文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*/
|
||||
public static boolean deleteFile(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (file.exists() && file.isFile()) {
|
||||
boolean deleted = file.delete();
|
||||
if (deleted) {
|
||||
logger.info("文件删除成功: {}", filePath);
|
||||
} else {
|
||||
logger.warn("文件删除失败: {}", filePath);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
88
src/main/java/com/mini/capi/utils/MailUtil.java
Normal file
88
src/main/java/com/mini/capi/utils/MailUtil.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package com.mini.capi.utils;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.mail.BodyPart;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.IOException;
|
||||
|
||||
public class MailUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailUtil.class);
|
||||
|
||||
/**
|
||||
* 获取邮件内容
|
||||
*/
|
||||
public static String getEmailContent(Message message) {
|
||||
try {
|
||||
Object content = message.getContent();
|
||||
|
||||
// 简单文本内容
|
||||
if (content instanceof String) {
|
||||
return (String) content;
|
||||
}
|
||||
// 复杂内容(多部分)
|
||||
else if (content instanceof Multipart) {
|
||||
Multipart multipart = (Multipart) content;
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
|
||||
// 遍历所有部分
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
|
||||
// 忽略附件
|
||||
if (BodyPart.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) ||
|
||||
bodyPart.getFileName() != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取内容
|
||||
Object partContent = bodyPart.getContent();
|
||||
if (partContent instanceof String) {
|
||||
contentBuilder.append(partContent);
|
||||
} else if (partContent instanceof Multipart) {
|
||||
// 处理嵌套的多部分内容
|
||||
contentBuilder.append(getMultipartContent((Multipart) partContent));
|
||||
}
|
||||
}
|
||||
|
||||
return contentBuilder.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("获取邮件内容失败", e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理嵌套的多部分内容
|
||||
*/
|
||||
private static String getMultipartContent(Multipart multipart) throws MessagingException, IOException {
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < multipart.getCount(); i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
|
||||
// 忽略附件
|
||||
if (BodyPart.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) ||
|
||||
bodyPart.getFileName() != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object partContent = bodyPart.getContent();
|
||||
if (partContent instanceof String) {
|
||||
contentBuilder.append(partContent);
|
||||
} else if (partContent instanceof Multipart) {
|
||||
contentBuilder.append(getMultipartContent((Multipart) partContent));
|
||||
}
|
||||
}
|
||||
|
||||
return contentBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user