SpringCloud郵件工具類

簡介

SpringCloud使用的郵件工具和Springboot中的一樣,都可以使用spring-boot-starter-mail起步依賴來實現。本文將提供兩個郵件工具方法,分別是發送帶有單個附件的方法和發送帶有多個附件的方法,二者只是入參不同而已。本文還將介紹實際使用中遇到的問題及解決方法。

一.添加Maven依賴

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

二.在配置文件Properties.xml中添加郵件配置

配置文件需要修改前三行配置,你需要指定一個郵箱賬號和密碼,用其來發送郵件。這個賬號可以是QQ郵箱,也可以是網易郵箱,都可以。

根據選擇郵箱的不同,host屬性值也可能不同,這個地方需要調試,如果第一次就像成功,在下面填入QQ郵箱賬號密碼即可,host我已經給出,等你跑通了程序,在來測試或替換成你們公司的官方郵箱。

spring.mail.host=smtp.exmail.qq.com
spring.mail.username=填寫你的郵箱賬號(格式:[email protected])
spring.mail.password=填寫你的郵箱密碼
spring.mail.properties.mail.smtp.auth=true
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
# 連接時間限制(毫秒)
spring.mail.mail.smtp.connectiontimeout=10000
# 發送時間限制(毫秒)
spring.mail.mail.smtp.writetimeout=5000
# 本地不配置端口,默認端口25也可以發送,上線若連接失敗,改下端口
#spring.mail.port=465
#spring.mail.properties.mail.smtp.socketFactory.port=465

三.郵箱工具類(EmailUtils.java)

這裏面提供兩個方法,只需改下包名即可使用。


package com.blog.commons.mail;
import java.util.ArrayList;
import java.util.List;

import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.ObjectUtils;

import com.blog.commons.bean;

import lombok.extern.slf4j.Slf4j;

/**
 * @project commons-util
 * @description: 電子郵件工具類
 * @author 大腦補丁
 * @create 2020-03-17 20:32
 */
@Slf4j
public class EmailUtils {

