本文介紹使用 Javamail 通過 SMTP 協議發信。
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>範例程式碼:
package org.example;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
//import java.net.MalformedURLException;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;
//import java.util.HashMap;
//import java.util.Base64;
//import java.net.URL;
//import java.io.IOException;
//import java.io.InputStream;
//import javax.mail.util.ByteArrayDataSource;
//import java.net.URLEncoder;
//import javax.activation.DataHandler;
//import javax.activation.FileDataSource;
//import javax.activation.URLDataSource;
//import com.google.gson.GsonBuilder;
public class SampleMail {
// 配置常量
private static final String SMTP_HOST = "smtpdm.aliyun.com";
private static final int SMTP_PORT = 80;
private static final String USER_NAME = "發信地址";
private static final String PASSWORD = "xxxxxxx";
protected static String genMessageID(String mailFrom) {
// 產生Message-ID:
if (!mailFrom.contains("@")) {
throw new IllegalArgumentException("Invalid email format: " + mailFrom);
}
String domain = mailFrom.split("@")[1];
UUID uuid = UUID.randomUUID();
return "<" + uuid.toString() + "@" + domain + ">";
}
private static void setRecipients(MimeMessage message, Message.RecipientType type, String[] recipients)
throws MessagingException {
// 設定收件者地址
if (recipients == null || recipients.length == 0) {
return; // 空列表不設定
}
InternetAddress[] addresses = new InternetAddress[recipients.length];
for (int h = 0; h < recipients.length; h++) {
addresses[h] = new InternetAddress(recipients[h]);
}
message.setRecipients(type, addresses);
}
public static void main(String[] args) throws MessagingException, UnsupportedEncodingException {
// 配置發送郵件的環境屬性
final Properties props = new Properties();
// 表示SMTP發送郵件,需要進行身分識別驗證
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", SMTP_HOST);
//設定連接埠:
props.put("mail.smtp.port", SMTP_PORT);//或"25", 如果使用ssl,則去掉使用80或25連接埠的配置,進行如下配置:
//加密方式:
//props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//props.put("mail.smtp.socketFactory.fallback", "false");//禁止回退非加密
//props.put("mail.smtp.socketFactory.port", "465");
//props.put("mail.smtp.port", "465");
props.put("mail.smtp.from", USER_NAME); //mailfrom 參數
props.put("mail.user", USER_NAME);// 寄件者的帳號(在控制台建立的發信地址)
props.put("mail.password", PASSWORD);// 發信地址的smtp密碼(在控制台選擇發信地址進行設定)
//props.put("mail.smtp.connectiontimeout", 1000);
System.setProperty("mail.mime.splitlongparameters", "false");//用於解決附件名過長導致的顯示異常
//props.setProperty("mail.smtp.ssl.enable", "true"); //請配合465連接埠使用
// 構建授權資訊,用於進行SMTP進行身分識別驗證
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(USER_NAME, PASSWORD);
}
};
//使用環境屬性和授權資訊,建立郵件會話
Session mailSession = Session.getInstance(props, authenticator);
String messageIDValue = genMessageID(USER_NAME);
MimeMessage message = new MimeMessage(mailSession) {
@Override
protected void updateMessageID() throws MessagingException {
setHeader("Message-ID", messageIDValue);
}
};
try {
// 設定寄件者郵件地址和名稱。填寫控制台配置的發信地址。和上面的mail.user保持一致。名稱使用者可以自訂填寫。
InternetAddress from = new InternetAddress(USER_NAME, "寄件者暱稱");//from 參數,可實現代發,注意:代發容易被收信方拒信或進入垃圾箱。
message.setFrom(from);
setRecipients(message, Message.RecipientType.TO, new String[]{"收信地址1", "收信地址2"});
setRecipients(message, Message.RecipientType.CC, new String[]{"收信地址3", "收信地址4"});
setRecipients(message, Message.RecipientType.BCC, new String[]{"收信地址5", "收信地址6"});
InternetAddress replyToAddress = new InternetAddress("回信地址");
message.setReplyTo(new Address[]{replyToAddress});//可選。設定回信地址
message.setSentDate(new Date());
message.setSubject("測試主題");
// message.setContent("測試txt內容1", "text/text;charset=UTF-8");//純文字內容,若使用MimeBodyPart這裡會被覆蓋
// 或
// message.setContent("測試<br> html內容2", "text/html;charset=UTF-8");//HTML內容,若使用MimeBodyPart這裡會被覆蓋
// //若需要開啟郵件Tracing Service,請使用以下代碼設定跟蹤連結頭。前置條件和約束見文檔"如何開啟資料跟蹤功能?"
// String tagName = "tagname4";
// HashMap<String, String> trace = new HashMap<>();
// //這裡為字串"1"
// trace.put("OpenTrace", "1"); //開啟郵件跟蹤
// trace.put("LinkTrace", "1"); //點擊郵件裡的URL跟蹤
// trace.put("TagName", tagName); //控制台建立的標籤tagname
// String jsonTrace = new GsonBuilder().setPrettyPrinting().create().toJson(trace);
// //System.out.println(jsonTrace);
// String base64Trace = new String(Base64.getEncoder().encode(jsonTrace.getBytes()));
// //設定跟蹤連結頭
// message.addHeader("X-AliDM-Trace", base64Trace);
//郵件eml原文中的樣本值:X-AliDM-Trace: eyJUYWdOYW1lIjoiVGVzdCIsIk9wZW5UcmFjZSI6IjEiLCJMaW5rVHJhY2UiOiIxIn0=
//發送附件和內容:
// 建立多重訊息
Multipart multipart = new MimeMultipart();
// // 建立一個BodyPart用於純文字內容
// BodyPart textPart = new MimeBodyPart();
// textPart.setText("測試txt內容3");
// multipart.addBodyPart(textPart);
// 建立一個BodyPart用於HTML內容
BodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent("測試<br> html內容4", "text/html;charset=UTF-8");//設定郵件的內容,會覆蓋前面的message.setContent
multipart.addBodyPart(htmlPart);
// //附件部分
// //發送附件,總的郵件大小不超過15M,建立訊息部分。
// // 發送本地附件
// String[] fileList = {"C:\\Users\\Downloads\\test1.txt", "C:\\Users\\Downloads\\test2.txt"};
// for (String filePath : fileList) {
// MimeBodyPart mimeBodyPart = new MimeBodyPart();
//
// FileDataSource fileDataSource = new FileDataSource(filePath);
// mimeBodyPart.setDataHandler(new DataHandler(fileDataSource));
// //處理附件名稱中文(附帶檔案路徑)亂碼問題
// mimeBodyPart.setFileName(MimeUtility.encodeWord(fileDataSource.getName()));
// mimeBodyPart.addHeader("Content-Transfer-Encoding", "base64");
// multipart.addBodyPart(mimeBodyPart);
// }
// // 發送URL附件
// String[] fileListUrl = {"https://example.oss-cn-shanghai.aliyuncs.com/xxxxxxxxxxx1.png", "https://example.oss-cn-shanghai.aliyuncs.com/xxxxxxxxxxx2.png"};
// for (String fileUrl : fileListUrl) {
// URL url = new URL(fileUrl);
// String filename = url.getPath();
// filename = filename.substring(filename.lastIndexOf('/') + 1);
// try (InputStream in = url.openStream()) {
// // 建立附件部分
// MimeBodyPart attachmentPart = new MimeBodyPart();
// // 使用位元組數組資料來源
// ByteArrayDataSource ds = new ByteArrayDataSource(in, "application/octet-stream");
// attachmentPart.setDataHandler(new javax.activation.DataHandler(ds));
// attachmentPart.setFileName(filename);
// attachmentPart.setDisposition(MimeBodyPart.ATTACHMENT);
// multipart.addBodyPart(attachmentPart);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
// 添加完整訊息
message.setContent(multipart);
// 發送附件代碼,結束
//mailSession.setDebug(true);//開啟debug模式
Transport.send(message);
System.out.println("發送完成!");
} catch (MessagingException | UnsupportedEncodingException e) {
System.err.println("郵件發送失敗: " + e.getMessage());
e.printStackTrace();
// } catch (MalformedURLException e) {
// throw new RuntimeException(e);
}
}
}