首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JavaMail 實現郵件批量發送:從核心流程到生產級封裝實戰

     編輯:Java 相關知識

JavaMail 是 Java 平台發送/接收郵件的標準 API。本文完整演示:核心流程解析、認證器封裝、發送器核心類、工廠模式管理、觀察者模式業務整合,構建可複用的批量郵件發送組件。

核心流程五步驟

  1. 認證器:繼承 Authenticator,重寫 getPasswordAuthentication() 提供帳號密碼。
  2. Session 配置:Properties 設定 SMTP 主機、端口、認證、加密(SSL/TLS)。
  3. 構建郵件:MimeMessage 設定寄件者、收件者、主題、內容(文本/HTML/附件)。
  4. 發送:Transport.send(message)。
  5. 異常處理:捕獲 MessagingException、AddressException。

1. 認證器封裝


public class MailAuthenticator extends Authenticator {
    private String username;
    private String password;

    public MailAuthenticator(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password);
    }
    // getter/setter 略
}

2. 郵件發送核心類


public class SimpleMailSender {
    private final Properties props = System.getProperties();
    private MailAuthenticator authenticator;
    private Session session;

    // 構造器:自動解析 SMTP 主機 (smtp.域名)
    public SimpleMailSender(String username, String password) {
        String smtpHost = "smtp." + username.split("@")[1];
        init(username, password, smtpHost);
    }
    // 構造器:指定 SMTP 主機
    public SimpleMailSender(String smtpHost, String username, String password) {
        init(username, password, smtpHost);
    }

    private void init(String username, String password, String smtpHost) {
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.host", smtpHost);
        // SSL 支援(465 端口)
        // props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        // props.put("mail.smtp.socketFactory.port", "465");
        // TLS 支援(587 端口)
        // props.put("mail.smtp.starttls.enable", "true");

        authenticator = new MailAuthenticator(username, password);
        session = Session.getInstance(props, authenticator);
    }

    // 單發
    public void send(String recipient, String subject, Object content) 
            throws AddressException, MessagingException {
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(authenticator.getUsername()));
        msg.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
        msg.setSubject(subject);
        msg.setContent(content.toString(), "text/html;charset=utf-8");
        Transport.send(msg);
    }

    // 群發(單郵件多收件人,收件人互見)
    public void send(List recipients, String subject, Object content)
            throws AddressException, MessagingException {
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(authenticator.getUsername()));
        msg.setRecipients(Message.RecipientType.TO, 
            recipients.stream().map(InternetAddress::new).toArray(InternetAddress[]::new));
        msg.setSubject(subject);
        msg.setContent(content.toString(), "text/html;charset=utf-8");
        Transport.send(msg);
    }

    // 重載:接受 SimpleMail POJO
    public void send(String recipient, SimpleMail mail) throws AddressException, MessagingException {
        send(recipient, mail.getSubject(), mail.getContent());
    }
    public void send(List recipients, SimpleMail mail) throws AddressException, MessagingException {
        send(recipients, mail.getSubject(), mail.getContent());
    }
}

3. 郵件 POJO


public class SimpleMail {
    private String subject;
    private String content;
    // getter/setter
}

4. 工廠模式管理發送器單例


public class MailSenderFactory {
    private static SimpleMailSender serviceSender;

    public static SimpleMailSender getSender(MailSenderType type) {
        if (type == MailSenderType.SERVICE) {
            if (serviceSender == null) {
                // 從配置檔讀取帳密
                serviceSender = new SimpleMailSender("service@126.com", "password");
            }
            return serviceSender;
        }
        return null;
    }
}

5. 觀察者模式業務整合:價格變動通知


public class ProductPriceObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (!(o instanceof Product)) return;
        Product product = (Product) o;
        if (!(arg instanceof Float)) return;
        Float newPrice = (Float) arg;
        Float decrease = product.getPrice() - newPrice;
        if (decrease > 0) {
            SimpleMailSender sender = MailSenderFactory.getSender(MailSenderType.SERVICE);
            List recipients = Arrays.asList("user1@qq.com", "user2@gmail.com");
            try {
                for (String to : recipients) {
                    sender.send(to, "價格變動通知", 
                        "關注商品 " + product.getName() + " 降價!" +
                        "原價 " + product.getPrice() + " → 現價 " + newPrice +
                        ",降幅 " + decrease + " 元。");
                }
            } catch (MessagingException e) {
                log.error("郵件發送失敗", e);
            }
        }
    }
}

生產環境關鍵增強清單

常見 SMTP 設定參考

增強點實現方案
連線池使用 Session.getInstance(props, authenticator) 複用 Session;或整合 Apache Commons Email 內建連線池
異步發送@Async + 執行緒池 / 消息佇列 (RabbitMQ/Kafka) 削峰
重試機制指數退避重試(Spring Retry / Resilience4j)
模板引擎Thymeleaf/FreeMarker 渲染 HTML 郵件模板
附件/內嵌圖片MimeMultipart + MimeBodyPart 組裝
退信/打開率追蹤整合 SendGrid/Mailgun/Amazon SES 等雲郵件服務
配置外部化Spring @ConfigurationProperties 綁定 application.yml
郵箱服務商SMTP 主機端口加密
163/126smtp.163.com465/994SSL
QQsmtp.qq.com465/587SSL/TLS
Gmailsmtp.gmail.com465/587SSL/TLS
Outlooksmtp.office365.com587TLS
開啟「客戶端授權碼」而非登錄密碼,並啟用 SMTP 服務。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved