叙:本文主要記述了 Springboot 中如何內建并實作多附件的郵件發送,以QQ郵箱的伺服器為發送郵件的郵件伺服器;
Java實作多附件的郵件發送
- 1、前期準備
-
- 1.1、擷取收發伺服器位址及其端口号
- 1.2、 授權碼的擷取
- 2、代碼
-
- 2.1、pom檔案
- 2.1、Controller層
- Utils工具類
- 3、 測試接口
- 4、上傳檔案管控
1、前期準備
主要需要什麼呢?
- 第一,你要知道你選擇的作為發送郵件的郵箱賬号所在伺服器所提供的發送郵件伺服器(一般都會有一個發送郵件伺服器 [SMTP] 和接收郵件伺服器 [POP3]);
- 第二,發送郵件伺服器的端口号;
- 第三,你要針對發送郵件的郵箱設定 授權碼,這個授權碼就是第三方使用郵箱進行一系列操作時所需要登陸的密碼;
1.1、擷取收發伺服器位址及其端口号
收發郵件伺服器和端口号的整理都在此篇《各郵箱服務商的接收、發送郵件伺服器位址、端口号》文章中,有興趣的大家可以看看嘗試一下不同的郵箱發送短信,想要學習一下自己去找這些的可以繼續往下看;
第一步、第二步的獲悉資訊位置如下查找(QQ郵箱,其他的郵箱也差不多,有需要的可以去翻一下):
往下翻,找到下圖中的設定,首先開啟服務:IMAP/SMTP,通俗點說這個服務就是在開發過程中所使用的一種賬号認證服務設定,打開後點選第四步~
點選了第四步中的連接配接後可以看到如下的頁面,往下翻就會看到圖中的圈住的資訊了~
這一下就将我們所需要的三分之二的資料都找齊了,就剩下授權碼了;
1.2、 授權碼的擷取
其實第三個就是上上張截圖中第五步的操作,點選第五步的按鈕連結,如下圖所示:
使用上圖中的密保手機給框中的号碼【1069070069】發送一個内容為【配置郵件用戶端】的資訊,發送完後點選【我已發送】按鈕,若是QQ郵箱的伺服器收到了你發的短信,就會返給你個如下圖所示的16位串(圖是我偷的,我自己之前操作的我還記着呢,你們發吧,我随意~🤣🤣🤣),複制并儲存一下這個串;
en~,前準備工作可以了,下面開始上代碼;
2、代碼
就不多餘的叙述了,代碼裡面有注釋,如果碰到麻煩的可能會羅嗦兩句哈~
2.1、pom檔案
<!-- javamail —— 郵箱jar -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
2.1、Controller層
package com.java.product.module.controller;
import com.java.product.module.utils.MailSendUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.macrocloud.kernel.model.reqres.response.ResponseData;
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")
@Api(value = "郵件發送", tags = "發送郵件")
public class MailController {
/**
* 發送帶附件的郵件
*
* @param sendMail 發件人郵箱
* @param sendMailPwd 發件人密碼
* @param sendMailName 發件人昵稱(可選)
* @param receiveMail 收件人郵箱
* @param receiveMailName 收件人昵稱(可選)
* @param sendSMTPHost 發件人郵箱的 SMTP 伺服器位址, 必須準确, 不同郵件伺服器位址不同, 一般(隻是一般, 絕非絕對)格式為: smtp.xxx.com
* @param title 郵件主題
* @param content 郵件正文
* @param files 上傳的檔案集合
* @param port 郵件伺服器發送郵件端口
*/
@PostMapping("/sendFileMail")
@ApiOperation(value = "檔案郵件", notes = "sendMail(發件人郵箱),sendMailPwd(發件人密碼),sendMailName(發件人昵稱-可選), receiveMail(收件人郵箱),receiveMailName(收件人昵稱-可選), sendSMTPHost(發件人郵箱的SMTP伺服器位址),title(郵件主題),content(郵件正文)")
public ResponseData sendFileMail(String sendMail, String sendMailPwd, String sendMailName, String[] receiveMail, String receiveMailName, String sendSMTPHost, String title, String content,
MultipartFile[] files, String port) {
try{
MailSendUtil.sendFileMail(sendMail, sendMailPwd, sendMailName, receiveMail, receiveMailName, sendSMTPHost, title, content,
files, port);
}catch (Exception e){
return ResponseData.error(e.toString());
}
return ResponseData.success();
}
}
Utils工具類
package com.java.product.module.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
/**
* @Author:qtl
* @Discription:郵件發送工具類
* @Date:11:00 2021/4/20
*/
@Slf4j
public class MailSendUtil {
/**
* 郵箱正規表達式
*/
static final Pattern pattern = Pattern.compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
/**
* 發送帶附件的郵件
*
* @param sendMail 發件人郵箱
* @param sendMailPwd 發件人密碼(授權碼)
* @param sendMailName 發件人昵稱(可選)
* @param receiveMail 收件人郵箱
* @param receiveMailName 收件人昵稱(可選)
* @param sendSMTPHost 發件人郵箱的 SMTP 伺服器位址, 必須準确, 不同郵件伺服器位址不同, 一般(隻是一般, 絕非絕對)格式為: smtp.xxx.com
* @param title 郵件主題
* @param content 郵件正文
* @param files 附件檔案集合
* @param port 郵件伺服器發送郵件端口
*
*/
public static void sendFileMail(String sendMail, String sendMailPwd, String sendMailName, String[] receiveMail, String receiveMailName,
String sendSMTPHost, String title, String content, MultipartFile[] files, String port) {
Session session = createSSLSession(sendSMTPHost, port, sendMailName, sendMailPwd);
// 3. 建立一封郵件
MimeMessage message;
try {
message = createMimeMessage(session, sendMail, sendMailName, receiveMail, receiveMailName, title, content);
// 5. Content: 郵件正文(可以使用html标簽)(内容有廣告嫌疑,避免被郵件伺服器誤認為是濫發廣告以至傳回失敗,請修改發送内容)
MimeMultipart mm = new MimeMultipart();
MimeBodyPart text = new MimeBodyPart();
text.setContent(content, "text/html;charset=UTF-8");
mm.addBodyPart(text);
if (files.length > 0) {
for (MultipartFile f : files) {
// MultipartFile 轉化成 InputStream
byte [] byteArr=f.getBytes();
InputStream inputStream = new ByteArrayInputStream(byteArr);
MimeBodyPart attachment = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(inputStream, "application/msexcel");
attachment.setDataHandler(new DataHandler(source));
// 設定附件的檔案名(需要編碼)
attachment.setFileName(MimeUtility.encodeText(f.getOriginalFilename()));
// 10. 設定文本和 附件 的關系(合成一個大的混合"節點" / Multipart )
// 如果有多個附件,可以建立多個多次添加
mm.addBodyPart(attachment);
}
}
message.setContent(mm);
message.saveChanges();
// 4. 根據 Session 擷取郵件傳輸對象
Transport transport = session.getTransport("smtp");
transport.connect(sendSMTPHost, sendMail, sendMailPwd);
// 6. 發送郵件, 發到所有的收件位址, message.getAllRecipients() 擷取到的是在建立郵件對象時添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 關閉連接配接
} catch (Exception e) {
log.error("", e);
}
}
/**
* 建立session
*/
private static Session createSSLSession(String sendSMTPHost, String port, String userName, String pwd) {
// 1. 建立參數配置, 用于連接配接郵件伺服器的參數配置
Properties props = new Properties(); // 參數配置
props.setProperty("mail.smtp.user", userName);
props.setProperty("mail.smtp.password", pwd);
props.setProperty("mail.smtp.host", sendSMTPHost);
props.setProperty("mail.smtp.port", port);
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.port", port);
props.put("mail.smtp.auth", "true");
// 2. 根據配置建立會話對象, 用于和郵件伺服器互動
Session session = Session.getDefaultInstance(props, new Authenticator() {
//身份認證
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, pwd);
}
});
session.setDebug(true); // 設定為debug模式, 可以檢視詳細的發送 log
return session;
}
/**
* 建立一封隻包含文本的簡單郵件
*
* @param session 和伺服器互動的會話
* @param sendMail 發件人郵箱
* @param sendMailName 發件人昵稱
* @param receiveMail 收件人郵箱
* @param receiveMailName 收件人昵稱
* @param title 郵件主題
* @param content 郵件正文
* @return
* @throws Exception
*/
public static MimeMessage createMimeMessage(Session session, String sendMail, String sendMailName, String[] receiveMail, String receiveMailName, String title, String content) throws Exception {
// 1. 建立一封郵件
MimeMessage message = new MimeMessage(session);
// 2. From: 發件人
message.setFrom(new InternetAddress(sendMail, sendMailName, "UTF-8"));
// 3. To: 收件人(可以增加多個收件人、抄送、密送)
List<InternetAddress> to = new LinkedList<>();
for (String s : receiveMail) {
if (pattern.matcher(s).matches()) {
to.add(new InternetAddress(s));
}
}
//Address[] addresses = new Address[]{new InternetAddress(receiveMail),new InternetAddress(receiveMail)};
message.addRecipients(MimeMessage.RecipientType.TO, to.toArray((new InternetAddress[to.size()])));
// 4. Subject: 郵件主題(标題有廣告嫌疑,避免被郵件伺服器誤認為是濫發廣告以至傳回失敗,請修改标題)
message.setSubject(title, "UTF-8");
// 5. Content: 郵件正文(可以使用html标簽)(内容有廣告嫌疑,避免被郵件伺服器誤認為是濫發廣告以至傳回失敗,請修改發送内容)
message.setContent(content, "text/html;charset=UTF-8");
// 6. 設定發件時間
message.setSentDate(new Date());
// 7. 儲存設定
message.saveChanges();
return message;
}
}
3、 測試接口
在此解釋一下哈,我沒有用swagger來調試我的接口,可能很多人都很奇怪,為什麼我配置了swagger但是卻不用它呢?因為在swagger中,同一個集合中隻能存在一個參數,也就是說我沒法測多個檔案同時上傳的效果了,嘛~ !隻能這樣使用postMan了,下圖中的參數如果覺得亂的,大家可以看一下controller層中的字段注釋~
傳回的資料結果說請求成功了,那麼我登陸一下我的接收者賬号,看看資料是否正常存在~
第一部至少成功了,就看裡面的附件了;
OK,檔案正常!一切正常~
4、上傳檔案管控
另外,存在一個下問題,既然涉及到了檔案的上傳,那就需要有個檔案上傳管控了,配置檔案【application.yml】中加入如下代碼:
spring:
# 開啟檔案上傳控制
servlet:
multipart:
enabled: true
# 檔案寫入磁盤的門檻值
file-size-threshold: 1KB
# 最大檔案大小
max-file-size: 10MB
# 最大請求大小
max-request-size: 200MB
pass:文中有什麼不明白的歡迎提問,共同努力,共同進步!