最近项目准备进入测试阶段,时间相对充沛些,便对邮箱的信息发送记录下!
邮箱设置-开启smtp协议及获取授权码
以QQ邮箱为例,其他邮箱大同小异!
开启协议
获取授权码
具体代码
基于javax.mail实现
原文可看 前辈帖子
pom.xml
<!-- 邮件 -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version >1.5.4 </version >
</dependency>
EmailVO.java类(前端上送参数)
package com.example.demo.vo;
import lombok.Data;
import java.util.List;
/**
* @Auther: lr
* @Date: 2024/6/12 16:14
* @Description:
*/
@Data
public class EmailVO {
private String content; //正文
private String subject; //主题
private List<String> toEmailPerson; //收件人
private List<String> ccMail; //抄送人
private List<String> bccMail; //密送人
private List<String> fileNames; //附件
}
EmailPropertiesConstant常量信息(一般会在系统设置中配置)
package com.example.demo.constant;
import lombok.Data;
/**
* @Auther: lr
* @Date: 2024/6/12 17:11
* @Description:
*/
@Data
public class EmailPropertiesConstant {
// 发件人smtp邮箱服务地址
private String emailSmtpHost = "smtp.qq.com";
// 发件人smtp端口
private String emailSmtpPort = "25";
// 开启TLS加密
private String emailSmtpIsneedssl = "1";
// 开启验证
private String emailSmtpIsneedauth = "1";
// 发件人邮箱地址
private String userName = "xxx@qq.com";
// smtp邮箱授权码
private String userPassword = "xxx";
// 发件人昵称
private String userNicky = "测试人";
// 邮箱开关状态 0关闭 1开启
private String status = "1";
}
EmailUtil类(发送邮件)
package com.example.demo.util;
import com.example.demo.constant.EmailPropertiesConstant;
import com.example.demo.vo.EmailVO;
import com.sun.mail.util.MailSSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.CollectionUtils;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
/**
* @Auther: lr
* @Date: 2024/6/13 10:38
* @Description:
*/
public class EmailUtil {
private static final Logger logger = LoggerFactory.getLogger(EmailUtil.class);
/**
* 发送邮件
* @param emailPropertiesConstant 系统信息配置
* @param emailVO 邮件信息
* @return
*/
public static HashMap<String, Object> sendEmail(EmailPropertiesConstant emailPropertiesConstant,
EmailVO emailVO) {
HashMap<String, Object> resultMap = new HashMap<>();
if ("0".equals(emailPropertiesConstant.getStatus())) {
logger.error("邮箱未开启");
resultMap.put("code", 500);
resultMap.put("message", "邮箱未开启!");
return resultMap;
}
if (CollectionUtils.isEmpty(emailVO.getToEmailPerson())) {
logger.error("邮件收件人为空");
resultMap.put("code", 500);
resultMap.put("message", "邮件收件人为空!");
return resultMap;
}
try {
// 设置参数
Properties properties = System.getProperties();
// smtp服务地址
properties.put("mail.smtp.host", emailPropertiesConstant.getEmailSmtpHost());
// smtp服务端口
properties.put("mail.smtp.port", emailPropertiesConstant.getEmailSmtpPort());
// 开启验证
properties.put("mail.smtp.auth", "1".equals(emailPropertiesConstant.getEmailSmtpIsneedauth()) ? "true" : "false");
// 开启TLS加密
properties.put("mail.smtp.starttls.enable", "1".equals(emailPropertiesConstant.getEmailSmtpIsneedssl()) ? "true" : "false");
// 是否启用socketFactory,默认为true
properties.put("mail.smtp.socketFactory.fallback", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
// 建立会话,利用内部类将邮箱授权给jvm
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailPropertiesConstant.getUserName(), emailPropertiesConstant.getUserPassword());
}
});
// 设置为true可以在控制台打印发送过程,生产环境关闭
session.setDebug(true);
// 创建邮件对象
MimeMessage message = new MimeMessage(session);
// 通过MimeMessageHelper设置正文和附件,否则会导致两者显示不全
MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
//设置发件人 to为收件人,cc为抄送,bcc为密送
helper.setFrom(new InternetAddress(emailPropertiesConstant.getUserName(), emailPropertiesConstant.getUserNicky()));
helper.setTo(InternetAddress.parse(String.join(",", emailVO.getToEmailPerson()), false));
if (!CollectionUtils.isEmpty(emailVO.getCcMail())) {
helper.setCc(InternetAddress.parse(String.join(",", emailVO.getCcMail()), false));
}
if (!CollectionUtils.isEmpty(emailVO.getBccMail())) {
helper.setBcc(InternetAddress.parse(String.join(",", emailVO.getBccMail()), false));
}
// 设置邮件主题
helper.setSubject(emailVO.getSubject());
//设置邮件正文内容
helper.setText(emailVO.getContent());
//设置发送的日期
helper.setSentDate(new Date());
// 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
if (!CollectionUtils.isEmpty(emailVO.getFileNames())) {
for (String fileName : emailVO.getFileNames()) {
FileDataSource fileDataSource = new FileDataSource(fileName);
helper.addAttachment(fileDataSource.getName(), fileDataSource);
}
}
//调用Transport的send方法去发送邮件
Transport.send(message);
logger.info("发送邮件成功****************************!");
resultMap.put("code", 200);
resultMap.put("message", "邮件发送成功!");
return resultMap;
} catch (Exception e) {
e.printStackTrace();
logger.error("邮件发送失败****************************!", e);
resultMap.put("code", 500);
resultMap.put("message", "邮件发送失败");
resultMap.put("data", e);
return resultMap;
}
}
}
EmailController类
package com.example.demo.controller;
import com.example.demo.constant.EmailPropertiesConstant;
import com.example.demo.util.EmailUtil;
import com.example.demo.vo.EmailVO;
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 java.util.HashMap;
/**
* @Auther: lr
* @Date: 2024/6/12 10:30
* @Description:
*/
@RestController
@RequestMapping("/email")
public class EmailController {
@PostMapping("/testEmail")
public HashMap<String, Object> testEmail(@RequestBody EmailVO emailVO) {
HashMap<String, Object> hashMap = EmailUtil.sendEmail(new EmailPropertiesConstant(), emailVO);
return hashMap;
}
}
测试
注意点
mail.smtp.auth,默认是true。一般用来测试QQ邮箱需要开启认证,而当时项目需求是客户方用内网连接邮箱服务器,此时不需要账号密码验证,所以设置为mail.smtp.auth=fale即可。但是当时生产上同时设置了mail.smtp.starttls.enable=false,未出现使用异常,到目前还是比较疑惑这个参数的设置。
发送邮件时 需要有网!!! 局域网也可。
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Exception reading response;
nested exception is:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?. Failed messages: javax.mail.MessagingException: Exception reading response;
nested exception is:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?解决办法:mail.smtp.socketFactory.fallback=true
基于spring-boot-starter-mail实现
系统参数是配置到application.yml文件中的,不利于系统维护邮件配置信息!!!
pom.xml
<!-- 邮件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
application.yml文件
spring:
mail:
host: smtp.qq.com #发件人smtp邮箱服务地址
username: xxxx@qq.com #发件人邮箱地址
password: xxx #smtp邮箱授权码
default-encoding: UTF-8
properties:
userNicky: test #发件人昵称
status: 1 #邮箱开关状态 0关闭 1开启
mail:
smtp:
auth: true #开启加密
ssl:
enable: true
starttls:
enable: true #开启TLS验证
socketFactory:
fallback: true
debug: true
port: 25 #发件人smtp端口
EmailUtil文件
package com.example.demo.util;
import com.example.demo.vo.EmailVO;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.activation.FileDataSource;
import javax.mail.internet.MimeMessage;
import java.util.HashMap;
/**
* @Auther: lr
* @Date: 2024/6/14 10:14
* @Description:
*/
@Component
@AllArgsConstructor
public class EmailUtil {
private static final Logger logger = LoggerFactory.getLogger(EmailUtil.class);
@Autowired
JavaMailSender javaMailSender;
@Autowired
MailProperties mailProperties;
/**
* 发送邮件
* @param emailVO 邮件信息
* @return
*/
public HashMap<String, Object> sendEmail(EmailVO emailVO){
HashMap<String, Object> resultMap = new HashMap<>();
if ("0".equals(mailProperties.getProperties().get("status"))) {
logger.error("邮箱未开启");
resultMap.put("code", 500);
resultMap.put("message", "邮箱未开启!");
return resultMap;
}
if (CollectionUtils.isEmpty(emailVO.getToEmailPerson())) {
logger.error("邮件收件人为空");
resultMap.put("code", 500);
resultMap.put("message", "邮件收件人为空!");
return resultMap;
}
try {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(mailProperties.getUsername(), mailProperties.getProperties().get("userNicky"));
helper.setTo(String.join(",", emailVO.getToEmailPerson()));
if (!CollectionUtils.isEmpty(emailVO.getCcMail())) {
helper.setCc(String.join(",", emailVO.getCcMail()));
}
if (!CollectionUtils.isEmpty(emailVO.getBccMail())) {
helper.setBcc(String.join(",", emailVO.getBccMail()));
}
helper.setSubject(emailVO.getSubject());
helper.setText(emailVO.getContent());
// 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
if (!CollectionUtils.isEmpty(emailVO.getFileNames())) {
for (String fileName : emailVO.getFileNames()) {
FileDataSource fileDataSource = new FileDataSource(fileName);
helper.addAttachment(fileDataSource.getName(), fileDataSource);
}
}
javaMailSender.send(message);
logger.info("发送邮件成功****************************!");
resultMap.put("code", 200);
resultMap.put("message", "邮件发送成功!");
return resultMap;
}catch (Exception e) {
e.printStackTrace();
logger.error("邮件发送失败****************************!", e);
resultMap.put("code", 500);
resultMap.put("message", "邮件发送失败");
resultMap.put("data", e);
return resultMap;
}
}
}
controller
package com.example.demo.controller;
import com.example.demo.constant.EmailPropertiesConstant;
import com.example.demo.util.EmailUtil;
import com.example.demo.vo.EmailVO;
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 java.util.HashMap;
/**
* @Auther: lr
* @Date: 2024/6/12 10:30
* @Description:
*/
@RestController
@RequestMapping("/email")
public class EmailController {
@Autowired
EmailUtil emailUtil;
@PostMapping("/test")
public HashMap<String, Object> test(@RequestBody EmailVO emailVO) {
HashMap<String, Object> hashMap = emailUtil.sendEmail(emailVO);
return hashMap;
}
}
测试
目前接触到的项目使用过这两种方式,简单记录下!