Pingchas 发表于 2026-3-5 17:47:47

[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]
查看完整版本: [Java]《批量邮件发送》