JavaMail (javax.mail) 是 Java 平台發送電子郵件的標準 API。本文提供可直接落地的完整工具類,支援純文字、HTML 內容與多附件發送。
Session:郵件會話,保有伺服器設定與認證資訊Message (MimeMessage):郵件主體,含主旨、寄件者、收件者、內容Transport:傳輸協定實作(SMTP),負責實際發送Authenticator:SMTP 認證(帳號/密碼)MimeMultipart + MimeBodyPart:多部分內容(HTML + 附件)容器package com.lgf.email;
import javax.activation.*;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
public class EmailSender {
// ===== 設定區 =====
private static final String SMTP_HOST = "smtp.gmail.com";
private static final String USERNAME = "your_email@gmail.com";
private static final String PASSWORD = "your_app_password"; // 應用程式密碼
private static final String FROM = USERNAME;
private static final String FROM_NAME = "系統通知";
// ===== 核心發送邏輯 =====
private Session createSession() {
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_HOST);
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true"); // TLS 加密
return Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(USERNAME, PASSWORD);
}
});
}
/** 發送純文字郵件 */
public void sendText(String to, String subject, String content) throws MessagingException {
MimeMessage msg = createBaseMessage(to, subject);
msg.setText(content, "utf-8");
Transport.send(msg);
}
/** 發送 HTML 郵件 */
public void sendHtml(String to, String subject, String htmlContent) throws MessagingException {
MimeMessage msg = createBaseMessage(to, subject);
msg.setContent(htmlContent, "text/html;charset=utf-8");
Transport.send(msg);
}
/** 發送帶附件郵件 */
public void sendWithAttachments(String to, String subject, String htmlContent, List<File> attachments) throws MessagingException {
MimeMessage msg = createBaseMessage(to, subject);
// 建立 Multipart 容器
Multipart multipart = new MimeMultipart();
// 1. HTML 內容部分
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlContent, "text/html;charset=utf-8");
multipart.addBodyPart(htmlPart);
// 2. 附件部分
for (File file : attachments) {
MimeBodyPart attachPart = new MimeBodyPart();
DataSource source = new FileDataSource(file);
attachPart.setDataHandler(new DataHandler(source));
// 解決中文檔名編碼問題
attachPart.setFileName(MimeUtility.encodeText(file.getName()));
multipart.addBodyPart(attachPart);
}
msg.setContent(multipart);
Transport.send(msg);
}
private MimeMessage createBaseMessage(String to, String subject) throws MessagingException {
Session session = createSession();
session.setDebug(true); // 開發期開啟除錯
MimeMessage msg = new MimeMessage(session);
msg.setSubject(subject, "utf-8");
msg.setFrom(new InternetAddress(FROM, FROM_NAME, "utf-8"));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
msg.setSentDate(new Date());
return msg;
}
// ===== 測試主程式 =====
public static void main(String[] args) {
EmailSender sender = new EmailSender();
try {
// sender.sendText("target@example.com", "測試純文字", "Hello JavaMail!");
// sender.sendHtml("target@example.com", "測試 HTML", "<h1 style='color:red'>HTML 郵件</h1>");
sender.sendWithAttachments(
"target@example.com",
"測試附件",
"<p>請查收附件</p>",
Arrays.asList(new File("report.pdf"), new File("data.xlsx"))
);
System.out.println("發送成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
| 問題 | 解決方案 |
|---|---|
| Gmail/Outlook 拒絕登入 | 開啟「兩步驟驗證」並產生「應用程式密碼」,不可用主密碼 |
| 中文附件檔名亂碼 | MimeUtility.encodeText(fileName) 編碼檔名 |
| HTML 圖片不顯示 | 使用 CID 內嵌圖片:<img src="cid:imageId"> + htmlPart.addRelatedPart(imagePart) |
| 大量發送效能 | 復用 Session、使用連線池、非同步發送佇列 |
| 編碼問題 | 統一指定 utf-8:setSubject(sub, "utf-8")、setText(text, "utf-8") |
@ConfigurationProperties(prefix = "mail")
@Data
public class MailProperties {
private String host;
private int port;
private String username;
private String password;
private String from;
}
@Service
@RequiredArgsConstructor
public class MailService {
private final MailProperties props;
private final JavaMailSender mailSender; // Spring Boot 自動配置
public void sendHtml(String to, String subject, String html) {
MimeMessage msg = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8");
helper.setFrom(props.getFrom());
helper.setTo(to);
helper.setSubject(subject);
helper.setText(html, true); // true = HTML
mailSender.send(msg);
}
}
JavaMail 功能強大但 API 底層,實務建議封裝為領域服務(EmailService),搭配 Spring Boot JavaMailSender 簡化配置。重點掌握 MimeMultipart 組合 HTML 與附件、中文編碼處理、SMTP 認證與 TLS 設定,即可覆蓋 95% 發送郵件場景。