如何使用 MS Exchange 伺服器傳送電子郵件
1. 引言
在企業級Java應用程式中,發送電子郵件非常普遍。一些應用場景包括發送事務性郵件、發送通知或共享重要更新。
本文將探討如何使用 Java 以程式設計方式設定和傳送電子郵件,並介紹 MS Exchange Server。我們也將探討常見問題及相應的解決方案。
2. 先決條件
在本節中,我們將了解使用 Exchange Server 傳送電子郵件的先決條件。
2.1. SMTP 屬性
在開始編寫程式碼之前,我們需要確保擁有 SMTP 主機名稱、SMTP 連接埠以及有效的 Exchange 使用者名稱和密碼。此外,我們還需要知道存取伺服器的連接埠號碼。通常情況下,連接埠號碼為 25 或 587。
2.2. 所需庫
Java 本身並非原生支援發送電子郵件。我們需要使用jakarta.mail-api (以前稱為 JavaMail)來發送電子郵件,而angus-mail是運行時實際需要的 SMTP 實作。如果沒有 angus-mail,我們會收到提供者或傳輸錯誤。
讓我們新增 Maven 依賴項:
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-mail</artifactId>
<version>2.0.3</version>
</dependency>
3. Java 程式碼範例
在本節中,我們將探討如何透過 Java 程式碼存取 MS Exchange 並傳送電子郵件。
3.1. 設定 SMTP 屬性
要透過 Exchange 傳送電子郵件,我們需要設定 SMTP 屬性。這些屬性告訴 Java 如何連接到 Exchange 伺服器。
我們先來介紹一下這些屬性:
Properties props = new Properties();
props.put("mail.smtp.host", "exchange.company.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "LOGIN");
mail.smtp.host指定 SMTP 指令需要傳送到的主機。
接下來, mail.smtp.port指定伺服器接受 SMTP 連線的連接埠。這裡我們使用了連接埠 587,這是一個需要身份驗證的標準連接埠。通常,出於安全考慮,Exchange 伺服器不允許透過連接埠 25 進行通訊。
接下來,我們將mail.smtp.auth設為true ,這告訴 JavaMail 在嘗試發送郵件之前需要進行身份驗證。
mail.smtp.starttls.enable屬性啟用 STARTTLS,它會將初始的明文連線升級為加密的 TLS 通道。這可以確保憑證和電子郵件內容在傳輸過程中受到保護。
最後,將mail.smtp.auth.mechanisms設定為LOGIN 。這將告訴 JavaMail 使用LOGIN作為驗證機制,使用使用者名稱和密碼。
3.2 建立郵件會話
接下來,我們需要建立一個郵件會話。此會話包含用於傳送電子郵件的 SMTP 設定和驗證詳細資訊:
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Jakarta Mail 中的session用於建立與郵件伺服器通訊所需的上下文配置。透過Session.getInstance ,我們可以使用 SMTP 屬性建立一個新會話。
我們傳遞的第二個參數是Authenticator的匿名子類別。 JavaMail 不會將憑證硬編碼到程式碼中,而是僅在伺服器於 SMTP 握手期間請求憑證時才向Authenticator請求憑證。
接下來,當 Exchange Server 傳送驗證質詢時,JavaMail 會呼叫getPasswordAuthentication方法來檢索憑證。
3.3 撰寫電子郵件
現在讓我們看看如何透過程式設計方式撰寫和發送電子郵件:
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(FROM_ADDRESS));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
message.setSubject(subject);
message.setText(body);
session物件包含所有 SMTP 配置。它會建立MimeMessage對象,該對象表示要傳送的電子郵件訊息。它包含主題、正文、收件者和郵件頭。
` setFrom()方法用來設定寄件者的電子郵件地址。該地址將顯示在電子郵件發送時的from欄位中。此位址必須與 Exchange 伺服器中設定的電子郵件帳戶一致。
setRecipients()方法設定收件者的電子郵件地址,郵件必須傳送到該位址。這裡, Message.RecipientType.TO指定主要收件者及其網際網路位址, parse會將收件者字串安全地轉換為一個或多個有效的電子郵件地址物件。
setSubject()方法設定電子郵件主題, setText()方法將電子郵件正文內容設定為純文字。
3.4 發送電子郵件
讓我們編寫程式碼向收件者發送電子郵件:
Transport.send(message);
System.out.println("Email sent successfully");
Transport.send(message)語句將完整建置的電子郵件傳送給 JavaMail 的 SMTP 傳輸層。這會連接到 SMTP 伺服器並發送郵件。如果沒有出現任何異常,郵件將會成功發送。
3.5. SMTP通訊的調試和日誌記錄
我們通常依賴異常訊息來確定故障原因。然而,有時僅憑異常訊息很難確定問題所在。借助 Jakarta Mail,我們可以記錄完整的 SMTP 會話、TLS 協商和伺服器回應。啟用 Jakarta Debug 日誌記錄即可查看這些資訊:
session.setDebug(true);
啟用偵錯日誌後,JavaMail 會將詳細的協定級資訊列印到控制台。輸出內容包括客戶端發送的 SMTP 命令和 Exchange 伺服器傳回的回應。這些日誌有助於診斷身份驗證失敗、不支援的身份驗證機制以及與 TLS 相關的問題。
需要注意的是,這些日誌也會列印出敏感訊息,例如電子郵件地址和身份驗證流程。因此,我們應該僅在開發或故障排除期間啟用此功能,並在生產環境中停用它。
4. 常見問題
在本節中,我們將探討開發過程中遇到的一些常見問題。
4.1. 身份驗證失敗
身份驗證失敗通常會導致郵件無法傳送。當 Exchange 伺服器拒絕傳送應用程式提供的憑證時,就會發生這種情況。
若要解決此問題,管理員必須在郵件伺服器上啟用 SMTP 驗證,並確保所使用的憑證有效。
此外,管理員需要確認已選擇正確的 SMTP 連接埠和加密方法。使用錯誤的連接埠或不匹配的安全設定(例如 SSL/TLS 或 STARTTLS)可能會導致身份驗證錯誤。
4.2 連線錯誤
當我們的應用程式無法與 SMTP 伺服器建立有效連線時,就會發生連線錯誤。這通常是由不正確的 SMTP 屬性或網路相關配置引起的。
要解決此問題,我們必須確保 SMTP 伺服器位址和連接埠配置正確,並且發送系統可以存取該伺服器。我們還需要驗證防火牆規則或網路安全政策是否阻止了出站 SMTP 流量。
伺服器臨時故障或 SMTP 服務停用也可能導致連線失敗,因此確認伺服器可用性非常重要。
4.3. TLS 和憑證問題
TLS憑證相關問題也可能導致郵件投遞失敗。 JVM預設不信任組織機構的自簽名憑證。即使SMTP主機和憑證正確,JavaMail也可能會拋出SSL或TLS相關的例外。
一種解決方案是將 Exchange 伺服器的憑證匯入到 JVM 的預設信任庫中。另一種方法是使用包含所需憑證的自訂信任庫。
我們也可以停用證書驗證。但是,這樣做會顯著降低安全性,並可能洩漏敏感資料。
5. SMTP 與 Microsoft Graph API
SMTP 提供了一種高效的電子郵件發送方式,只需簡單的使用者名稱和密碼驗證即可,因此非常適合本地部署的 Exchange 伺服器和舊系統。但它通常也存在一些限制。
某些組織機構對 SMTP 存取進行了限製或停用。在這種情況下,我們無法使用 JavaMail。我們必須使用其他替代方案,例如 Microsoft Graph API 或 Exchange Web Services。
Microsoft Graph API 使用基於 OAuth 的身份驗證,是與 Exchange Server 通訊的建議方式,因為它能提高安全性、提供更精細的控制,並支援存取更進階的功能。雖然它們更複雜,但 Exchange Online 官方支援。
6. 結論
在本教程中,我們已經了解到,使用 Microsoft Exchange Server 以程式設計方式傳送電子郵件與使用任何 SMTP 伺服器傳送電子郵件的方式類似。我們也探討了一些在發送電子郵件時可能遇到的常見問題以及解決方法。雖然管理員通常對本機 Exchange 伺服器和舊系統使用 SMTP 訪問,但他們在基於雲端的 Exchange Online 部署中會使用 Microsoft Graph API 以提高安全性。
透過正確的配置和設置,我們可以使用 MS Exchange 伺服器無縫發送電子郵件。
與往常一樣,範例的原始程式碼可以在 GitHub 上找到。