MailSenderUtils 是一個用於發送電子郵件的工具類別。此類別設計為 Spring 元件,提供多種郵件發送方式,支援 HTML 內容、多附件、多收件人等功能,特別適合在企業應用程式中使用。
// 發送簡單郵件
List<String> recipients = Arrays.asList("user@example.com");
String subject = "測試郵件";
String content = "這是一封測試郵件";
String result = mailSenderUtils.sendMailContent(recipients, subject, content);
// 發送 HTML 格式郵件
String htmlContent = "<h1>歡迎</h1><p>這是一封 HTML 格式的郵件</p>";
mailSenderUtils.sendMailContent(recipients, "HTML 測試", htmlContent);
// 發送帶附件的郵件
File attachment = new File("report.pdf");
String result = mailSenderUtils.sendMailWithFiles(
recipients,
"附件測試",
"請查收附件",
attachment
);
// 發送多個附件
File file1 = new File("doc1.pdf");
File file2 = new File("doc2.xlsx");
mailSenderUtils.sendMailWithFiles(
recipients,
"多附件測試",
"請查收附件",
file1, file2
);
// 設定完整郵件資訊
MailMessageModel message = new MailMessageModel();
message.setListRecipients(Arrays.asList("user1@example.com"));
message.setListCCAddress(Arrays.asList("cc@example.com"));
message.setListBccAddress(Arrays.asList("bcc@example.com"));
message.setSubject("完整測試");
message.setContentBody("這是一封完整的測試郵件");
mailSenderUtils.sendMailMessage(message);
// 自訂寄件者
MailMessageModel message = new MailMessageModel();
message.setSenderName("系統管理員");
message.setSenderAddress("admin@example.com");
mailSenderUtils.sendMailMessage(message);
// 使用指定的 SMTP 伺服器
Session session = mailSenderUtils.getJavaMailSession("smtp.example.com", 25);
// 使用 JNDI 資源
Session session = mailSenderUtils.getJbossMailResourceSession("java:jboss/mail/Default");
List<String> recipients = new ArrayList<>();
recipients.add("user@example.com");
String subject = "測試郵件";
String content = "<h1>這是一封測試郵件</h1><p>使用 HTML 格式</p>";
MailSenderUtils mailUtils = new MailSenderUtils();
String result = mailUtils.sendMailContent(recipients, subject, content);
List<String> recipients = new ArrayList<>();
recipients.add("user@example.com");
String subject = "含附件的測試郵件";
String content = "請查看附件";
File attachment = new File("document.pdf");
MailSenderUtils mailUtils = new MailSenderUtils();
String result = mailUtils.sendMailWithFiles(recipients, subject, content, attachment);
MailMessageModel mailMessage = new MailMessageModel();
mailMessage.setSenderName("系統管理員");
mailMessage.setSenderAddress("admin@example.com");
mailMessage.setListRecipients(Arrays.asList("user1@example.com"));
mailMessage.setListCCAddress(Arrays.asList("user2@example.com"));
mailMessage.setSubject("重要通知");
mailMessage.setContentBody("<h1>系統更新通知</h1>");
MailSenderUtils mailUtils = new MailSenderUtils();
String result = mailUtils.sendMailMessage(mailMessage);
需要在系統中設定以下環境變數:
SMTP_SERVER: SMTP 伺服器位址SMTP_PORT: SMTP 伺服器埠號MAIL_RESOURCE_JNDI: JNDI 資源名稱(選用)MAIL_SENDER_ADDRESS: 預設寄件者地址MAIL_SENDER_NAME: 預設寄件者名稱java.net.preferIPv4Stack=true)工具類會在以下情況回傳錯誤訊息:
以下測試範例示範 MailSenderUtils 的常見測試思路:
@Test
void testBuildMailMessageModel() {
MailMessageModel m = new MailMessageModel();
m.setSenderAddress("admin@example.com");
m.setListRecipients(Arrays.asList("user@example.com"));
m.setSubject("測試");
m.setContentBody("內容");
assertEquals("admin@example.com", m.getSenderAddress());
assertFalse(m.getListRecipients().isEmpty());
}
@Test
void testSendMailContentWithMock() throws Exception {
// 建議在單元測試中使用 mock(例如 Mockito)來模擬實際傳送
MailSenderUtils mail = Mockito.spy(new MailSenderUtils());
List<String> recipients = Arrays.asList("user@example.com");
// 假設 sendMailContent 會回傳 "OK" 或錯誤訊息
Mockito.doReturn("OK").when(mail).sendMailContent(recipients, "sub", "body");
String result = mail.sendMailContent(recipients, "sub", "body");
assertEquals("OK", result);
}
@Test
void testGetJavaMailSessionError() {
// 測試取得 session 時發生錯誤的處理(視實作回傳方式)
assertThrows(Exception.class, () -> {
MailSenderUtils.getJavaMailSession("invalid.host", -1);
});
}
package tw.lewishome.webapp.base.utility.common;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.lang3.StringUtils;
import jakarta.activation.CommandMap;
import jakarta.activation.DataHandler;
import jakarta.activation.MailcapCommandMap;
import jakarta.activation.MimetypesFileTypeMap;
import jakarta.mail.Address;
import jakarta.mail.Multipart;
import jakarta.mail.Part;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.internet.MimeUtility;
import jakarta.mail.util.ByteArrayDataSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import tw.lewishome.webapp.GlobalConstants;
/**
*
* MailSenderUtils 是一個用於發送電子郵件的工具類,支援多種寄信方式,包括透過 JNDI 資源或直接指定 SMTP 主機與埠號。
* 此工具類可處理郵件主旨、內容、收件人、CC、BCC 及附件,並支援自訂寄件人名稱與編碼格式。
*
*
*
* 主要功能:
* <ul>
* <li>發送含附件的電子郵件</li>
* <li>支援 HTML 格式郵件內容</li>
* <li>可設定收件人、CC、BCC、寄件人名稱與地址</li>
* <li>自動取得系統參數設定的 SMTP 主機、埠號與資源</li>
* <li>支援 JNDI 方式取得郵件 Session,或直接建立 JavaMail Session</li>
* <li>自動判斷附件檔案型態</li>
* </ul>
*
*
*
* 使用方式:
* <ul>
* <li>可透過 sendMailMessage(MailMessageModel) 傳送自訂郵件物件</li>
* <li>可使用 sendMailWithFiles(...) 傳送含附件的郵件</li>
* <li>可使用 sendMailContent(...) 傳送純文字或 HTML 內容郵件</li>
* </ul>
*
*
*
* 注意事項:
* <ul>
* <li>若 SMTP 主機或資源未設定,將使用預設值</li>
* <li>附件需以 InputStream 方式傳入,並自動判斷檔案型態</li>
* <li>支援多收件人、CC、BCC</li>
* <li>郵件內容預設編碼為 UTF-8</li>
* <li>寄信失敗時會回傳錯誤訊息,並記錄 log</li>
* </ul>
*
*
*
* 主要成員說明:
* <ul>
* <li>sendMailMessage:以 MailMessageModel 物件發送郵件</li>
* <li>sendMailWithFiles:以收件人、主旨、內容及檔案清單發送郵件</li>
* <li>sendMailContent:以收件人、主旨、內容發送郵件(無附件)</li>
* <li>getSession:自動取得郵件 Session,優先使用 JNDI 資源</li>
* <li>getJavaMailSession:直接建立 JavaMail Session</li>
* <li>getJbossMailResourceSession:透過 JNDI 取得郵件 Session</li>
* <li>MailMessageModel:郵件內容物件,包含收件人、主旨、內容、附件等</li>
* </ul>
*
*
*
* 適用場景:
* <ul>
* <li>Spring Boot 或 JBoss 等 Java Web 應用程式發送郵件通知</li>
* <li>需支援多附件、多收件人、CC、BCC 的郵件發送需求</li>
* <li>需自訂郵件主旨、內容格式(HTML)、寄件人資訊</li>
* </ul>
*
*
* @author Lewis
* @version 1.0
* @since 2024-06
*/
@Slf4j
public class MailSenderUtils {
/**
* Fix for javadoc warning :
* use of default constructor, which does not provide a comment
* Constructs a new MailSenderUtils instance.
* This is the default constructor, implicitly provided by the compiler
* and can be used to create a new instance of the class.
*
* This constructor does not require any parameters and can be called without
* any arguments.
*/
public MailSenderUtils() {
// Constructor body (can be empty)
}
/**
* send Email Message with mailMessage Object
*
* @param mailMessageModel MailMessage 物件
* @return String SendMail執行訊息
*/
public String sendMailMessage(MailMessageModel mailMessageModel) {
try {
Session session = getSession();
if (session == null) {
return "get Mail Session error.";
}
// create a message
MimeMessage mimeMessage = new MimeMessage(session);
String mailSenderEmail = mailMessageModel.getSenderAddress();
if (StringUtils.isBlank(mailSenderEmail)) {
mailSenderEmail = GlobalConstants.ENV_VAR.get("MAIL_SENDER_ADDRESS");
}
String mailSenderName = mailMessageModel.getSenderName();
if (StringUtils.isBlank(mailSenderName)) {
mailSenderName = GlobalConstants.ENV_VAR.get("MAIL_SENDER_NAME");
}
Address from = new InternetAddress(mailSenderEmail, mailSenderName);
mimeMessage.setFrom(from);
String contentTestString = "";
List<String> mergedListRecipients = new ArrayList<>();
if (mailMessageModel.getListRecipients()!= null) {
mergedListRecipients.addAll(mailMessageModel.getListRecipients());
}
if (mailMessageModel.getListCCAddress()!= null) {
mergedListRecipients.addAll(mailMessageModel.getListCCAddress());
}
if (mailMessageModel.getListBccAddress()!= null) {
mergedListRecipients.addAll(mailMessageModel.getListBccAddress());
}
if (isAllEmailInvaild(mergedListRecipients)) {
return "All recipients are invalid email address : sendMailMessage Failed.";
}
// Recipients
Address[] arrayAddressTO = getInternetAddress(mailMessageModel.getListRecipients());
mimeMessage.setRecipients(jakarta.mail.Message.RecipientType.TO, arrayAddressTO);
if (mailMessageModel.getListCCAddress() != null) {
Address[] arrayAddressCC = getInternetAddress(mailMessageModel.getListCCAddress());
mimeMessage.setRecipients(jakarta.mail.Message.RecipientType.CC, arrayAddressCC);
}
if (mailMessageModel.getListBccAddress() != null) {
Address[] arrayAddressBCC = getInternetAddress(mailMessageModel.getListBccAddress());
mimeMessage.setRecipients(jakarta.mail.Message.RecipientType.BCC, arrayAddressBCC);
}
// subject
// mimeMessage.setSubject(MailMessageModel.getSubject());
mimeMessage.setSubject(
MimeUtility.encodeText(mailMessageModel.getSubject(), GlobalConstants.DEFAULT_CHAR_SET, "B"));
// create and fill the first message part
MimeBodyPart mimeBodyPart = new MimeBodyPart();
String contentBody = mailMessageModel.getContentBody();
String contentMimeType = "text/html; charset=" + GlobalConstants.DEFAULT_CHAR_SET;
mimeBodyPart.setContent(contentTestString + contentBody, contentMimeType);
// create the Multipart and add its parts to it
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
// add the Multipart to the message
mimeMessage.setContent(multipart);
MailcapCommandMap mailcapCommandMap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mailcapCommandMap.addMailcap("text/html; x-java-content-handler=com.sun.mail.handlers.text_html");
mailcapCommandMap.addMailcap("text/xml; x-java-content-handler=com.sun.mail.handlers.text_xml");
mailcapCommandMap.addMailcap("text/plain; x-java-content-handler=com.sun.mail.handlers.text_plain");
mailcapCommandMap.addMailcap("multipart/*; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mailcapCommandMap.addMailcap("message/rfc822; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mailcapCommandMap);
List<MimeBodyPart> listMimeBodyPart = getAttached(mailMessageModel.getListAttachment());
for (int i = 0; i < listMimeBodyPart.size(); i++) {
multipart.addBodyPart(listMimeBodyPart.get(i));
}
Transport.send(mimeMessage);
} catch (Exception ex) {
ex.printStackTrace();
return "Mail Sent Failed.";
}
return "Mail Sent Successfully.";
}
/**
* send Email message with parm without attached
*
* @param recipients ArrayList for recipients
* @param subject Subject String
* @param contentBody Content String
* @return String
*/
public String sendMailContent(List<String> recipients, String subject, String contentBody) {
log.info("sendMailContent:" + recipients.toString());
MailMessageModel mailMessage = new MailMessageModel();
mailMessage.setListRecipients(recipients);
mailMessage.setSubject(subject);
mailMessage.setContentBody(contentBody);
List<MailMessageModel.Attachment> listAttachment = new ArrayList<>();
mailMessage.setListAttachment(listAttachment);
return sendMailMessage(mailMessage);
}
/**
* send Email message with parm
*
* @param recipients 收件者 Email List
* @param subject Subject String (主旨)
* @param contentBody Context String (內文)
* @param listFiles Attached File... ( 附件檔案)
* @return String SendMail 執行訊息
*/
public String sendMailWithFiles(List<String> recipients, String subject, String contentBody, File... listFiles) {
MailMessageModel mailMessage = new MailMessageModel();
mailMessage.setListRecipients(recipients);
mailMessage.setSubject(subject);
mailMessage.setContentBody(contentBody);
List<MailMessageModel.Attachment> listAttachment = new ArrayList<>();
for (File oneFile : listFiles) {
try (InputStream fileInputStream = new FileInputStream(oneFile)) {
MailMessageModel.Attachment oneAttachment = new MailMessageModel.Attachment();
oneAttachment.setFileName(oneFile.getName());
oneAttachment.setInputStream(fileInputStream);
listAttachment.add(oneAttachment);
} catch (Exception ex) {
ex.printStackTrace();
}
}
mailMessage.setListAttachment(listAttachment);
return sendMailMessage(mailMessage);
}
/**
* get Mail Session
*
* @return Session 取得 Mail Session
*/
public Session getSession() {
Session rtnSession = null;
String smtpServer = GlobalConstants.ENV_VAR.get("SMTP_SERVER");
String smtpPort = GlobalConstants.ENV_VAR.get("SMTP_PORT");
String mailResourceJndi = GlobalConstants.ENV_VAR.get("MAIL_RESOURCE_JNDI");
rtnSession = getJbossMailResourceSession(mailResourceJndi);
if (rtnSession == null) {
int intSmtpPort = Integer.parseInt(smtpPort);
rtnSession = getJavaMailSession(smtpServer, intSmtpPort);
}
return rtnSession;
}
private List<MimeBodyPart> getAttached(List<MailMessageModel.Attachment> listAttachment) throws IOException {
List<MimeBodyPart> listAttachmentPart = new ArrayList<>();
String oneFileName = "";
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
for (MailMessageModel.Attachment oneAttachment : listAttachment) {
MimeBodyPart attachmentPart = new MimeBodyPart();
oneFileName = oneAttachment.getFileName();
String oneFileType = oneAttachment.getFileType();
if ("".equalsIgnoreCase(oneFileType)) {
oneFileType = fileTypeMap.getContentType(oneFileName);
}
try (InputStream oneInputStream = oneAttachment.getInputStream()) {
// InputStream oneInputStream = oneAttachment.getInputStream();
ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(oneInputStream, oneFileType);
attachmentPart.setFileName(MimeUtility.encodeText(oneFileName, GlobalConstants.DEFAULT_CHAR_SET, "B"));
attachmentPart.setDataHandler(new DataHandler(byteArrayDataSource));
attachmentPart.setDisposition(Part.ATTACHMENT);
listAttachmentPart.add(attachmentPart);
} catch (Exception ex) {
throw new IOException("attachmentPart IOException " + oneFileName);
}
}
return listAttachmentPart;
}
private Address[] getInternetAddress(List<String> listAddress) throws AddressException {
Address[] arrayAddress = new InternetAddress[listAddress.size()];
try {
for (int i = 0; i < listAddress.size(); i++) {
arrayAddress[i] = new InternetAddress(listAddress.get(i));
}
} catch (Exception ex) {
throw new AddressException("Internet Address AddressException");
}
return arrayAddress;
}
private Boolean isAllEmailInvaild(List<String> listAddress) {
boolean isAllInvalidRecipients = true;
for (String oneRecipient : listAddress) {
if (StringUtils.isNotBlank(oneRecipient)) {
if (CommUtils.isValidEmailAddress(oneRecipient)) {
isAllInvalidRecipients = false;
break;
}
}
}
return isAllInvalidRecipients;
}
/**
* get Java Mail Session with host port
*
* @param smtpHost String SMTP Host name or IP
* @param smtpPort int SMTP port Number
* @return Session 取得 Mail Session
*/
public Session getJavaMailSession(String smtpHost, int smtpPort) {
System.setProperty("mail.mime.splitLongParameters", "false");
System.setProperty("java.net.preferIPv4Stack", "true"); // 以IPv4方式寄信
try {
Boolean pingMailServer = NetUtils.checkSocket(smtpHost, smtpPort, 100);
if (Boolean.FALSE.equals(pingMailServer)) {
log.info("Ping SMTP Server Error." + smtpHost + ":" + smtpPort);
return null;
}
} catch (Exception ex) {
ex.printStackTrace();
log.error("Ping SMTP Server Exception." + smtpHost + ":" + smtpPort);
return null;
}
// for Spring Boot mail session
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", smtpPort);
Session mailSession = Session.getInstance(props);
if (mailSession == null) {
log.info("Get Jboss Mail Session Failed. " + smtpHost + ":" + smtpPort);
return null;
}
return mailSession;
}
/**
* get Java Mail Session with JNDI
*
* @param mailResource String(JNDI )
* @return Session 取得 Mail Session
*/
public Session getJbossMailResourceSession(String mailResource) {
System.setProperty("mail.mime.splitlongparameters", "false");
System.setProperty("java.net.preferIPv4Stack", "true"); // 以IPv4方式寄信
try {
// get mail session from container (Jboss or Liberty)
// InitialContext initialContext = new InitialContext();
// Session mailSession = (Session) initialContext.lookup(mailResource);
if (StringUtils.isNotBlank(mailResource)) {
Session mailSession = (Session) new InitialContext().lookup(mailResource);
log.info("Get Mail Resource " + mailResource);
return mailSession;
}
} catch (NamingException ex) {
ex.printStackTrace();
log.info("Get Jboss Mail Resource Failed. " + mailResource);
}
return null;
}
/**
* SMTP MAIL Message 物件
*
* @author Lewis
**/
@Data
public static class MailMessageModel implements Serializable {
/**
* Fix for javadoc warning :
* use of default constructor, which does not provide a comment
*
* Constructs a new MailMessageModel instance.
* This is the default constructor, implicitly provided by the compiler
* if no other constructors are defined.
*/
public MailMessageModel() {
// Constructor body (can be empty)
}
/** serialVersionUID */
private static final long serialVersionUID = 1L;
/** 寄件者Email */
private String senderAddress = ""; // sender email address
/** 寄件者名稱 */
private String senderName = ""; // sender name
/** 收件者Email List */
private List<String> listRecipients; // list of recipient
/** CC收件者Email List */
private List<String> listCCAddress; // list of cc
/** BCC收件者Email List */
private List<String> listBccAddress; // list of bcc
/** Email主旨 */
private String subject = ""; // mail subject
/** Email內容 */
private String contentBody = ""; // main content body
/** Email附件檔案 */
private List<Attachment> listAttachment; //
/**
* SMTP MAIL Message 附件明細資料
*
* @author Lewis
**/
@Data
public static class Attachment implements Serializable {
/**
* Fix for javadoc warning :
* use of default constructor, which does not provide a comment
*
* Constructs a new Attachment instance.
* This is the default constructor, implicitly provided by the compiler
* if no other constructors are defined.
*/
public Attachment() {
// Constructor body (can be empty)
}
/** serialVersionUID */
private static final long serialVersionUID = 1L;
/** Email檔案名稱 */
private String fileName = "";
/** Email檔案類型 */
private String fileType = "";
/** Email檔案 (InputStream) */
private InputStream inputStream;
}
}
}
單元測試程式碼 MailSenderUtilsTest.java
package tw.lewishome.webapp.base.utility.common;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetup;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import tw.lewishome.webapp.GlobalConstants;
import tw.lewishome.webapp.base.utility.common.MailSenderUtils.MailMessageModel;
/**
* MailSenderUtils 的單元測試類別
*/
class MailSenderUtilsTest {
private MailSenderUtils mailSender;
private GreenMail greenMail;
private static final String TEST_SMTP_HOST = "127.0.0.1";
private static final int TEST_SMTP_PORT = 3025; // GreenMail 預設 SMTP 埠號
private static final String TEST_SENDER = "sender@test.com";
private static final String TEST_RECIPIENT = "recipient@test.com";
@TempDir
Path tempDir;
@BeforeEach
void setUp() {
// 啟動 GreenMail
ServerSetup serverSetup = new ServerSetup(TEST_SMTP_PORT, TEST_SMTP_HOST, ServerSetup.PROTOCOL_SMTP);
greenMail = new GreenMail(serverSetup);
greenMail.start();
System.out.println("GreenMail started on " + serverSetup.getBindAddress() + ":" + serverSetup.getPort());
mailSender = new MailSenderUtils();
// 設定測試用的環境變數
GlobalConstants.ENV_VAR.put("SMTP_SERVER", TEST_SMTP_HOST);
GlobalConstants.ENV_VAR.put("SMTP_PORT", String.valueOf(TEST_SMTP_PORT));
GlobalConstants.ENV_VAR.put("MAIL_SENDER_ADDRESS", TEST_SENDER);
GlobalConstants.ENV_VAR.put("MAIL_SENDER_NAME", "Test Sender");
}
@AfterEach
void tearDown() {
// 停止 GreenMail 伺服器
if (greenMail != null) {
greenMail.stop();
}
// 清理環境變數
GlobalConstants.ENV_VAR.remove("SMTP_SERVER");
GlobalConstants.ENV_VAR.remove("SMTP_PORT");
GlobalConstants.ENV_VAR.remove("MAIL_SENDER_ADDRESS");
GlobalConstants.ENV_VAR.remove("MAIL_SENDER_NAME");
}
@Test
void testSendMailContent() throws MessagingException {
// 準備測試數據
List<String> recipients = Arrays.asList(TEST_RECIPIENT);
String subject = "Test Subject";
String content = "<html><body>Test Content</body></html>";
// 執行測試
String result = mailSender.sendMailContent(recipients, subject, content);
// 驗證結果
assertEquals("Mail Sent Successfully.", result);
// 驗證郵件內容
MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
assertEquals(1, receivedMessages.length);
MimeMessage receivedMessage = receivedMessages[0];
assertEquals(subject, receivedMessage.getSubject());
assertTrue(GreenMailUtil.getBody(receivedMessage).contains("Test Content"));
assertEquals(TEST_RECIPIENT, receivedMessage.getAllRecipients()[0].toString());
}
@Test
void testSendMailWithFiles() throws IOException {
// 準備測試檔案
File testFile = tempDir.resolve("test.txt").toFile();
FileUtils.stringListToFile(Arrays.asList("Test content"), testFile.getAbsolutePath());
// 準備測試數據
List<String> recipients = Arrays.asList(TEST_RECIPIENT);
String subject = "Test Subject with Attachment";
String content = "Test Content with Attachment";
// 執行測試
String result = mailSender.sendMailWithFiles(recipients, subject, content, testFile);
// 驗證結果
assertNotNull(result);
// 清理測試檔案
FileUtils.deleteFile(testFile.getAbsolutePath());
}
@Test
void testMailMessageModel() throws MessagingException, IOException {
// 建立完整的郵件物件
mailSender = new MailSenderUtils();
MailMessageModel mailMessage = new MailSenderUtils.MailMessageModel();
mailMessage.setSenderAddress(TEST_SENDER);
mailMessage.setSenderName("Test Sender");
mailMessage.setListRecipients(Arrays.asList(TEST_RECIPIENT));
mailMessage.setListCCAddress(Arrays.asList("cc@test.com"));
mailMessage.setListBccAddress(Arrays.asList("bcc@test.com"));
mailMessage.setSubject("Test Complete Message");
mailMessage.setContentBody("Test Complete Content");
// 建立並添加附件
File testFile = tempDir.resolve("test.txt").toFile();
FileUtils.stringListToFile(Arrays.asList("Test attachment content"), testFile.getAbsolutePath());
List<MailMessageModel.Attachment> attachments = new ArrayList<>();
MailMessageModel.Attachment attachment = new MailMessageModel.Attachment();
attachment.setFileName("test.txt");
attachment.setFileType("text/plain");
// 設定附件的 InputStream
attachment.setInputStream(java.nio.file.Files.newInputStream(testFile.toPath()));
attachments.add(attachment);
mailMessage.setListAttachment(attachments);
// 執行測試
String result = mailSender.sendMailMessage(mailMessage);
// 驗證結果
assertEquals("Mail Sent Successfully.", result);
// 驗證郵件內容
MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
for (int i = 0; i < receivedMessages.length; i++) {
System.out.println("Received message " + i + " subject: " + receivedMessages[i].getSubject());
}
// 三個receiver
assertEquals(3, receivedMessages.length);
MimeMessage receivedMessage = receivedMessages[0];
assertEquals("Test Complete Message", receivedMessage.getSubject());
assertTrue(GreenMailUtil.getBody(receivedMessage).contains("Test Complete Content"));
// 驗證收件人
assertEquals(TEST_RECIPIENT, receivedMessage.getAllRecipients()[0].toString());
// 清理測試檔案
FileUtils.deleteFile(testFile.getAbsolutePath());
}
@Test
void testGetJavaMailSession() {
// 測試取得 JavaMail Session
Session session = mailSender.getJavaMailSession(TEST_SMTP_HOST, TEST_SMTP_PORT);
// 因為測試環境可能無法連接 SMTP,所以這裡可能為 null
if (session != null) {
assertNotNull(session.getProperties());
assertEquals(TEST_SMTP_HOST, session.getProperties().getProperty("mail.smtp.host"));
}
@SuppressWarnings("null")
String sessionSmtpPort = session.getProperties().getProperty("mail.smtp.port");
// 因為測試環境可能無法連接 SMTP,所以這裡可能為 null
if (sessionSmtpPort != null) {
assertEquals(String.valueOf(TEST_SMTP_PORT), sessionSmtpPort);
}
}
@Test
void testGetJbossMailResourceSession() {
// 測試 JNDI 資源
String testJndi = "java:jboss/mail/Default";
Session session = mailSender.getJbossMailResourceSession(testJndi);
// 在測試環境中,因為沒有實際的 JNDI 資源,預期會返回 null
assertNull(session);
}
@Test
void testGetSession() {
// 測試預設的 Session 取得方法
Session session = mailSender.getSession();
// 在測試環境中可能返回 null(因為無法連接 SMTP 伺服器)
if (session != null) {
Properties props = session.getProperties();
assertNotNull(props);
assertEquals(TEST_SMTP_HOST, props.getProperty("mail.smtp.host"));
}
}
@Test
void testSendMailWithInvalidRecipient() {
// 測試無效的收件人地址
List<String> recipients = Arrays.asList("invalid-email");
String subject = "Test Subject";
String content = "Test Content";
String result = mailSender.sendMailContent(recipients, subject, content);
// 預期會回傳錯誤訊息
assertTrue(result.contains("Failed") || result.contains("error"));
}
@Test
void testSendMailWithEmptyContent() {
// 測試空內容
List<String> recipients = Arrays.asList(TEST_RECIPIENT);
String subject = "Test Subject";
String content = "";
String result = mailSender.sendMailContent(recipients, subject, content);
assertNotNull(result);
}
@Test
void testSendMailWithLargeAttachment() throws IOException {
// 準備大型測試檔案
File largeFile = tempDir.resolve("large.txt").toFile();
List<String> largeContent = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
largeContent.add("Test content line " + i);
}
FileUtils.stringListToFile(largeContent, largeFile.getAbsolutePath());
// 執行測試
List<String> recipients = Arrays.asList(TEST_RECIPIENT);
String subject = "Test Large Attachment";
String content = "Test Content with Large Attachment";
String result = mailSender.sendMailWithFiles(recipients, subject, content, largeFile);
// 驗證結果
assertNotNull(result);
// 清理測試檔案
FileUtils.deleteFile(largeFile.getAbsolutePath());
}
@Test
void testSendMailWithMultipleRecipients() {
// 測試多個收件人
List<String> recipients = Arrays.asList(
"recipient1@test.com",
"recipient2@test.com",
"recipient3@test.com");
String subject = "Test Multiple Recipients";
String content = "Test Content";
String result = mailSender.sendMailContent(recipients, subject, content);
assertNotNull(result);
}
}