JavaMail API (javax.mail) + JavaBeans Activation Framework (JAF, javax.activation)。JAF 處理 MIME 編碼,郵件附件必須依賴它。
mail.jar (JavaMail 1.3.2+)activation.jar (JAF 1.0.2+)CLASSPATH
public class SendMail {
private MimeMessage mimeMsg;
private Session session;
private Properties props;
private boolean needAuth = false;
private String username, password;
private Multipart mp; // 郵件內容容器:正文 + 附件
public SendMail(String smtpHost) {
setSmtpHost(smtpHost);
createMimeMessage();
}
// 設定 SMTP 主機
public void setSmtpHost(String host) {
if (props == null) props = System.getProperties();
props.put("mail.smtp.host", host);
}
// 建立 Session 與 MimeMessage
public boolean createMimeMessage() {
try {
session = Session.getDefaultInstance(props, null);
mimeMsg = new MimeMessage(session);
mp = new MimeMultipart();
return true;
} catch (Exception e) { return false; }
}
// 啟用 SMTP 認證
public void setNeedAuth(boolean need) {
if (props == null) props = System.getProperties();
props.put("mail.smtp.auth", need ? "true" : "false");
this.needAuth = need;
}
public void setNamePass(String user, String pwd) {
this.username = user; this.password = pwd;
}
// 設定主旨
public boolean setSubject(String subject) {
try { mimeMsg.setSubject(subject); return true; }
catch (Exception e) { return false; }
}
// 設定 HTML 正文
public boolean setBody(String htmlBody) {
try {
BodyPart bp = new MimeBodyPart();
bp.setContent(htmlBody, "text/html;charset=GB2312");
mp.addBodyPart(bp);
return true;
} catch (Exception e) { return false; }
}
// 新增附件
public boolean addFileAffix(String filename) {
try {
BodyPart bp = new MimeBodyPart();
FileDataSource fds = new FileDataSource(filename);
bp.setDataHandler(new DataHandler(fds));
bp.setFileName(fds.getName()); // 保留原檔名
mp.addBodyPart(bp);
return true;
} catch (Exception e) { return false; }
}
// 設定寄件者
public boolean setFrom(String from) {
try { mimeMsg.setFrom(new InternetAddress(from)); return true; }
catch (Exception e) { return false; }
}
// 設定收件者 (TO)
public boolean setTo(String to) {
if (to == null) return false;
try {
mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
return true;
} catch (Exception e) { return false; }
}
// 發送郵件
public boolean sendout() {
try {
mimeMsg.setContent(mp);
mimeMsg.saveChanges();
Session mailSession = Session.getInstance(props, null);
Transport transport = mailSession.getTransport("smtp");
transport.connect((String)props.get("mail.smtp.host"), username, password);
transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO));
transport.close();
return true;
} catch (Exception e) { return false; }
}
}
public static void main(String[] args) {
SendMail mail = new SendMail("smtp.163.com");
mail.setNeedAuth(true);
mail.setNamePass("sendMail", "Javacode"); // 帳號密碼
mail.setSubject("測試主旨");
mail.setBody("<h1>HTML 內容</h1><p>支援中文</p>");
mail.setFrom("sendMail@163.com");
mail.setTo("recipient@example.com");
mail.addFileAffix("D:/SendMail.java"); // 附件路徑
mail.sendout();
}
| 功能 | 關鍵類/方法 | 注意事項 |
|---|---|---|
| HTML 內容 | MimeBodyPart.setContent(html, "text/html;charset=GB2312") | 編碼需與中文環境匹配 |
| 附件 | FileDataSource + DataHandler | 大檔案建議分段或壓縮 |
| SMTP 認證 | props.put("mail.smtp.auth", "true") + Transport.connect(host, user, pwd) | 163/126/QQ 等均需認證 |
| 多收件者 | InternetAddress.parse("a@b.com, c@d.com") | 逗號分隔 |
| 抄送/密送 | Message.RecipientType.CC / BCC | 同 setRecipients |
NoClassDefFoundError: javax/activation/DataHandler → 缺 activation.jarAuthentication failed → 帳號/密碼錯誤,或郵箱需開啟「SMTP 服務」與「授權碼」MimeUtility.encodeWord(filename, "GB2312", "B") 編碼檔名