SpringBoot整合郵箱傳送郵件
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: [email protected]
# 授權碼(自己郵箱的授權碼)
password: AWYCRGDVOAUHTVOC
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; } }
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 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.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 "傳送複雜郵件失敗!!!"; } } }MailUtils