<!-- Maven -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>2.0.1</version>
</dependency>
<!-- 或舊版 javax.mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
import jakarta.mail.*;
import jakarta.mail.internet.*;
import java.util.Properties;
import java.util.Date;
public class HtmlMailSender {
private final String smtpHost;
private final String username;
private final String password;
private final String from;
private final Session session;
public HtmlMailSender(String smtpHost, int port, String username, String password, String from) {
this.smtpHost = smtpHost;
this.username = username;
this.password = password;
this.from = from;
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true"); // TLS 加密
props.put("mail.transport.protocol", "smtp");
props.put("mail.debug", "false");
this.session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
public void sendHtmlMail(String to, String subject, String htmlContent) throws MessagingException {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(subject, "UTF-8");
message.setSentDate(new Date());
// 關鍵:設定內容類型為 text/html
message.setContent(htmlContent, "text/html; charset=UTF-8");
Transport.send(message);
}
// 批量發送
public void sendBatch(String[] tos, String subject, String htmlContent) throws MessagingException {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(String.join(",", tos)));
message.setSubject(subject, "UTF-8");
message.setSentDate(new Date());
message.setContent(htmlContent, "text/html; charset=UTF-8");
Transport.send(message);
}
}
<!-- mail-template.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.container { max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif; }
.header { background: #2c3e50; color: white; padding: 20px; text-align: center; }
.content { padding: 20px; line-height: 1.6; }
.button { display: inline-block; background: #3498db; color: white; padding: 12px 24px;
text-decoration: none; border-radius: 4px; margin-top: 16px; }
.footer { background: #ecf0f1; padding: 15px; text-align: center; font-size: 12px; color: #7f8c8d; }
</style>
</head>
<body>
<div class="container">
<div class="header"><h1>${title}</h1></div>
<div class="content">
<p>親愛的 ${userName},</p>
<p>${body}</p>
<a href="${actionUrl}" class="button">${buttonText}</a>
</div>
<div class="footer">© 2024 ${companyName}. 保留所有權利。</div>
</div>
</body>
</html>
MimeMessage message = new MimeMessage(session);
MimeMultipart multipart = new MimeMultipart("related");
// HTML 部分
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlContent, "text/html; charset=UTF-8");
multipart.addBodyPart(htmlPart);
// 圖片部分
MimeBodyPart imagePart = new MimeBodyPart();
imagePart.attachFile(new File("logo.png"));
imagePart.setContentID("<logo>"); // HTML 中用
multipart.addBodyPart(imagePart);
message.setContent(multipart);
MimeBodyPart attachment = new MimeBodyPart();
attachment.attachFile(new File("report.pdf"));
attachment.setFileName(MimeUtility.encodeText("月報.pdf", "UTF-8", "B"));
multipart.addBodyPart(attachment);
| 參數 | 建議值 | 說明 |
|---|---|---|
| mail.smtp.starttls.enable | true | 強制 TLS 加密傳輸 |
| mail.smtp.ssl.trust | smtp.example.com | 信任自簽證書 (測試環境) |
| mail.smtp.connectiontimeout | 10000 | 連線超時 10秒 |
| mail.smtp.timeout | 10000 | 讀寫超時 10秒 |
| mail.smtp.writetimeout | 10000 | 寫入超時 10秒 |
@Configuration
public class MailConfig {
@Value("${spring.mail.host}") String host;
@Value("${spring.mail.port}") int port;
@Value("${spring.mail.username}") String user;
@Value("${spring.mail.password}") String pass;
@Bean
public JavaMailSender javaMailSender() {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost(host);
sender.setPort(port);
sender.setUsername(user);
sender.setPassword(pass);
sender.setDefaultEncoding("UTF-8");
Properties props = sender.getJavaMailProperties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "false");
return sender;
}
}
@Service
public class NotificationService {
@Autowired JavaMailSender mailSender;
@Autowired TemplateEngine templateEngine;
public void sendWelcomeEmail(User user) {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(user.getEmail());
helper.setSubject("歡迎註冊!");
Context ctx = new Context();
ctx.setVariable("userName", user.getName());
ctx.setVariable("title", "歡迎加入我們");
ctx.setVariable("body", "您的帳號已成功建立,請點擊下方按鈕完成驗證。");
ctx.setVariable("actionUrl", "https://app.example.com/verify?token=" + user.getVerifyToken());
ctx.setVariable("buttonText", "立即驗證");
ctx.setVariable("companyName", "Example Inc.");
String html = templateEngine.process("mail/welcome", ctx);
helper.setText(html, true); // true = HTML
mailSender.send(message);
}
}
MimeUtility.encodeText(subject, "UTF-8", "B"),內容設定 charset=UTF-8。Java 發送 HTML 郵件核心在於:正確設定 Content-Type、使用模板引擎分離內容與邏輯、配置 TLS 加密、處理編碼與附件/內嵌資源。Spring Boot 整合 JavaMailSender + Thymeleaf 是企業級應用的標準棧,兼顧開發效率與生產穩定性。