1. SpringBoot整合郵箱發送郵件
在開發中,經常會碰到email郵件發送的場景,如發送驗證碼,向客戶發送郵件等等。
今天,本項目將講解通過 SpringBoot 發送 email 郵件(普通文本郵件 ,HTML內容板式郵件 ,包含靜態資源郵件,以及帶附件郵件)。
2. 項目配置
2.1 創建SpringBoot項目
項目結構,簡單測試沒有分包
2.2 pom文件導入需要的依賴
<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>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
2.3 郵箱smtp配置
因為各大郵件都有其對應安全系統,不是項目中想用就可以用的,我們必須要拿到其對應的客戶端授權碼才行,拿到授權碼,在項目中配置SMTP服務協議以及主機配置賬戶,才可以在項目中使用各大郵件
運營商進行發送郵件了。
什么是SMTP?SMTP全稱為Simple Mail Transfer Protocol(簡單郵件傳輸協議),它是一組用於從源地址到目的地址傳輸郵件的規范,通過它來控制郵件的中轉方式。SMTP認證要求必須提供賬號和密碼
才能登陸服務器,其設計目的在於避免用戶受到垃圾郵件的侵擾。
什么是IMAP?IMAP全稱為Internet Message Access Protocol(互聯網郵件訪問協議),IMAP允許從郵件服務器上獲取郵件的信息、下載郵件等。IMAP與POP類似,都是一種郵件獲取協議。
什么是POP3?POP3全稱為Post Office Protocol 3(郵局協議),POP3支持客戶端遠程管理服務器端的郵件。POP3常用於“離線”郵件處理,即允許客戶端下載服務器郵件,然后服務器上的郵件將會被刪
除。目前很多POP3的郵件服務器只提供下載郵件功能,服務器本身並不刪除郵件,這種屬於改進版的POP3協議。
獲取客戶端授權碼過程,由於國內使用163郵箱以及qq郵箱較多,僅展示163郵箱獲取客戶端授權碼的步驟(qq的類似)
如果沒有開啟,選擇開啟發送驗證碼即可,我的是已經開過了(如果忘記授權碼,重新發送短信生成)
2.4 配置yml文件
在拿到授權碼后,就可以在我們Springboot工程中的配置文件 aplication.yml 或者properties文件中配置了
server:
port: 8091
# 郵件配置
spring:
mail:
# 這里換成自己的郵箱類型 例如smtp.163.com, smtp.qq.com
host: smtp.163.com
# 發送郵件服務協議
protocol: smtp
# 編碼集
default-encoding: UTF-8
# 發送郵件的賬戶
username: liy22222@163.com
# 授權碼(自己郵箱的授權碼)
password: AWYFJEIJSDFJASSDDDVOC
test-connection: true
properties:
mail:
smtp:
# 表示SMTP發送郵件,需要進行身份驗證
auth: true
starttls:
enable: true
required: true
2.5 創建接收消息的對象
package com.liyh;
import lombok.*;
@Data
public class MessageInfo {
/**
* 收件人郵箱
**/
private String receiver;
/**
* 一對多群發收件人郵箱
**/
private String receivers;
/**
* 郵件標題
**/
private String subject;
/**
* 郵件內容
**/
private String content;
/**
* 圖片路徑
**/
private String imgPath;
/**
* 文件路徑
**/
private String filePath1;
/**
* 文件路徑
**/
private String filePath2;
/**
* 發件人姓名
**/
private String fromName;
/**
* 收件人姓名
**/
private String receiverName;
}
2.6 Html郵箱模板
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8"/>
<title>郵件通知</title>
</head>
<body>
<div>
<includetail>
<div align="center">
<div class="open_email" style="margin-left: 8px; margin-top: 8px; margin-bottom: 8px; margin-right: 8px;">
<div>
<br>
<span class="genEmailContent">
<div id="cTMail-Wrap"
style="word-break: break-all;box-sizing:border-box;text-align:center;min-width:320px; max-width:660px; border:1px solid #f6f6f6; background-color:#f7f8fa; margin:auto; padding:20px 0 30px; font-family:'helvetica neue',PingFangSC-Light,arial,'hiragino sans gb','microsoft yahei ui','microsoft yahei',simsun,sans-serif">
<div class="main-content" style="">
<table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse">
<tbody>
<tr style="font-weight:300">
<td style="width:3%;max-width:30px;"></td>
<td style="max-width:600px;">
<div id="cTMail-logo" style="width:92px; height:25px;">
<a href="">
<img border="0" src="https://image.youyoushop.work/yahoo/zhenyu.png"
style="height:50px;display:block">
</a>
</div>
<p style="height:2px;background-color: #00a4ff;border: 0;font-size:0;padding:0;width:100%;margin-top:20px;"></p>
<div id="cTMail-inner" style="background-color:#fff; padding:23px 0 20px;box-shadow: 0px 1px 1px 0px rgba(122, 55, 55, 0.2);text-align:left;">
<table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse;text-align:left;">
<tbody>
<tr style="font-weight:300">
<td style="width:3.2%;max-width:30px;"></td>
<td style="max-width:480px;text-align:left;">
<h1 id="cTMail-title" style="font-size: 20px; line-height: 36px; margin: 0px 0px 22px;">
郵件測試平台
</h1>
<p id="cTMail-receiverName" style="font-size:14px;color:#333; line-height:24px; margin:0;">
尊敬的<span style="font-weight: bold;"> ${receiverName} </span>用戶,您好!
</p>
<p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
<span style="color: rgb(51, 51, 51); font-size: 14px;">
由<span style="font-weight: bold;"> ${fromName} </span>發送的郵件請及時處理。消息內容如下:<br/>
</span>
</p>
<p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
<span style="color: rgb(51, 51, 51); font-size: 14px;">
<span style="font-weight: bold;">${content}</span>
</span>
</p>
<dl style="font-size: 14px; color: rgb(51, 51, 51); line-height: 18px;">
<dd style="margin: 0px 0px 6px; padding: 0px; font-size: 12px; line-height: 22px;">
<p id="cTMail-sender" style="font-size: 14px; line-height: 26px; word-wrap: break-word; word-break: break-all; margin-top: 32px;">
發送時間
<br>
<strong>${sendTime}</strong>
</p>
</dd>
</dl>
</td>
<td style="width:3.2%;max-width:30px;"></td>
</tr>
</tbody>
</table>
</div>
</td>
<td style="width:3%;max-width:30px;"></td>
</tr>
</tbody>
</table>
</div>
</div>
</span>
</div>
</div>
</div>
</includetail>
</div>
</body>
</html>
2.7 創建Spring工具類
package com.liyh;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* spring工具類 方便在非spring管理環境中獲取bean
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
/**
* Spring應用上下文環境
*/
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
/**
* 獲取對象
*
* @param name
* @return Object 一個以所給名字注冊的bean的實例
* @throws org.springframework.beans.BeansException
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 獲取類型為requiredType的對象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) beanFactory.getBean(clz);
return result;
}
}
2.8 創建 MailUtil 工具類
package com.liyh;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
@Component
public class MailUtil {
/**
* 從配置文件中注入發件人的姓名
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* Spring官方提供的集成郵件服務的實現類,目前是Java后端發送郵件和集成郵件服務的主流工具。
*/
@Autowired
private JavaMailSender mailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
}
2.9 創建 MailUtils 工具類
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 統一郵件發送工具類
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 從配置文件中注入是否需要身份驗證
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 從配置文件中注入郵箱類型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 從配置文件中注入發件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 從配置文件中注入授權碼
*/
@Value("${spring.mail.password}")
private String password;
}
2.10 創建 SendMailController
package com.liyh;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 發送郵件接口
*/
@RestController
@RequestMapping("/mail")
public class SendMailController {
}
3. 第一種方式可以配置模板使用
下面開始 SpringBoot 項目中發送郵件的代碼編寫
其實也非常簡單 ,SpringBoot已經給我們郵件發送進行了非常好的整合了,我們只需要注入郵件發送接口 調用其中的方法,就能輕松而愉悅的進行郵件發送了!
3.1 發送文本郵件
3.1.1 創建 MailUtil 工具類,添加代碼
/**
* 發送文本郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
*/
public String sendSimpleMail(String receiver, String subject, String content) {
try {
SimpleMailMessage message = new SimpleMailMessage();
// 發件人
message.setFrom(fromEmail);
// 收件人
message.setTo(receiver);
// 郵件標題
message.setSubject(subject);
// 郵件內容
message.setText(content);
mailSender.send(message);
return "發送文本郵件成功";
} catch (MailException e) {
e.printStackTrace();
return "發送文本郵件失敗!!!";
}
}
3.1.2 添加訪問接口
/**
* 發送文本郵件
*
* @param messageInfo 郵件信息
*/
@PostMapping("sendSimpleMail")
public String sendSimpleMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
}
3.1.3 測試接口
3.2 發送帶附件的郵件
3.2.1 在MailUtil工具類添加代碼
/**
* 發送帶附件的郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param filePath 文件路徑
* @param imgPath 圖片路徑
* @param multipartFile 上傳的文件
*/
public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
try {
MimeMessage message = mailSender.createMimeMessage();
// 要帶附件第二個參數設為true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 發件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 郵件標題
helper.setSubject(subject);
// 郵件內容,第二個參數:格式是否為html
helper.setText(content, true);
// 添加文件附件1
FileSystemResource file = new FileSystemResource(new File(filePath));
helper.addAttachment(file.getFilename(), file);
// 添加文件附件2
FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
helper.addAttachment(files.getFilename(), files);
// 添加圖片附件
FileSystemResource image = new FileSystemResource(new File(imgPath));
helper.addAttachment(image.getFilename(), image);
mailSender.send(message);
return "發送帶附件的郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送帶附件的郵件失敗!!!";
}
}
3.2.2 在MailUtil工具類添加代碼
/**
* 把 multiFile 轉換為 file
*
* @param multiFile
* @return
*/
private File multipartFileToFile(MultipartFile multiFile) {
// 獲取文件名
String fileName = multiFile.getOriginalFilename();
// 獲取文件后綴
String prefix = fileName.substring(fileName.lastIndexOf("."));
// 若需要防止生成的臨時文件重復,可以在文件名后添加隨機碼
try {
File file = File.createTempFile(fileName, prefix);
multiFile.transferTo(file);
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3.2.3 添加訪問接口
/**
* 發送帶附件的郵件
*
* @param messageInfo 郵件信息
* @param multipartFile 上傳的文件
*/
@PostMapping("sendAttachmentsMail")
public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 發送帶附件的郵件( 路徑中的 \ 通常需要使用 \\, 如果是 / 就不需要使用轉義了, \ 常用於本地,而/ 常用於網絡連接地址 )
// D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
// C:/Users/Administrator/Pictures/1.jpg
return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
}
3.2.4 測試接口
3.3 發送模板郵件
3.3.1 在MailUtil工具類添加代碼
/**
* 發送模板郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param fromName 發件人姓名
* @param receiverName 收件人姓名
* @return
*/
public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 獲得模板
Template template = null;
try {
template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
} catch (IOException e) {
e.printStackTrace();
return "獲取模板失敗!!!";
}
// 使用Map作為數據模型,定義屬性和值
Map<String, Object> model = new HashMap<>();
model.put("fromName", fromName);
model.put("receiverName", receiverName);
model.put("content", content);
model.put("sendTime", simpleDateFormat.format(new Date()));
// 傳入數據模型到模板,替代模板中的占位符,並將模板轉化為html字符串
String templateHtml = null;
try {
templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
} catch (IOException e) {
e.printStackTrace();
return "轉換模板失敗!!!";
} catch (TemplateException e) {
e.printStackTrace();
return "轉換模板失敗!!!";
}
// 該方法本質上還是發送html郵件,調用之前發送html郵件的方法
return this.sendHtmlMail(receiver, subject, templateHtml);
}
/**
* 發送html郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
*/
public String sendHtmlMail(String receiver, String subject, String content) {
try {
// 注意這里使用的是MimeMessage
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 發件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 郵件標題
helper.setSubject(subject);
// 郵件內容,第二個參數:格式是否為html
helper.setText(content, true);
mailSender.send(message);
return "發送html郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送html郵件失敗!!!";
}
}
3.3.2 添加訪問接口
/**
* 發送模板郵件
*
* @param messageInfo 郵件信息
* @return
*/
@PostMapping("sendTemplateMail")
public String sendTemplateMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 發送Html模板郵件
return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFromName(), messageInfo.getReceiverName());
}
3.3.3 測試接口
4 第二種方式可以發送復雜的郵件(支持一對多發送郵件)
4.1 發送復雜郵件
4.1.1 創建 MailUtils 工具類,添加代碼
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;
/**
* 統一郵件發送工具類
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 從配置文件中注入是否需要身份驗證
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 從配置文件中注入郵箱類型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 從配置文件中注入發件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 從配置文件中注入授權碼
*/
@Value("${spring.mail.password}")
private String password;
/**
* 發送復雜郵件
*
* @param receivers 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param imgPath 圖片路徑
* @param filePath1 文件路徑
* @param filePath2 文件路徑
*/
public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
try {
Properties props = new Properties();
// 表示SMTP發送郵件,需要進行身份驗證
props.put("mail.smtp.auth", auth);
props.put("mail.smtp.host", emailHost);
// 發件人的賬號
props.put("mail.user", fromEmail);
// 訪問SMTP服務時需要提供的密碼
props.put("mail.password", password);
// 1.Session對象.連接(與郵箱服務器連接)
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
});
// 2.構建郵件信息
Message message = new MimeMessage(session);
// 發件人郵箱
message.setFrom(new InternetAddress(fromEmail));
// Message.RecipientType.TO:消息接受者
// Message.RecipientType.CC:消息抄送者
// Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到這個接受者的姓名和地址)
// 判斷接收人個數
if (receivers != null && receivers != "") {
String[] receiverArray = receivers.split(",");
if (receiverArray.length == 1) {
// 一對一發送郵件
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
} else {
// 一對多發送郵件
// 構建一個群發地址數組
String[] receiverArry = receivers.split(",");
InternetAddress[] adr = new InternetAddress[receiverArry.length];
for (int i = 0; i < receiverArry.length; i++) {
adr[i] = new InternetAddress(receiverArry[i]);
}
// Message的setRecipients方法支持群發。。注意:setRecipients方法是復數和點 到點不一樣
message.setRecipients(Message.RecipientType.TO, adr);
}
}
// 發送日期
message.setSentDate(new Date());
// 設置標題
message.setSubject(subject);
// 3.准備郵件內容
// 3.1.准備圖片數據
MimeBodyPart image = new MimeBodyPart();
FileDataSource imageSource = new FileDataSource(imgPath);
DataHandler handler = new DataHandler(imageSource);
image.setDataHandler(handler);
image.setFileName(imageSource.getName());
// 創建圖片的一個表示用於顯示在郵件中顯示
image.setContentID(imageSource.getName());
// 3.2准備本文本數據
MimeBodyPart text = new MimeBodyPart();
text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");
// 3.3.准備附件數據
MimeBodyPart appendix1 = new MimeBodyPart();
FileDataSource fileSource1 = new FileDataSource(filePath1);
appendix1.setDataHandler(new DataHandler(fileSource1));
appendix1.setFileName(fileSource1.getName());
MimeBodyPart appendix2 = new MimeBodyPart();
FileDataSource fileSource2= new FileDataSource(filePath2);
appendix2.setDataHandler(new DataHandler(fileSource2));
appendix2.setFileName(fileSource2.getName());
// 3.4.拼裝郵件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(image);
mimeMultipart.addBodyPart(text);
// 文本和圖片內嵌成功
mimeMultipart.setSubType("related");
// 3.5.將拼裝好的正文內容設置為主體
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
// 3.6.拼接附件
MimeMultipart allFile = new MimeMultipart();
// 附件
allFile.addBodyPart(image);
allFile.addBodyPart(appendix1);
allFile.addBodyPart(appendix2);
// 正文
allFile.addBodyPart(contentText);
// 正文和附件都存在郵件中,所有類型設置為mixed
allFile.setSubType("mixed");
// 3.7.放到Message消息中
message.setContent(allFile);
// 4.發送郵件信息
Transport.send(message);
return "發送復雜郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送復雜郵件失敗!!!";
}
}
}
4.1.2 添加訪問接口
/**
* 發送復雜郵件
*
* @param messageInfo 郵件信息
*/
@PostMapping("sendComplexMail")
public String sendComplexMail(MessageInfo messageInfo) {
MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
}
4.1.3 測試接口
4.2 完整工具類代碼
4.2.1 SendMailController
查看代碼
package com.liyh;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* 發送郵件接口
*/
@RestController
@RequestMapping("/mail")
public class SendMailController {
/**
* 發送文本郵件
*
* @param messageInfo 郵件信息
*/
@PostMapping("sendSimpleMail")
public String sendSimpleMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
}
/**
* 發送帶附件的郵件
*
* @param messageInfo 郵件信息
* @param multipartFile 上傳的文件
*/
@PostMapping("sendAttachmentsMail")
public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 發送帶附件的郵件( 路徑中的 \ 通常需要使用 \\, 如果是 / 就不需要使用轉義了, \ 常用於本地,而/ 常用於網絡連接地址 )
// D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
// C:/Users/Administrator/Pictures/1.jpg
return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
}
/**
* 發送模板郵件
*
* @param messageInfo 郵件信息
* @return
*/
@PostMapping("sendTemplateMail")
public String sendTemplateMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 發送Html模板郵件
return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFromName(), messageInfo.getReceiverName());
}
/**
* 發送復雜郵件
*
* @param messageInfo 郵件信息
*/
@PostMapping("sendComplexMail")
public String sendComplexMail(MessageInfo messageInfo) {
MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
}
}
4.2.2 MailUtil
查看代碼
package com.liyh;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class MailUtil {
/**
* 從配置文件中注入發件人的姓名
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* Spring官方提供的集成郵件服務的實現類,目前是Java后端發送郵件和集成郵件服務的主流工具。
*/
@Autowired
private JavaMailSender mailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
/**
* 發送文本郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
*/
public String sendSimpleMail(String receiver, String subject, String content) {
try {
SimpleMailMessage message = new SimpleMailMessage();
// 發件人
message.setFrom(fromEmail);
// 收件人
message.setTo(receiver);
// 郵件標題
message.setSubject(subject);
// 郵件內容
message.setText(content);
mailSender.send(message);
return "發送文本郵件成功";
} catch (MailException e) {
e.printStackTrace();
return "發送文本郵件失敗!!!";
}
}
/**
* 發送html郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
*/
public String sendHtmlMail(String receiver, String subject, String content) {
try {
// 注意這里使用的是MimeMessage
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 發件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 郵件標題
helper.setSubject(subject);
// 郵件內容,第二個參數:格式是否為html
helper.setText(content, true);
mailSender.send(message);
return "發送html郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送html郵件失敗!!!";
}
}
/**
* 發送帶附件的郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param filePath 文件路徑
* @param imgPath 圖片路徑
* @param multipartFile 上傳的文件
*/
public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
try {
MimeMessage message = mailSender.createMimeMessage();
// 要帶附件第二個參數設為true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 發件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 郵件標題
helper.setSubject(subject);
// 郵件內容,第二個參數:格式是否為html
helper.setText(content, true);
// 添加文件附件1
FileSystemResource file = new FileSystemResource(new File(filePath));
helper.addAttachment(file.getFilename(), file);
// 添加文件附件2
FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
helper.addAttachment(files.getFilename(), files);
// 添加圖片附件
FileSystemResource image = new FileSystemResource(new File(imgPath));
helper.addAttachment(image.getFilename(), image);
mailSender.send(message);
return "發送帶附件的郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送帶附件的郵件失敗!!!";
}
}
/**
* 發送模板郵件
*
* @param receiver 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param fromName 發件人姓名
* @param receiverName 收件人姓名
* @return
*/
public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 獲得模板
Template template = null;
try {
template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
} catch (IOException e) {
e.printStackTrace();
return "獲取模板失敗!!!";
}
// 使用Map作為數據模型,定義屬性和值
Map<String, Object> model = new HashMap<>();
model.put("fromName", fromName);
model.put("receiverName", receiverName);
model.put("content", content);
model.put("sendTime", simpleDateFormat.format(new Date()));
// 傳入數據模型到模板,替代模板中的占位符,並將模板轉化為html字符串
String templateHtml = null;
try {
templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
} catch (IOException e) {
e.printStackTrace();
return "轉換模板失敗!!!";
} catch (TemplateException e) {
e.printStackTrace();
return "轉換模板失敗!!!";
}
// 該方法本質上還是發送html郵件,調用之前發送html郵件的方法
return this.sendHtmlMail(receiver, subject, templateHtml);
}
/**
* 把 multiFile 轉換為 file
*
* @param multiFile
* @return
*/
private File multipartFileToFile(MultipartFile multiFile) {
// 獲取文件名
String fileName = multiFile.getOriginalFilename();
// 獲取文件后綴
String prefix = fileName.substring(fileName.lastIndexOf("."));
// 若需要防止生成的臨時文件重復,可以在文件名后添加隨機碼
try {
File file = File.createTempFile(fileName, prefix);
multiFile.transferTo(file);
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
MailUtil
4.2.3 MailUtils
查看代碼
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;
/**
* 統一郵件發送工具類
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 從配置文件中注入是否需要身份驗證
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 從配置文件中注入郵箱類型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 從配置文件中注入發件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 從配置文件中注入授權碼
*/
@Value("${spring.mail.password}")
private String password;
/**
* 發送復雜郵件
*
* @param receivers 收件人
* @param subject 郵件標題
* @param content 郵件內容
* @param imgPath 圖片路徑
* @param filePath1 文件路徑
* @param filePath2 文件路徑
*/
public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
try {
Properties props = new Properties();
// 表示SMTP發送郵件,需要進行身份驗證
props.put("mail.smtp.auth", auth);
props.put("mail.smtp.host", emailHost);
// 發件人的賬號
props.put("mail.user", fromEmail);
// 訪問SMTP服務時需要提供的密碼
props.put("mail.password", password);
// 1.Session對象.連接(與郵箱服務器連接)
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
});
// 2.構建郵件信息
Message message = new MimeMessage(session);
// 發件人郵箱
message.setFrom(new InternetAddress(fromEmail));
// Message.RecipientType.TO:消息接受者
// Message.RecipientType.CC:消息抄送者
// Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到這個接受者的姓名和地址)
// 判斷接收人個數
if (receivers != null && receivers != "") {
String[] receiverArray = receivers.split(",");
if (receiverArray.length == 1) {
// 一對一發送郵件
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
} else {
// 一對多發送郵件
// 構建一個群發地址數組
String[] receiverArry = receivers.split(",");
InternetAddress[] adr = new InternetAddress[receiverArry.length];
for (int i = 0; i < receiverArry.length; i++) {
adr[i] = new InternetAddress(receiverArry[i]);
}
// Message的setRecipients方法支持群發。。注意:setRecipients方法是復數和點 到點不一樣
message.setRecipients(Message.RecipientType.TO, adr);
}
}
// 發送日期
message.setSentDate(new Date());
// 設置標題
message.setSubject(subject);
// 3.准備郵件內容
// 3.1.准備圖片數據
MimeBodyPart image = new MimeBodyPart();
FileDataSource imageSource = new FileDataSource(imgPath);
DataHandler handler = new DataHandler(imageSource);
image.setDataHandler(handler);
image.setFileName(imageSource.getName());
// 創建圖片的一個表示用於顯示在郵件中顯示
image.setContentID(imageSource.getName());
// 3.2准備本文本數據
MimeBodyPart text = new MimeBodyPart();
text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");
// 3.3.准備附件數據
MimeBodyPart appendix1 = new MimeBodyPart();
FileDataSource fileSource1 = new FileDataSource(filePath1);
appendix1.setDataHandler(new DataHandler(fileSource1));
appendix1.setFileName(fileSource1.getName());
MimeBodyPart appendix2 = new MimeBodyPart();
FileDataSource fileSource2= new FileDataSource(filePath2);
appendix2.setDataHandler(new DataHandler(fileSource2));
appendix2.setFileName(fileSource2.getName());
// 3.4.拼裝郵件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(image);
mimeMultipart.addBodyPart(text);
// 文本和圖片內嵌成功
mimeMultipart.setSubType("related");
// 3.5.將拼裝好的正文內容設置為主體
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
// 3.6.拼接附件
MimeMultipart allFile = new MimeMultipart();
// 附件
allFile.addBodyPart(image);
allFile.addBodyPart(appendix1);
allFile.addBodyPart(appendix2);
// 正文
allFile.addBodyPart(contentText);
// 正文和附件都存在郵件中,所有類型設置為mixed
allFile.setSubType("mixed");
// 3.7.放到Message消息中
message.setContent(allFile);
// 4.發送郵件信息
Transport.send(message);
return "發送復雜郵件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "發送復雜郵件失敗!!!";
}
}
}
MailUtils