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

JavaMail 發送郵件完整封裝:支援 HTML、附件、多收件人、Spring 整合

     編輯:Java 相關知識

前言

JavaMail 是 Java 平台發送電子郵件的標準 API。本文提供兩個生產級封裝類:SendMail(輕量獨立版)與 EmailServer(Spring 整合、單例、模板支援),涵蓋純文本/HTML 郵件、多附件、多收件人、郵件伺服器配置管理等實戰需求。

一、輕量級獨立封裝:SendMail

1.1 核心特性

  • 零依賴(僅需 javax.mail、javax.activation)。
  • 支援郵件伺服器、發件人、多收件人(字串/陣列/List)靈活配置。
  • 支援 HTML 內容、多附件、自動編碼處理。
  • 內建郵箱格式正則校驗。

1.2 完整代碼

public class SendMail {
    private static final String MAIL_REGEX = "^[\\w\\.=-]+@[\\w\\.-]+\\.[\\w]{2,3}$";
    private String mailServer;
    private String sender;
    private String[] receiver;

    // 多重配置入口
    public void setMailBasicInfo(String mailServer, String sender, String receiver) { ... }
    public void setMailBasicInfo(String mailServer, String sender, String[] users) { ... }
    public void setMailBasicInfo(String mailServer, String sender, List<String> users) { ... }

    // 統一發送入口
    public boolean send(String subject, String content, List<String> fileNames) {
        subject = subject == null ? "" : subject;
        content = content == null ? "" : content;

        Properties props = new Properties();
        props.put("mail.smtp.host", mailServer);
        Session session = Session.getInstance(props, null);

        try {
            InternetAddress[] to = getReceiverList();
            if (to.length == 0) return false;

            MimeMessage msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(sender));
            msg.setRecipients(Message.RecipientType.TO, to);
            msg.setSubject(subject, "UTF-8");
            msg.setSentDate(new Date());

            // 多部分容器:文本 + 附件
            Multipart mp = new MimeMultipart();
            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setContent(content, "text/html;charset=UTF-8");
            mp.addBodyPart(textPart);

            // 處理附件
            if (fileNames != null) {
                for (String fn : fileNames) {
                    File f = new File(fn);
                    if (!f.isFile()) continue;
                    MimeBodyPart filePart = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(f);
                    filePart.setDataHandler(new DataHandler(fds));
                    filePart.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B"));
                    mp.addBodyPart(filePart);
                }
            }
            msg.setContent(mp);
            Transport.send(msg);
            return true;
        } catch (Exception e) {
            log.error("郵件發送失敗", e);
            return false;
        }
    }

    // 重載簡化調用
    public boolean send(String subject, String content) { return send(subject, content, null); }
    public boolean send(String subject) { return send(subject, null); }

    // 解析收件人列表
    private InternetAddress[] getReceiverList() throws AddressException {
        List<InternetAddress> list = new ArrayList<>();
        for (String r : receiver) {
            if (r.matches(MAIL_REGEX)) list.add(new InternetAddress(r));
        }
        return list.toArray(new InternetAddress[0]);
    }
}

1.3 使用範例

SendMail mail = new SendMail();
mail.setMailBasicInfo("smtp.163.com", "sender@163.com", Arrays.asList("a@qq.com", "b@gmail.com"));

String html = "<h1>測試郵件</h1><a href='https://example.com'>點擊鏈接</a>";
List<String> attachments = Arrays.asList("/path/report.pdf", "/path/image.png");

mail.send("測試主題", html, attachments);

二、企業級 Spring 整合版:EmailServer

2.1 設計亮點

  • 單例模式:Spring 管理 Bean,全局唯一實例。
  • 配置外部化:多郵件伺服器配置(EmailConfig)注入,自動根據發件人域名匹配 SMTP 設定。
  • 統一異常處理與日誌:SLF4J 記錄詳細發送過程與失敗原因。
  • 支援身份驗證:可配置 Authenticator,支援 SSL/TLS(需補全 SSL SocketFactory 配置)。
  • 模式分離:sendTextMail / sendHtmlMail 語義清晰。

2.2 核心代碼結構

@Component // Spring Bean
public class EmailServer {
    private static final Logger log = LoggerFactory.getLogger(EmailServer.class);

