簡介
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=填寫你的郵箱賬號(格式:[email protected])
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
* 發件人郵箱地址(格式:[email protected])
* @param toEmail
* 收件人郵箱地址(格式:[email protected])
* @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
* 發件人郵箱地址(格式:[email protected])
* @param toEmail
* 收件人郵箱地址(格式:[email protected])
* @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, "客戶[email protected]","標題", "正文。",attachment );
兩個工具方法的使用示例
private void demo() {
// 步驟一:注入郵件工具實例。
// @Autowired
// private JavaMailSender javaMailSender;
// 步驟二:注入公司郵箱,配置文件中,微服務模塊對應的郵箱地址,每個服務郵箱地址可能不相同。
// @Value("${spring.mail.username}")
// private String email;
// 步驟三:發送郵件。
// 郵件工具1:發送單個附件郵件
// Integer oneAttachment = EmailUtils.sendMailAttachment(javaMailSender, "業務模塊1專用郵箱@163.cn", "客戶[email protected]",
// "我是標題", "您好!我是正文。", 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郵件微服務進行使用了。