    /**
     * 發送帶有單個附件的郵件
     * 
     * @param mailSender
     *            郵件工具實例 (客戶端通過 @Autowired JavaMailSender javaMailSender 注入即可使用)
     * 
     * @param fromEmail
     *            發件人郵箱地址(格式:[email protected])
     * @param toEmail
     *            收件人郵箱地址(格式:[email protected])
     * @param subject
     *            主題
     * @param content
     *            正文
     * @param attachment
     *            附件(若爲null則不添加附件)
     * @return 0:失敗,1:成功
     * 
     * @author 大腦補丁 on 2020-03-17 22:25
     */
    public static Integer sendMailAttachment(JavaMailSender mailSender, String fromEmail, String toEmail,
        String subject, String content, Attachment attachment) {
        // 附件名完整顯示
        System.setProperty("mail.mime.splitlongparameters", "false");
        MimeMessage message = mailSender.createMimeMessage();
        // 1:成功;0:失敗
        Integer result = 1;
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(fromEmail);
            helper.setTo(toEmail);
            helper.setSubject(subject);
            helper.setText(content, true);
            if (!ObjectUtils.isEmpty(attachment) && !ObjectUtils.isEmpty(attachment.getFileName())
                && !ObjectUtils.isEmpty(attachment.getFilePath())) {
                try {
                    FileSystemResource file = new FileSystemResource(attachment.getFilePath());
                    // helper.addAttachment(attachment.getFileName(), file);
                    // 附件中文名編碼,B:Base64編碼格式
                    helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);
                } catch (Exception e) {
                    // 如果存在附件,但添加附件時出錯,則標記郵件發送結果爲失敗
                    result = 0;
                    e.printStackTrace();
                }
            }
            if (result == 1) {
                // 若存在附件且附件添加成功時才發送;若不存在附件,則直接發送
                mailSender.send(message);
            }
            log.info("郵件發送成功,收件人地址:" + toEmail);
            return result;
        } catch (Exception e) {
            log.error("郵件發送出現異常,收件人地址:" + toEmail, e);
        }
        return result;
    }

    /**
     * 發送帶有多個附件的郵件
     * 
     * @param mailSender
     *            郵件工具實例 (客戶端通過 @Autowired JavaMailSender javaMailSender 注入即可使用)
     * 
     * @param fromEmail
     *            發件人郵箱地址(格式:[email protected])
     * @param toEmail
     *            收件人郵箱地址(格式:[email protected])
     * @param subject
     *            主題
     * @param content
     *            正文
     * @param List<Attachment>
     *            多個附件列表
     * @return 0:失敗,1:成功
     * @author 大腦補丁 on 2020-03-17 22:16
     */
    public static Integer sendMailAttachments(JavaMailSender mailSender, String fromEmail, String toEmail,
        String subject, String content, List<Attachment> attachments) {
        System.setProperty("mail.mime.splitlongparameters", "false");
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(fromEmail);
            helper.setTo(toEmail);
            helper.setSubject(subject);
            helper.setText(content, true);
            if (!ObjectUtils.isEmpty(attachments)) {
                attachments.forEach((attachment) -> {
                    try {
                        // 加載文件資源,作爲附件
                        FileSystemResource file = new FileSystemResource(attachment.getFilePath());
                        // 添加附件
                        helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
            mailSender.send(message);
            log.info("郵件發送成功,收件人地址:" + toEmail);
            return 1;
        } catch (Exception e) {
            log.error("郵件發送出現異常,收件人地址:" + toEmail, e);
        }
        return 0;
    }
}

四.郵件對象類(Attachment.java)

  • 上面工具類使用了一個附件對象,對象有兩個屬性,一個是附件名稱、一個是文件路徑。
  • 附件名稱是在郵件附件中的文件名,而不是本地文件名。文件路徑要注意,文件路徑要傳遞完整路徑,如:C:\temp\文檔.txt,因爲要同過文件流讀取這個文件,路徑不能只寫到文件夾。
  • 下面的實體類用到了lombok.jar,如果你沒有使用該插件,將下方類名上的3個註解刪除,並自行增加Getter\Setter方法即可。
package com.blog.commons.bean;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;

/**
 * @project commons-util
 * @description: 郵件附件
 * @author 大腦補丁
 * @create 2020-03-17 22:37
 */
@Data
@Accessors(chain = true)
@RequiredArgsConstructor(staticName = "of")
public class Attachment {
    /** 文件名稱 */
    private String fileName;
    /** 文件路徑 */
    private String filePath;
}

五.如何使用

  1. 在需要發送郵件的類中,通過@Autowired,注入郵件對象JavaMailSender
  2. 在需要發送郵件的類中,通過@Value("${spring.mail.username}"),注入配置文件中,你的郵箱地址。(爲什麼不寫死郵箱?因爲SpringCloud微服務每個服務模塊的郵箱賬號都不同,比如訂單有訂單的郵箱,廣告有廣告的郵箱。不可能只用一個郵箱賬號發送所有功能的郵件,否則很容易被郵箱客戶端自動列入黑名單,用戶收到的文件直接進入了垃圾箱)
@Value("${spring.mail.username}")
private String email;
  1. 創建附件對象。
Attachment attachment = new Attachment();
//郵件中的附件名,可以與路徑中的不一樣
attachment.setFileName("你的附件名.txt");
//硬盤中的文件名,必須寫擴展名。
attachment.setFilePath("C:temo\文檔.txt");
  1. 發送郵件
    發送成功返回1,失敗返回0。
Integer result = EmailUtils.sendMailAttachment(javaMailSender, email, "客戶[email protected]","標題", "正文。",attachment );

兩個工具方法的使用示例

    private void demo() {

        // 步驟一:注入郵件工具實例。
        // @Autowired
        // private JavaMailSender javaMailSender;

        // 步驟二:注入公司郵箱,配置文件中,微服務模塊對應的郵箱地址,每個服務郵箱地址可能不相同。
        // @Value("${spring.mail.username}")
        // private String email;

        // 步驟三:發送郵件。

        // 郵件工具1:發送單個附件郵件
        // Integer oneAttachment = EmailUtils.sendMailAttachment(javaMailSender, "業務模塊1專用郵箱@163.cn", "客戶[email protected]",
        // "我是標題", "您好!我是正文。", Attachment.of().setFileName("郵件附件名稱.xls").setFilePath("C:\\Workspace\\本地文件名稱.xlsx"));

        // 郵件工具2:發送多個附件郵件
        // 創建多個附件
        List<Attachment> attachments = new ArrayList<Attachment>();
        attachments.add(Attachment.of().setFileName("郵件附件名稱1.xlsx").setFilePath("C:\\Workspace\\本地文件名稱1.xlsx"));
        attachments.add(Attachment.of().setFileName("郵件附件名稱2.xlsx").setFilePath("C:\\Workspace\\本地文件名稱2.xlsx"));
        // 發送多個附件郵件
        // Integer multiAttachment = EmailUtils.sendMailAttachments(javaMailSender, "業務模塊專用郵箱@cnecloud.cn",
        // "客戶@qq.com","我是標題", "您好!我是正文。", attachments);
    }

六.Java正則表達式校驗郵件合法性

可以在控制層,驗證用戶輸入的郵箱是否合法的方法:

Pattern pattern = Pattern.compile(".+@.+\\.[a-z]+");
Matcher matcher = pattern.matcher(sendBillInput.getEmail());
    if (!matcher.matches()) {
        log.error("郵箱格式不合法");
    }

七.郵件發送中遇到的問題

1.附件中文名亂碼

解決方法:

在工具類中添加編碼即可。

MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
// 附件中文名編碼,參數"B"含義:Base64編碼格式
helper.addAttachment(MimeUtility.encodeWord(attachment.getFileName(), "UTF-8", "B"), file);

2.郵件附件名稱,顯示不全或被轉換成了其他字符。

如:附件名稱定義爲:2021年蘋果公司銷售額記錄單.xls,但QQ郵箱異常顯示爲:2021年蘋果公____司銷售額E7__.xls,網易郵箱異常顯示爲:ATT0002.bin,這是怎麼回事呢?

解決方法:

這個問題不同於亂碼,這不是附件名稱亂碼,而是附件名稱沒有正常的顯示全,我們再郵件工具中增加下行配置解決:

 System.setProperty("mail.mime.splitlongparameters", "false");

八.總結

關於SpringCloud、或Springboot中發送郵件的方法和常見問題,都分享在這了。掌握了這些,在SpringCloud中使用郵件已經足夠了。當然你可以將此工具類作爲一個單獨的SpringCloud郵件微服務進行使用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章