天天看點

使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試

目錄

場景與方案分析

開啟QQ郵箱的SMTP服務

實體類準備

工具類準備

測試

場景與方案分析

最近部落客做了一個項目,有一個業務場景是這樣的:

背景管理者釋出活動的時候可以上傳與此活動相關的幾個檔案,使用者報名某活動之後,将這些檔案以附件的方式發送到其郵箱。

綜上需求,我先介紹一下我們系統的情況:

1、檔案可能上傳多個,是以郵件的發送涉及到多附件上傳;

2、我們的系統是前後端分離的,檔案子產品采用的是分布式的MinIO伺服器,都是外網伺服器上的線上檔案,不是落在Java項目所運作的伺服器磁盤上;

3、為了使用者體驗,郵件中的每個附件名稱都要是使用者上傳時的原檔案名稱。

以上三點我們依次考慮,

第一點無所謂,我們隻需要一個for循環即可;

第二點,因為我們的檔案存儲在專門的檔案伺服器上,是以我們需要讀取檔案的IO流,而不是指定本地磁盤上的檔案路徑;

第三點,我們在上傳檔案的時候記錄了檔案的原名稱,在發送郵件時要用一個實體類聲明檔案的外網路徑(用于擷取IO流)以及檔案的原名稱。

開啟QQ郵箱的SMTP服務

要發送郵件,就涉及到郵件發送方,在項目中一般是公司的企業賬号,但是測試、學習用我們自己的QQ郵箱也是可以的,步驟很簡單,在你的QQ郵箱裡進行如下操作:

使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試

然後點選“賬戶”,往下滑:

使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試

點選“開啟”,騰訊就會對你的身份進行驗證,驗證通過之後會給你一個授權碼,将這個授權碼儲存好,作為你發送郵件的憑證。

實體類準備

我們将檔案在外網的路徑和原名稱,用一個實體類來表示,在發送郵件時将該實體類的集合作為實參,達到多附件的效果。

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();
        }
    }
}
           

測試

我們從京東上随便找一張圖檔:

使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試

再從我們的項目上拉一個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方法,可以看到已經收到郵件了:

使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試
使用Java發送郵件(IO流方式攜帶多個附件)場景與方案分析開啟QQ郵箱的SMTP服務實體類準備工具類準備測試

繼續閱讀