    @Autowired private List<EmailConfig> config; // 多郵箱配置
    private boolean isDebug = false;
    private boolean isAuth = true;

    // 單例獲取
    public static EmailServer getInstance() { 
        return ApplicationHelper.getInstance().getBean(EmailServer.class); 
    }

    // 文本郵件
    public boolean sendTextMail(String username, String password, String title, 
                                String content, String receiver) { ... }
    public boolean sendTextMail(String username, String password, String title, 
                                String content, List<String> receivers) { ... }

    // HTML 郵件
    public boolean sendHtmlMail(String username, String password, String title, 
                                String content, String receiver) { ... }
    public boolean sendHtmlMail(String username, String password, String title, 
                                String content, List<String> receivers) { ... }

    // 核心構建 Message
    private Message makeTextMail(Session session, String title, String content, 
                                 String from, List<String> receivers, boolean isHtml) {
        MimeMessage msg = new MimeMessage(session);
        msg.setSubject(title, "UTF-8");
        if (isHtml) msg.setContent(content, "text/html;charset=UTF-8");
        else msg.setText(content, "UTF-8");
        msg.setFrom(new InternetAddress(from));
        msg.setRecipients(Message.RecipientType.TO, 
                receivers.stream().filter(ValidateUtils::isEmail)
                         .map(InternetAddress::new).toArray(InternetAddress[]::new));
        msg.setSentDate(new Date());
        return msg;
    }

    // 根據發件人域名自動匹配 SMTP 配置
    private EmailConfig getEmailConfig(String email) { ... }
}

2.3 Spring 配置範例

<!-- applicationContext.xml -->
<bean class="com.message.base.email.EmailServer">
    <property name="config">
        <list>
            <bean class="com.message.base.email.EmailConfig">
                <property name="name" value="163" />
                <property name="smtp" value="smtp.163.com" />
                <property name="port" value="465" /> <!-- SSL 端口 -->
            </bean>
            <bean class="com.message.base.email.EmailConfig">
                <property name="name" value="qq" />
                <property name="smtp" value="smtp.qq.com" />
                <property name="port" value="587" /> <!-- TLS 端口 -->
            </bean>
        </list>
    </property>
    <property name="isAuth" value="true" />
    <property name="isDebug" value="false" />
</bean>

2.4 調用範例

@Autowired EmailServer emailServer; // 或 EmailServer.getInstance()

List<String> to = Arrays.asList("user1@163.com", "user2@qq.com");
emailServer.sendHtmlMail("admin@163.com", "password", "HTML 郵件測試", 
        "<span style='color:red'>內容</span><a href='https://baidu.com'>鏈接</a>", to);
emailServer.sendTextMail("admin@163.com", "password", "文本郵件測試", "純文本內容", to);

三、生產環境關鍵補強

  1. SSL/TLS 支援:props.put("mail.smtp.ssl.enable", "true") (SSL) 或 props.put("mail.smtp.starttls.enable", "true") (TLS),並配置對應端口(465/587)。
  2. 連接池/複用:高頻發送場景使用 Transport.connect() 保持長連接,或引入 Spring Boot Mail 自動配置的連接池。
  3. 異步發送:@Async 或線程池提交,避免阻塞業務線程。
  4. 模板引擎:整合 Thymeleaf/FreeMarker 渲染複雜 HTML 郵件,分離業務與視圖。
  5. 發送狀態追蹤:記錄 Message-ID、發送時間、狀態(成功/退信/打開/點擊),配合郵件服務商 Webhook 實現全鏈路監控。
  6. 防刷/限流:單 IP/用戶發送頻率限制,防止濫用。
  7. 編碼統一:全鏈路 UTF-8,附件檔名用 MimeUtility.encodeText 避免中文亂碼。

四、總結

SendMail 適合無框架、輕量級專案快速接入;EmailServer 適合 Spring 生態企業級應用,提供配置管理、多賬號隔離、擴展性更強。兩者核心均基於 JavaMail MimeMessage + Multipart 實現多部分郵件構建。掌握郵件協議(SMTP/SSL/TLS)、MIME 結構、異步化與監控,才能構建可靠的通知觸達體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved