目錄
場景與方案分析
開啟QQ郵箱的SMTP服務
實體類準備
工具類準備
測試
場景與方案分析
最近部落客做了一個項目,有一個業務場景是這樣的:
背景管理者釋出活動的時候可以上傳與此活動相關的幾個檔案,使用者報名某活動之後,将這些檔案以附件的方式發送到其郵箱。
綜上需求,我先介紹一下我們系統的情況:
1、檔案可能上傳多個,是以郵件的發送涉及到多附件上傳;
2、我們的系統是前後端分離的,檔案子產品采用的是分布式的MinIO伺服器,都是外網伺服器上的線上檔案,不是落在Java項目所運作的伺服器磁盤上;
3、為了使用者體驗,郵件中的每個附件名稱都要是使用者上傳時的原檔案名稱。
以上三點我們依次考慮,
第一點無所謂,我們隻需要一個for循環即可;
第二點,因為我們的檔案存儲在專門的檔案伺服器上,是以我們需要讀取檔案的IO流,而不是指定本地磁盤上的檔案路徑;
第三點,我們在上傳檔案的時候記錄了檔案的原名稱,在發送郵件時要用一個實體類聲明檔案的外網路徑(用于擷取IO流)以及檔案的原名稱。
開啟QQ郵箱的SMTP服務
要發送郵件,就涉及到郵件發送方,在項目中一般是公司的企業賬号,但是測試、學習用我們自己的QQ郵箱也是可以的,步驟很簡單,在你的QQ郵箱裡進行如下操作:
然後點選“賬戶”,往下滑:
點選“開啟”,騰訊就會對你的身份進行驗證,驗證通過之後會給你一個授權碼,将這個授權碼儲存好,作為你發送郵件的憑證。
實體類準備
我們将檔案在外網的路徑和原名稱,用一個實體類來表示,在發送郵件時将該實體類的集合作為實參,達到多附件的效果。
package com.dosion.model.activity.entity.activity;
import lombok.Data;
/**
* <p>
* 活動課件
* </p>
*
* @author 秋楓豔夢
* @date 2019-12-03
* */
@Data
public class ActivityCourse {
//原檔案名
private String fileName;
//檔案的外網路徑
private String filePath;
public ActivityCourse () {}
public ActivityCourse (String fileName , String filePath) {
this.fileName = fileName;
this.filePath = filePath;
}
}
工具類準備
package com.dosion.utils;
import com.alibaba.druid.util.StringUtils;
import com.dosion.model.activity.entity.activity.ActivityCourse;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class EmailUtils {
// 發件人電子郵箱
private static String from = "你的[email protected]";
// 發件人電子郵箱授權碼
private static String pass = "你的授權碼";
//設定QQ郵箱伺服器
private static String host = "smtp.qq.com";
/**
* 發送帶附件的郵件
*
* @param receive 收件人
* @param subject 郵件主題
* @param msg 郵件内容
* @param courseList 課件附件的位址集合
* @return
* @throws GeneralSecurityException
*/
public static void sendMail(String receive, String subject, String msg, List<ActivityCourse> courseList)
throws GeneralSecurityException, MalformedURLException {
// 擷取系統屬性
Properties properties = System.getProperties();
// 設定郵件伺服器
properties.setProperty("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
// 擷取預設session對象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() { // qq郵箱伺服器賬戶、第三方登入授權碼
return new PasswordAuthentication(from, pass); // 發件人郵件使用者名、密碼
}
});
try {
//建立MimeMessage 對象
MimeMessage message = new MimeMessage(session);
//設定發送人
message.setFrom(new InternetAddress(from));
//設定接收人
message.addRecipient(Message.RecipientType.TO, new InternetAddress(receive));
//設定郵件主題
message.setSubject(subject);
// 建立普通消息部分
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(msg);
// 建立多重消息
Multipart multipart = new MimeMultipart();
// 設定多重消息的文本消息部分
multipart.addBodyPart(messageBodyPart);
//設定多重消息的附件部分
int size = courseList.size();
URL url;
for (int i = 0; i < size; i++) {
// 發送多個附件部分
messageBodyPart = new MimeBodyPart();
String path = courseList.get(i).getFilePath();
String fileName = courseList.get(i).getFileName();
// 設定要發送附件的檔案IO流
url = new URL(path);
DataSource source = new URLDataSource(url);
messageBodyPart.setDataHandler(new DataHandler(source));
//設定附件名稱
messageBodyPart.setFileName(MimeUtility.encodeText(fileName));
multipart.addBodyPart(messageBodyPart);
}
//設定最終的郵件
message.setContent(multipart);
//發送
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
測試
我們從京東上随便找一張圖檔:
再從我們的項目上拉一個xls檔案:
duxiaohui.dosion.cc/activity/system/file/activity-ee5452ddeeb649dd8cc5ac63ef6c443d.xls
public static void main(String[] args) throws GeneralSecurityException, MalformedURLException {
List<ActivityCourse> courseList = new ArrayList<>();
courseList.add(new ActivityCourse("京東商品圖檔.png","https://img10.360buyimg.com/mobilecms/s500x500_jfs/t1/86469/24/3091/112229/5ddcc257E7f8899db/d51bbc277e44ed94.jpg"));
courseList.add(new ActivityCourse("每日一答__模闆.xls","http://duxiaohui.dosion.cc/activity/system/file/activity-ee5452ddeeb649dd8cc5ac63ef6c443d.xls"));
sendMail("[email protected]","多附件測試-部落格","多附件正文,消息",courseList);
}
執行這個main方法,可以看到已經收到郵件了: