1.前言
客户现场由于网络问题,可能发送邮件功能收到限制,目前想到的折中办法就是去http调用不受网络限制服务器的接口,从而达到发送邮件的功能。
2.邮件服务端开发
这个服务使用springboot框架,主要提供两个接口,发送邮件和上传附件。
(1)DTO
package cn.com.email.entity.dto;
import java.util.List;
public class EmailDTO {
/*
待发送邮件列表
*/
private List<String> emailArr;
/*
待发送邮件主题
*/
private String subject;
/*
待发送邮件内容
*/
private String content;
/*
邮件host
*/
private String emailHost;
/*
邮件用户名
*/
private String emailUsername;
/*
邮件密码
*/
private String emailPassword;
private List<String> fileNames;
public List<String> getEmailArr() {
return emailArr;
}
public void setEmailArr(List<String> emailArr) {
this.emailArr = emailArr;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getEmailHost() {
return emailHost;
}
public void setEmailHost(String emailHost) {
this.emailHost = emailHost;
}
public String getEmailUsername() {
return emailUsername;
}
public void setEmailUsername(String emailUsername) {
this.emailUsername = emailUsername;
}
public String getEmailPassword() {
return emailPassword;
}
public void setEmailPassword(String emailPassword) {
this.emailPassword = emailPassword;
}
public List<String> getFileNames() {
return fileNames;
}
public void setFileNames(List<String> fileNames) {
this.fileNames = fileNames;
}
@Override
public String toString() {
return "EmailDTO{" +
"emailArr=" + emailArr +
", subject='" + subject + '\'' +
", content='" + content + '\'' +
", emailHost='" + emailHost + '\'' +
", emailUsername='" + emailUsername + '\'' +
", emailPassword='" + emailPassword + '\'' +
", fileNames=" + fileNames +
'}';
}
}
(2)controller
package cn.com.email.controller;
import cn.com.email.entity.dto.EmailDTO;
import cn.com.email.service.EmailService;
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
@RequestMapping("/email")
public class EmailController {
@Autowired
private EmailService emailService;
/**
* 发送邮件
* @param emailDTO
* @return
*/
@PostMapping(value = "/send")
public String send(@RequestBody EmailDTO emailDTO) {
return emailService.senZgh(emailDTO);
}
/**
* 上传附件
* @param file
* @return
*/
@PostMapping(value = "upload")
public String upload(MultipartFile file){
return emailService.upload(file);
}
}
(3)serviceImpl层,service接口层省略
package cn.com.email.service.impl;
import cn.com.email.entity.dto.EmailDTO;
import cn.com.email.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@Service
public class EmailServiceImpl implements EmailService {
private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);
@Value("${email-upload-path}")
private String uploadPath;
@Override
public String send(EmailDTO emailDTO) {
logger.info("参数对象:{}",emailDTO);
if (null == emailDTO) {
return "FAILED";
}
List<String> newFilePaths = new ArrayList<>();
try {
List<String> fileNames = emailDTO.getFileNames();
String title = emailDTO.getSubject();
String content = emailDTO.getContent();
List<String> toAddrs = emailDTO.getEmailArr();
Properties props = new Properties();
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", emailDTO.getEmailHost());
String sendUser = emailDTO.getEmailUsername();
String password = emailDTO.getEmailPassword();
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
//第三方客户端授权密码和登录密码不一样
final String fromAddr_prefixx = sendUser.split("@")[0];
return new PasswordAuthentication(fromAddr_prefixx, password);
}
});
session.setDebug(false);
Message msg = new MimeMessage(session);
Multipart msgPart = new MimeMultipart("mixed");
msg.setContent(msgPart);
MimeBodyPart body = new MimeBodyPart(); //表示正文
msgPart.addBodyPart(body);
msg.setFrom(new InternetAddress("中广核新能源共享数据库" + "<" + sendUser + ">"));
msg.setSubject(title);
body.setContent(content, "text/html;charset=utf-8");
if (toAddrs != null && toAddrs.size() == 1) {
msg.setRecipient(Message.RecipientType.TO, new InternetAddress((String) toAddrs.toArray()[0]));
} else if (toAddrs != null && toAddrs.size() > 1) {
InternetAddress[] tos = new InternetAddress[toAddrs.size()];
if (toAddrs != null) {
for (int i = 0; i < toAddrs.size(); i++) {
tos[i] = new InternetAddress(toAddrs.get(i));
}
}
msg.setRecipients(Message.RecipientType.TO, tos);
} else {
throw new IllegalArgumentException("目标邮件地址不可为空");
}
if (null != fileNames && fileNames.size()>0) {
for (String fileName : fileNames) {
if(null != fileName && fileName.length()>0){
MimeBodyPart attach = new MimeBodyPart(); //表示附件
msgPart.addBodyPart(attach);
String newFileName = uploadPath + File.separator + fileName;
newFilePaths.add(newFileName);
attach.setDataHandler(new DataHandler(new FileDataSource(newFileName)));
// MimeUtility.encodeText();解决中文文件名乱码问题
attach.setFileName(MimeUtility.encodeText(fileName.replace("runtime", "").replace("daily", "").replace("\\", "")));
}
}
}
Transport.send(msg);
//删除附件,防止积压文件过多
// if (null != newFilePaths && newFilePaths.size() > 0) {
// for (String fileName : newFilePaths) {
// File folder = new File(fileName);
// folder.delete();
// }
// }
return "SUCCESS";
} catch (Exception e) {
logger.error("报错信息:{}", e);
e.printStackTrace();
}
return "FAILED";
}
@Override
public String upload(MultipartFile file) {
//上传文件保存文件夹, 不存在则新建.
File folder = new File(uploadPath);
if (!folder.exists() && !folder.isDirectory()) {
folder.mkdirs();
}
String fileName = file.getOriginalFilename();
Path path = Paths.get(folder + File.separator + fileName);
try {
InputStream inputStream = file.getInputStream();
Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
return "SUCCESS";
} catch (Exception e) {
e.getMessage();
}
return "FAILED";
}
}
(5)主要pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
3.调用方
(1)主要上传文件
public void upload(MultipartFile multipartFile) {
String filePath = FileUtils.upload(multipartFile, uploadPath);
File file = new File(filePath);
HashMap<String, Object> paramMap = new HashMap<>();
//文件上传只需将参数中的键指定(默认file),值设为文件对象即可
paramMap.put("file", FileUtil.file(file));
String result= HttpUtil.post(uploadUrl, paramMap);
if(!"SUCCESS".equals(result)){
throw new BizException("远程上传文件失败");
}
}
(2)发送邮件
public void sendMail(MailConfigDO mailConfigDO, String from, String[] toMails
, String subject, String content, String contentType) throws Exception {
List<String> emailArr1 = Arrays.asList(toMails);
EmailDTO emailDTO = new EmailDTO();
emailDTO.setEmailArr(emailArr1);
emailDTO.setContent(content);
emailDTO.setSubject(subject);
emailDTO.setEmailHost(mailConfigDO.getHost());
emailDTO.setEmailUsername(mailConfigDO.getMailName());
emailDTO.setEmailPassword(mailConfigDO.getPassword());
String result= HttpUtil.post(emailUrl,JSON.toJSONString(emailDTO));
if(!"SUCCESS".equals(result)){
throw new BizException("远程发送邮件失败");
}
}
上面的两个url其实就是另一个服务的接口
上述使用的httpUtil是hutool包,引入该依赖即可
这样就可以实现远程发送邮件了
记录一下打包插件:
resource文件创建config文件夹
assembly.yml内容如下:
<assembly>
<id>assembly</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/bin</directory>
<includes>
<include>*.sh</include>
</includes>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/conf</directory>
<outputDirectory>config</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/sql</directory>
<includes>
<include>*.sql</include>
</includes>
<outputDirectory>sql</outputDirectory>
</fileSet>
<fileSet>
<directory>target/classes/</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
<include>*.txt</include>
<include>*.yml</include>
</includes>
<outputDirectory>config</outputDirectory>
</fileSet>
<fileSet>
<directory>target/classes/config</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
<include>*.txt</include>
<include>*.yml</include>
</includes>
<outputDirectory>config</outputDirectory>
</fileSet>
<fileSet>
<directory>target</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${project.artifactId}.jar</source>
<outputDirectory>.</outputDirectory>
</file>
</files>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
pom.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
<groupId>cn.com.yeexun</groupId>
<artifactId>Email</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 单独制定spring-framework版本,springboot版本有点低,不安全 -->
<spring-framework.version>5.3.26</spring-framework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>cn.com.yeexun.EmailApplication</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>*.xml</exclude>
<exclude>*.yml</exclude>
<exclude>*.properties</exclude>
<exclude>config/</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<outputDirectory>${project.basedir}/target</outputDirectory>
<appendAssemblyId>false</appendAssemblyId>
<!--具体的配置文件-->
<descriptors>${project.basedir}/src/main/resources/config/assembly.xml</descriptors>
</configuration>
<id>make-assembly</id>
<!--绑定到maven操作类型上-->
<phase>package</phase>
<!--运行一次-->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>