[Java]《批量邮件发送》
package com.example.demo;import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class HelloApplication extends Application {
private File excelFile;
public static class Recipient {
public String email;
public String name;
public Recipient(String email, String name) {
this.email = email;
this.name = name;
}
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Excel 批量发邮件");
// SMTP 配置
TextField hostField = new TextField("smtp.example.com");
TextField portField = new TextField("465");
CheckBox sslCheck = new CheckBox("SSL");
sslCheck.setSelected(true);
CheckBox tlsCheck = new CheckBox("TLS"); // 一般只用一个,示例都给出
TextField fromField = new TextField("your_email@example.com");
PasswordField passwordField = new PasswordField();
// 邮件内容
TextField subjectField = new TextField("测试邮件主题");
TextArea bodyArea = new TextArea("您好,${name},这是一封测试邮件。");
// Excel 选择
Label excelLabel = new Label("未选择文件");
Button chooseExcelBtn = new Button("选择 Excel");
chooseExcelBtn.setOnAction(e -> {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("Excel 文件", "*.xlsx", "*.xls")
);
File file = fileChooser.showOpenDialog(primaryStage);
if (file != null) {
excelFile = file;
excelLabel.setText(file.getName());
}
});
Button sendBtn = new Button("发送");
TextArea logArea = new TextArea();
logArea.setEditable(false);
sendBtn.setOnAction(e -> {
if (excelFile == null) {
// showAlert("错误", "请先选择 Excel 文件");
return;
}
String host = hostField.getText().trim();
String port = portField.getText().trim();
String from = fromField.getText().trim();
String password = passwordField.getText();
String subject = subjectField.getText().trim();
String bodyTemplate = bodyArea.getText();
new Thread(() -> {
try {
List<Recipient> recipients = readRecipientsFromExcel(excelFile);
logArea.appendText("共读取到 " + recipients.size() + " 个收件人\n");
Session session = createMailSession(host, port, from, password,
sslCheck.isSelected(), tlsCheck.isSelected());
for (Recipient r : recipients) {
String body = bodyTemplate.replace("${name}",
r.name != null ? r.name : "");
try {
sendEmail(session, from, r.email, subject, body);
appendLog(logArea, "发送成功:" + r.email);
} catch (Exception ex) {
appendLog(logArea, "发送失败:" + r.email + ",错误:" + ex.getMessage());
}
}
} catch (Exception ex) {
appendLog(logArea, "总体错误:" + ex.getMessage());
}
}).start();
});
// 布局
GridPane grid = new GridPane();
grid.setPadding(new Insets(10));
grid.setHgap(8);
grid.setVgap(8);
int row = 0;
grid.add(new Label("SMTP 主机:"), 0, row);
grid.add(hostField, 1, row++);
grid.add(new Label("端口:"), 0, row);
grid.add(portField, 1, row++);
grid.add(sslCheck, 0, row);
grid.add(tlsCheck, 1, row++);
grid.add(new Label("发件邮箱:"), 0, row);
grid.add(fromField, 1, row++);
grid.add(new Label("密码/授权码:"), 0, row);
grid.add(passwordField, 1, row++);
grid.add(new Label("主题:"), 0, row);
grid.add(subjectField, 1, row++);
grid.add(new Label("正文模板:"), 0, row);
grid.add(bodyArea, 1, row++);
grid.add(new Label("Excel 文件:"), 0, row);
grid.add(excelLabel, 1, row++);
grid.add(chooseExcelBtn, 1, row++);
grid.add(sendBtn, 1, row++);
grid.add(new Label("日志:"), 0, row);
grid.add(logArea, 1, row++);
primaryStage.setScene(new Scene(grid, 700, 600));
primaryStage.show();
}
private void appendLog(TextArea logArea, String text) {
javafx.application.Platform.runLater(() -> {
logArea.appendText(text + "\n");
});
}
/**
* 创建邮件 Session,支持 SSL / TLS
*/
private Session createMailSession(String host,
String port,
String username,
String password,
boolean useSSL,
boolean useTLS) {
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
if (useSSL) {
// SSL 通道(常见 465 端口)
props.put("mail.smtp.ssl.enable", "true");
}
if (useTLS) {
// TLS/STARTTLS(常见 587 端口)
props.put("mail.smtp.starttls.enable", "true");
}
return Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
/**
* 发送单封邮件
*/
private void sendEmail(Session session,
String from,
String to,
String subject,
String body) throws Exception {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(to));
message.setSubject(subject);
message.setContent(body, "text/html;charset=UTF-8");
// message.setText(body); // 如需 HTML 可改为 setContent(body, "text/html;charset=UTF-8");
Transport.send(message);
}
/**
* 从 Excel 读取收件人列表
* 默认:第一行为表头,A列= email, B列= name
*/
private List<Recipient> readRecipientsFromExcel(File file) throws Exception {
List<Recipient> list = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(file);
Workbook workbook = new XSSFWorkbook(fis)) {
Sheet sheet = workbook.getSheetAt(0);
boolean isFirstRow = true;
for (Row row : sheet) {
if (isFirstRow) {
isFirstRow = false; // 跳过表头
continue;
}
if (row == null) continue;
Cell emailCell = row.getCell(0);
if (emailCell == null) continue;
String email = emailCell.toString().trim();
if (email.isEmpty()) continue;
String name = null;
Cell nameCell = row.getCell(1);
if (nameCell != null) {
name = nameCell.toString().trim();
}
list.add(new Recipient(email, name));
}
}
return list;
}
public static void main(String[] args) {
launch(args);
}
}
打包exe
cmd.exe /X /C "C:\Users\YTZS-D1\.jdks\corretto-18.0.2\bin\jpackage.exe --name EmailSender --dest C:\Users\YTZS-D1\Desktop\test\demo\target --app-version 1.0 --input C:\Users\YTZS-D1\Desktop\test\demo\target --main-class com.example.demo.Launcher --main-jar demo-1.0-SNAPSHOT.jar --win-dir-chooser --win-menu --win-shortcut"
页:
[1]