1. 概述
本教程將指導您完成從純 Java Spring 應用以及 Spring Boot 應用發送電子郵件的步驟。對於前者,我們將使用 JavaMail 庫,而後者將使用 <em >spring-boot-starter-mail</em> 依賴項。
2. Maven 依賴
首先,我們需要將依賴項添加到我們的 <em pom.xml</em> 中。
2.1. Spring
以下是我們將在純粹的 Spring 框架中使用添加的內容:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>6.2.12</version>
</dependency>最新版本可以在這裏找到:這裏。
2.2. Spring Boot
對於 Spring Boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>3.5.7</version>
</dependency>最新版本可在 Maven Central 倉庫中獲取。
3. 郵件服務器屬性
Spring框架中Java郵件支持的接口和類組織如下:
- MailSender 接口:提供基本功能的頂層接口,用於發送簡單的電子郵件。
- JavaMailSender 接口:上述 MailSender 的子接口。它支持 MIME 消息,通常與 MimeMessageHelper 類一起使用,用於創建 MimeMessage。建議使用此接口的 MimeMessagePreparator 機制。
- JavaMailSenderImpl 類:提供 JavaMailSender 接口的實現。它支持 MimeMessage 和 SimpleMailMessage。
- SimpleMailMessage 類:用於創建包含 from、to、cc、主題和文本字段的簡單郵件消息。
- MimeMessagePreparator 接口:提供 MIME 消息準備的回調接口。
- MimeMessageHelper 類:用於創建 MIME 消息的輔助類。它支持圖像、典型郵件附件和 HTML 佈局中的文本內容。
在後續部分,我們將展示如何使用這些接口和類。
3.1. Spring Mail Server 屬性
使用 JavaMailSenderImpl 可以定義所需的郵件屬性,例如指定 SMTP 服務器。
對於 Gmail,配置方法如下所示:
@Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("[email protected]");
mailSender.setPassword("password");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}
3.2. Spring Boot Mail Server 屬性
依賴項已添加後,下一步是在 application.properties文件中使用 spring.mail.*命名空間指定郵件服務器屬性。
可以通過以下方式指定 Gmail SMTP 服務器的屬性:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<login user to smtp server>
spring.mail.password=<login password to smtp server>
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
某些 SMTP 服務器需要 TLS 連接,因此我們使用屬性 spring.mail.properties.mail.smtp.starttls.enable啓用 TLS 保護的連接。
3.2.1. Gmail SMTP 屬性
我們可以通過 Gmail SMTP 服務器發送電子郵件。請參閲 文檔 以查看 Gmail 郵件發送 SMTP 服務器的屬性。
我們的 application.properties 文件已配置為使用 Gmail SMTP (見上一節)。
請注意,我們的賬户密碼不應是普通密碼,而應為為我們的 Google 賬户生成的應用程序密碼。請按照此 鏈接 查看詳細信息並生成您的 Google App Password。
3.2.2. SES SMTP 屬性
要使用 Amazon SES 發送電子郵件,我們設置我們的 application.properties :
spring.mail.host=email-smtp.us-west-2.amazonaws.com
spring.mail.username=username
spring.mail.password=password
spring.mail.properties.mail.transport.protocol=smtp
spring.mail.properties.mail.smtp.port=25
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true請注意,亞馬遜要求我們驗證憑據才能使用。請按照 此鏈接 驗證您的用户名和密碼。
4. 發送郵件
在依賴管理和配置就緒後,我們可以使用之前提到的 JavaMailSender 組件來發送郵件。
由於 Spring 框架(包括 Spring Boot 版本)都以類似的方式處理郵件的生成和發送,因此在下面的子章節中,我們無需區分這兩種版本。
4.1. 發送簡單的電子郵件
讓我們首先編寫併發送一條簡單的電子郵件,不包含任何附件:
@Component
public class EmailServiceImpl implements EmailService {
@Autowired
private JavaMailSender emailSender;
public void sendSimpleMessage(
String to, String subject, String text) {
...
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected]");
message.setTo(to);
message.setSubject(subject);
message.setText(text);
emailSender.send(message);
...
}
}請注意,雖然提供 from 地址並非強制要求,但許多 SMTP 服務器會拒絕此類消息。因此,我們在 EmailService 實現中使用了 [email protected] 電子郵件地址。
4.2. 發送帶有附件的郵件
有時 Spring 的簡單消息機制對於我們的用例來説是不夠的。
例如,我們想要發送包含發票的訂單確認郵件。在這種情況下,我們應該使用 MIME 多部分消息,從 JavaMail 庫中獲取,而不是 SimpleMailMessage。 Spring 支持使用 JavaMail 消息機制,通過使用 org.springframework.mail.javamail.MimeMessageHelper 類來實現。
首先,我們將添加一個方法到 EmailServiceImpl 中,用於發送帶有附件的郵件:
@Override
public void sendMessageWithAttachment(
String to, String subject, String text, String pathToAttachment) {
// ...
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("[email protected]");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file
= new FileSystemResource(new File(pathToAttachment));
helper.addAttachment("Invoice", file);
emailSender.send(message);
// ...
}4.3. 簡單郵件模板
<em class="String">SimpleMailMessage</em> 與字符串格式化效果良好。
我們可以通過在配置中定義模板 Bean 來創建郵件模板:
@Bean
public SimpleMailMessage templateSimpleMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setText(
"This is the test email template for your email:\n%s\n");
return message;
}現在我們可以使用這個 Bean 作為電子郵件模板,只需向模板提供必要的參數:
@Autowired
public SimpleMailMessage template;
...
String text = String.format(template.getText(), templateArgs);
sendSimpleMessage(to, subject, text);4.4. 使用 InputStream 發送附件
在需要發送動態生成或以 InputStream 形式提供的附件的情況下,我們可以利用 Spring 框架中的 MimeMessageHelper 類。
為了實現以 InputStream 形式提供的附件發送電子郵件,我們可以向 EmailServiceImpl 類添加以下方法:
public void sendMessageWithInputStreamAttachment(
String to, String subject, String text, String attachmentName, InputStream attachmentStream) {
try {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("[email protected]");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
// Add the attachment from InputStream
helper.addAttachment(attachmentName, new InputStreamResource(attachmentStream));
emailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}該方法首先通過使用 JavaMailSender 創建一個 MimeMessage 實例。 MimeMessageHelper 初始化為與 MimeMessage 關聯,從而支持多部分消息,這對於附件是必需的。
附件通過 addAttachment() 添加,其中 InputStreamResource 用於包裝提供的 InputStream。 這樣可以附加可能未存儲為文件的任何數據。
現在我們可以調用此方法:
InputStream attachmentStream = new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8));
emailService.sendMessageWithInputStreamAttachment(
"[email protected]",
"Subject Here",
"Body of the email",
"attachment.txt",
attachmentStream);在此示例中,一個簡單的字符串被轉換為 InputStream,然後作為名為 “attachment.txt” 的附件發送。 此方法提供了一種無需首先將它們保存到磁盤上的文件即可將各種類型的內容作為附件發送的靈活性。
5. 處理髮送錯誤
JavaMail 提供 SendFailedException 用於處理消息無法發送的情況。但是,在向錯誤的地址發送電子郵件時,我們可能無法收到該異常。原因如下:
RFC 821 中 SMTP 協議規範指定了 SMTP 服務器在嘗試向錯誤的地址發送電子郵件時應返回的 550 返回代碼。但大多數公共 SMTP 服務器並未執行此操作。相反,它們會發送“交付失敗”電子郵件或根本不提供任何反饋。
例如,Gmail SMTP 服務器會發送“交付失敗”消息。而我們的程序中不會拋出任何異常。
因此,我們有幾種處理這種情況的方法:
- 捕獲 SendFailedException,該異常永遠不會被拋出。
- 在一段時間內檢查我們的發件人郵箱中是否有“交付失敗”消息。這並不容易實現,並且時間間隔未確定。
- 如果我們的郵件服務器根本不提供任何反饋,我們什麼也不做。
結論
在本文中,我們演示瞭如何從 Spring Boot 應用程序中設置和發送電子郵件。