简介
SpringCloud使用的邮件工具和Springboot中的一样,都可以使用spring-boot-starter-mail
起步依赖来实现。本文将提供两个邮件工具方法,分别是发送带有单个附件的方法和发送带有多个附件的方法,二者只是入参不同而已。本文还将介绍实际使用中遇到的问题及解决方法。
一.添加Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
二.在配置文件Properties.xml中添加邮件配置
配置文件需要修改前三行配置,你需要指定一个邮箱账号和密码,用其来发送邮件。这个账号可以是QQ邮箱,也可以是网易邮箱,都可以。
根据选择邮箱的不同,host属性值也可能不同,这个地方需要调试,如果第一次就像成功,在下面填入QQ邮箱账号密码即可,host我已经给出,等你跑通了程序,在来测试或替换成你们公司的官方邮箱。
spring.mail.host=smtp.exmail.qq.com
spring.mail.username=填写你的邮箱账号(格式:1000@qq.com)
spring.mail.password=填写你的邮箱密码
spring.mail.properties.mail.smtp.auth=true
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
# 连接时间限制(毫秒)
spring.mail.mail.smtp.connectiontimeout=10000
# 发送时间限制(毫秒)
spring.mail.mail.smtp.writetimeout=5000
# 本地不配置端口,默认端口25也可以发送,上线若连接失败,改下端口
#spring.mail.port=465
#spring.mail.properties.mail.smtp.socketFactory.port=465
三.邮箱工具类(EmailUtils.java)
这里面提供两个方法,只需改下包名即可使用。
package com.blog.commons.mail;
import java.util.ArrayList;
import java.util.List;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.ObjectUtils;
import com.blog.commons.bean;
import lombok.extern.slf4j.Slf4j;
/**
* @project commons-util
* @description: 电子邮件工具类
* @author 大脑补丁
* @create 2020-03-17 20:32
*/
@Slf4j
public class EmailUtils {
/**
* 发送带有单个附件的邮件
*
* @param mailSender
* 邮件工具实例 (客户端通过 @Autowired JavaMailSender javaMailSender 注入即可使用)
*
* @param fromEmail
* 发件人邮箱地址(格式:abc@xxx.com)
* @param toEmail
* 收件人邮箱地址(格式:abc@xxx.com)
* @param subject
* 主题
* @param content
* 正文
* @param attachment
* 附件(若为null则不添加附件)
* @return 0:失败,1:成功
*
* @author 大脑补丁 on 2020-03-17 22:25
*/
public static Integer sendMailAttachment(JavaMailSender mailSender, String fromEmail, String toEmail,
String subject, String content, Attachment attachment) {
// 附件名完整显示
System.setProperty("mail.mime.splitlongparameters", "false");
MimeMessage message = mailSender.createMimeMessage();
// 1:成功;0:失败
Integer result = 1;
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(fromEmail);
helper.setTo(toEmail);
helper.setSubject(subject);
helper.setText(content, true);
if (!ObjectUtils.isEmpty(attachment) && !ObjectUtils.isEmpty(attachment.getFileName())
&& !ObjectUtils.isEmpty(attachment.getFilePath())) {
try {
FileSystemResource file = new FileSystemResource(attachment.getFilePath());
// helper.addAttachment(attachment.getFileName(), file);
// 附件中文名编码,B:Base64编码格式
helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);
} catch (Exception e) {
// 如果存在附件,但添加附件时出错,则标记邮件发送结果为失败
result = 0;
e.printStackTrace();
}
}
if (result == 1) {
// 若存在附件且附件添加成功时才发送;若不存在附件,则直接发送
mailSender.send(message);
}
log.info("邮件发送成功,收件人地址:" + toEmail);
return result;
} catch (Exception e) {
log.error("邮件发送出现异常,收件人地址:" + toEmail, e);
}
return result;
}
/**
* 发送带有多个附件的邮件
*
* @param mailSender
* 邮件工具实例 (客户端通过 @Autowired JavaMailSender javaMailSender 注入即可使用)
*
* @param fromEmail
* 发件人邮箱地址(格式:abc@xxx.com)
* @param toEmail
* 收件人邮箱地址(格式:abc@xxx.com)
* @param subject
* 主题
* @param content
* 正文
* @param List<Attachment>
* 多个附件列表
* @return 0:失败,1:成功
* @author 大脑补丁 on 2020-03-17 22:16
*/
public static Integer sendMailAttachments(JavaMailSender mailSender, String fromEmail, String toEmail,
String subject, String content, List<Attachment> attachments) {
System.setProperty("mail.mime.splitlongparameters", "false");
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(fromEmail);
helper.setTo(toEmail);
helper.setSubject(subject);
helper.setText(content, true);
if (!ObjectUtils.isEmpty(attachments)) {
attachments.forEach((attachment) -> {
try {
// 加载文件资源,作为附件
FileSystemResource file = new FileSystemResource(attachment.getFilePath());
// 添加附件
helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);
} catch (Exception e) {
e.printStackTrace();
}
});
}
mailSender.send(message);
log.info("邮件发送成功,收件人地址:" + toEmail);
return 1;
} catch (Exception e) {
log.error("邮件发送出现异常,收件人地址:" + toEmail, e);
}
return 0;
}
}
四.邮件对象类(Attachment.java)
- 上面工具类使用了一个附件对象,对象有两个属性,一个是附件名称、一个是文件路径。
- 附件名称是在邮件附件中的文件名,而不是本地文件名。文件路径要注意,文件路径要传递完整路径,如:
C:\temp\文档.txt
,因为要同过文件流读取这个文件,路径不能只写到文件夹。 - 下面的实体类用到了lombok.jar,如果你没有使用该插件,将下方类名上的3个注解删除,并自行增加Getter\Setter方法即可。
package com.blog.commons.bean;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
/**
* @project commons-util
* @description: 邮件附件
* @author 大脑补丁
* @create 2020-03-17 22:37
*/
@Data
@Accessors(chain = true)
@RequiredArgsConstructor(staticName = "of")
public class Attachment {
/** 文件名称 */
private String fileName;
/** 文件路径 */
private String filePath;
}
五.如何使用
- 在需要发送邮件的类中,通过
@Autowired
,注入邮件对象JavaMailSender
。 - 在需要发送邮件的类中,通过
@Value("${spring.mail.username}")
,注入配置文件中,你的邮箱地址。(为什么不写死邮箱?因为SpringCloud微服务每个服务模块的邮箱账号都不同,比如订单有订单的邮箱,广告有广告的邮箱。不可能只用一个邮箱账号发送所有功能的邮件,否则很容易被邮箱客户端自动列入黑名单,用户收到的文件直接进入了垃圾箱)
@Value("${spring.mail.username}")
private String email;
- 创建附件对象。
Attachment attachment = new Attachment();
//邮件中的附件名,可以与路径中的不一样
attachment.setFileName("你的附件名.txt");
//硬盘中的文件名,必须写扩展名。
attachment.setFilePath("C:temo\文档.txt");
- 发送邮件
发送成功返回1,失败返回0。
Integer result = EmailUtils.sendMailAttachment(javaMailSender, email, "客户1@qq.com","标题", "正文。",attachment );
两个工具方法的使用示例
private void demo() {
// 步骤一:注入邮件工具实例。
// @Autowired
// private JavaMailSender javaMailSender;
// 步骤二:注入公司邮箱,配置文件中,微服务模块对应的邮箱地址,每个服务邮箱地址可能不相同。
// @Value("${spring.mail.username}")
// private String email;
// 步骤三:发送邮件。
// 邮件工具1:发送单个附件邮件
// Integer oneAttachment = EmailUtils.sendMailAttachment(javaMailSender, "业务模块1专用邮箱@163.cn", "客户1@qq.com",
// "我是标题", "您好!我是正文。", Attachment.of().setFileName("邮件附件名称.xls").setFilePath("C:\\Workspace\\本地文件名称.xlsx"));
// 邮件工具2:发送多个附件邮件
// 创建多个附件
List<Attachment> attachments = new ArrayList<Attachment>();
attachments.add(Attachment.of().setFileName("邮件附件名称1.xlsx").setFilePath("C:\\Workspace\\本地文件名称1.xlsx"));
attachments.add(Attachment.of().setFileName("邮件附件名称2.xlsx").setFilePath("C:\\Workspace\\本地文件名称2.xlsx"));
// 发送多个附件邮件
// Integer multiAttachment = EmailUtils.sendMailAttachments(javaMailSender, "业务模块专用邮箱@cnecloud.cn",
// "客户@qq.com","我是标题", "您好!我是正文。", attachments);
}
六.Java正则表达式校验邮件合法性
可以在控制层,验证用户输入的邮箱是否合法的方法:
Pattern pattern = Pattern.compile(".+@.+\\.[a-z]+");
Matcher matcher = pattern.matcher(sendBillInput.getEmail());
if (!matcher.matches()) {
log.error("邮箱格式不合法");
}
七.邮件发送中遇到的问题
1.附件中文名乱码
解决方法:
在工具类中添加编码即可。
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
// 附件中文名编码,参数"B"含义:Base64编码格式
helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);
2.邮件附件名称,显示不全或被转换成了其他字符。
如:附件名称定义为:2021年苹果公司销售额记录单.xls
,但QQ邮箱异常显示为:2021年苹果公____司销售额E7__.xls
,网易邮箱异常显示为:ATT0002.bin
,这是怎么回事呢?
解决方法:
这个问题不同于乱码,这不是附件名称乱码,而是附件名称没有正常的显示全,我们再邮件工具中增加下行配置解决:
System.setProperty("mail.mime.splitlongparameters", "false");
八.总结
关于SpringCloud、或Springboot中发送邮件的方法和常见问题,都分享在这了。掌握了这些,在SpringCloud中使用邮件已经足够了。当然你可以将此工具类作为一个单独的SpringCloud邮件微服务进行使用了。