Spring Boot 傳送郵件
Maven 依賴
<!--mail-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
如果需要指定版本,也可以從mvn repo中找到你需要的版本號。
Spring Mail 服務簡介
Spring mail 是Spring 框架提供的一個程式庫,用於傳送電子郵件,使我們不受底層郵件系統的限制,只關注客戶端進行資源處理。Spring mail 包的內容如下:
MailSender
介面:核心介面,提供用於傳送簡單電子郵件的基本功能。JavaMailSender
介面:上述MailSender的子介面。它支援MIME訊息,並且通常與MimeMessageHelper類結合使用以建立MimeMessage。JavaMailSenderImpl
類:提供JavaMailSender介面的實現。它支援MimeMessage和SimpleMailMessage。SimpleMailMessage
類:用於建立簡單的郵件,包括from
(傳送者),to
(接收者),cc
(抄送),subject
(主題)和text
(文字)等欄位。MimeMessagePreparator
MimeMessageHelper
類:用於建立MIME訊息的幫助器類。它提供在HTML佈局中對影象,典型郵件附件和文字內容的支援。
郵件服務配置
引入maven依賴之後,下一步就是使用spring.mail.*
namespace 在 application.properties
檔案中配置郵件服務。
spring: mail: default-encoding: UTF-8 #郵件伺服器的地址:例如smtp.qq.com,smtp.gmail.com host: localhost #登陸伺服器的使用者名稱和密碼 username: username password: password port: 25 properties: mail: debug: false smtp: debug: false auth: true #啟用tls連線 starttls: true protocol: smtp test-connection: false
傳送郵件
傳送簡單郵件
@Service
public class MailServiceImpl implements MailService {
@Autowired
private JavaMailSender javaMailSender;
@Override
public void sendSimpleMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected]");
message.setTo("[email protected]");
message.setSubject("Test send simple mail message");
message.setText("Hello world!");
javaMailSender.send(message);
}
}
傳送附件郵件
@Override
public void sendMessageWithAttachment() {
MimeMessage message = javaMailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
helper.setSubject("Send attachment file to email");
helper.setText("attachment file...");
FileSystemResource file = new FileSystemResource(new File("Absolute path"));
helper.addAttachment("Invoice", file);
javaMailSender.send(message);
} catch (MessagingException ex) {
logger.error("Failed to send email to. error={}", ex.getMessage());
}
}
傳送模板郵件
Spring 中可以作為郵件模板的有幾個選擇:Velocity,Freemarker,Thymeleaf。 SpringBoot 1.4.0以後 Velocity 廢棄了,官方建議用Freemarker。而Thymeleaf的效率沒有freemaker高(評測見參考文章【4】)。
Freemarker 的語法可以參考官網的手冊:https://freemarker.apache.org/docs/index.html
中文手冊:https://sourceforge.net/projects/freemarker/files/chinese-manual/
同樣,我們先引入 Freemarker 的 Maven 依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
然後在專案的 /resoource/templates
目錄下新增一個 Freemarker 模板檔案 notification.flt
。
<html>
<head>
<title>Hello world!</title>
</head>
<body>
<h1>Hello</h1>
<p>My name is ${name}</p>
</body>
</html>
在 SpringBoot 的配置檔案中加上 Freemarker 的相關配置:
spring:
freemarker:
template-loader-path: classpath:/templates/
enabled: true
cache: false
charset: UTF-8
content-type: text/html
check-template-location: true
在 EmailServiceImpl
中使用 Freemarker 模板傳送郵件:
@Service
public class MailServiceImpl implements MailService {
private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
@Override
public void sendMessageWithFreemarkerTemplate() {
MimeMessage message = javaMailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
helper.setSubject("Send freemarker template to email");
HashMap<String, Object> models = new HashMap<>();
models.put("name", "freemarker");
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("notification.flt");
String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, models);
helper.setText(text);
javaMailSender.send(message);
} catch (Exception ex) {
logger.error("Failed to send email to. error={}", ex.getMessage());
}
}
}
至此實現了三中方式:純文字,富文字(圖片/附件),Freemarker模版的郵件傳送功能,接下來就來測試一下我們的郵件是否能傳送出去吧。
測試郵件傳送服務
我們為了測試郵件服務的傳送功能,暫時可以先不用使用真正的郵件伺服器,而是換成GreenMail。
GreenMail是用於測試目的的電子郵件伺服器,可以用於郵件整合測試或用於開發的輕量級沙盒郵件伺服器。具體的使用方法可以參考官網上的用例。
這裡先引入GreenMail 的Maven依賴:
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>1.5.11</version>
<scope>test</scope>
</dependency>
在Spring boot 的測試檔案(application-test.yaml)中配置用於郵件服務的相關屬性。
spring:
mail:
default-encoding: UTF-8
host: localhost
username: [email protected]
password: password
port: 3025
properties:
mail:
debug: false
smtp:
debug: false
auth: true
starttls: true
protocol: smtp
test-connection: false
我們建立一個自定義的 JUnit Rule 來初始化和停止GreenMail郵件伺服器。
public class SmtpServerRule extends ExternalResource {
# 設定傳送郵件服務的使用者的使用者名稱
private static final String USER_PASSWORD = "password";
# 設定傳送郵件服務使用者的密碼
private static final String USER_NAME = "[email protected]";
private GreenMail smtpServer;
@Override
protected void before() throws Throwable {
super.before();
smtpServer = new GreenMail(ServerSetupTest.SMTP);
smtpServer.start();
// setup user on the mail server
smtpServer.setUser(USER_NAME, USER_PASSWORD);
}
public MimeMessage[] getMessage() {
return smtpServer.getReceivedMessages();
}
@Override
protected void after() {
super.after();
smtpServer.stop();
}
}
然後就可以開始寫我們的測試用例了。
我們使用JUnit @Rule註解配置SmtpServerRule。這標記了在每個整合測試之前和之後要呼叫的自定義規則。並允許我們攔截傳入的電子郵件。最後,我們做出一些斷言並驗證傳送的電子郵件是否等於接收的電子郵件。
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class MailServiceImplTest {
@Rule
public SmtpServerRule smtpServerRule = new SmtpServerRule();
@Autowired
private MailService mailService;
@Test
public void sendSimpleMessage() throws MessagingException {
mailService.sendSimpleMessage();
MimeMessage[] messages = smtpServerRule.getMessage();
assertEquals("Test send simple mail message", messages[0].getSubject());
assertEquals("[email protected]", messages[0].getFrom()[0].toString());
assertEquals("[email protected]", messages[0].getAllRecipients()[0].toString());
}
}
另外的兩種郵件參考上面的程式碼實現。
總結
在這篇文章中,我們展示瞭如何通過Spring Boot應用程式設定和傳送電子郵件。所有這些示例和程式碼片段的實現都可以在MyGitHub專案中找到。
參考文章
【1】Testing mail code in Spring Boot application
【2】Spring Mail Integration Testing with JUnit and GreenMail Example