1. 程式人生 > 實用技巧 >Spring Boot demo系列(七):郵件服務

Spring Boot demo系列(七):郵件服務

1 概述

Spring Boot整合郵件服務,包括髮送普通的文字郵件以及帶附件的郵件。

2 郵箱選擇

這裡選擇的是QQ郵箱作為傳送的郵箱,當然也可以選擇其他的郵箱,只是具體的配置不一樣。

使用QQ郵箱的話,需要在個人設定中開啟SMTP服務:

傳送簡訊後完成驗證即可,會有一個授權碼,先複製下來儲存。

3 具體實現

3.1 依賴

提供了starter

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

gradle

implementation 'org.springframework.boot:spring-boot-starter-mail'

3.2 郵件介面

只有兩個簡單的介面,一個是傳送純文字的,一個是傳送帶附件的:

public interface MailService {
    void sendSimpleMail(String to,String subject,String content);
    void sendAttachmentMail(String to, String subject, String content, Path file) throws MessagingException;
}

3.3 介面實現

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MailServiceImpl implements MailService{
    private final JavaMailSender sender;

    @Value("${spring.mail.username}")
    private String from;

    @Override
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        sender.send(message);
    }

    @Override
    public void sendAttachmentMail(String to, String subject, String content, Path file) throws MessagingException {
        MimeMessage message = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message,true);
        helper.setFrom(from);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content);
        helper.addAttachment(file.getFileName().toString(),new FileSystemResource(file));
        sender.send(message);
    }
}

JavaMailSenderSpring Boot攜帶的郵件傳送介面,注入後可以傳送SimpleMailMessage以及MimeMessage型別的資訊。

  • SimpleMailMessage:簡單的郵件資訊物件,封裝了一些常見的屬性,比如寄信地址以及收信地址,傳送日期,主題,內容等
  • MimeMessage:傳送MIME型別的郵件資訊,MIME指的是Multipurpose Internet Mail Extensiosns,是描述訊息內容型別的因特網標準,能包含文字,影象,音訊,視訊以及其他應用程式專用的資料
  • MimeMessageHelper:用於設定MimeMessage屬性的類,可以利用其中的addAttachment新增附件
  • setFrom/setTo/setSubject/setText:分別表示設定寄信地址/收信地址/主題/內容

3.4 測試類

@SpringBootTest
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
class DemoApplicationTests {
	private final MailService service;

	@Test
	void contextLoads() throws URISyntaxException, MessagingException {
		service.sendSimpleMail("[email protected]","這是主題","這是內容");
		service.sendAttachmentMail("[email protected]","這是主題","這是內容", Path.of(Objects.requireNonNull(getClass().getClassLoader().getResource("pic/1.jpg")).toURI()));
		//附件為resources下pic/1.jpg
		service.sendAttachmentMail("[email protected]","這是主題","這是內容", Path.of("/","srv","http","1.jpg"));
		//附件為/srv/http/1.jpg
	}

傳送文字直接指定主題和內容即可,傳送帶附件的話:

  • 如果是resources下的內容,使用getClass().getClassLoader().getReource("xxx/xxx")
  • 如果是絕對路徑,使用Path.of("/","path1","path2",...,"filename")

3.5 配置檔案

spring:
  mail:
    host: smtp.qq.com
    username: [email protected]
    password: xxxxxxxxxx
    port: 465
    properties:
      mail:
        smtp:
          ssl:
            enable: true
          auth: true
          starttls:
            enable: true
            required: true

作為Demo使用只需要修改username以及password即可。

  • username:傳送的使用者郵箱
  • password:不是郵箱密碼,而是授權碼,就是剛才開啟SMTP服務出現的授權碼

其他配置說明:

  • hostSMTP伺服器地址
  • port:埠,可以選擇465/587host以及port可以參考QQ郵箱文件
  • properties:裡面都是一些安全設定,開啟SSL以及認證等

3.6 測試

修改測試類的郵箱,執行單元測試即可。

如果沒通過,可以參考這裡,羅列了常見的錯誤碼以及可能的解決方案。

4 加密

由於使用者名稱以及密碼都直接寫在了配置檔案中,如果洩露的話會很危險,因此需要對配置檔案進行加密。

具體的話可以參考筆者之前的原力計劃文章,戳這裡

4.1 依賴

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

gradle

implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3")

4.2 配置檔案

配置檔案只需要加上加密口令即可:

jasypt:
  encryptor:
    password: test

預設使用的是PBE加密演算法,PBE其實是一種組合加密演算法,預設是採用HCMA演算法(混合CMA-ES演算法)+SHA512訊息摘要演算法+AES256對稱加密演算法。

另外,如果不想在配置檔案直接寫上加密的口令,可以使用以下三種方法對口令進行引數化:

命令列引數(執行時設定):

java -jar xxx.jar --jasypt.encryptor.password=test

應用環境變數(執行時設定):

java -Djasypt.encryptor.password=test -jar xxx.jar

系統環境變數(在配置檔案中設定):

jasypt:
  encryptor:
    password: ${TEST}
# 表示獲取環境變數TEST的值作為加密口令

4.3 測試類

新建一個測試類:

@SpringBootTest
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class EncryptAndDecrypt {
    private final StringEncryptor encryptor;
    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    @Test
    public void encrypt()
    {
        System.out.println(encryptor.encrypt(username));
        System.out.println(encryptor.encrypt(password));
    }

    @Test
    public void decrypt()
    {
        System.out.println(username);
        System.out.println(password);
    }
}

4.4 獲取密文

假設明文如下:

執行encrypt即可,輸出如下:

4.5 替換明文

加上字首ENC(以及字尾)去替換明文:

4.6 測試

獲取明文直接執行decrypt即可,輸出:

這樣就完成加密了。

5 原始碼

Java版:

Kotlin版: