spring發送Email-驗證碼-圖片-附件-解決亂碼

本文簡要介紹如何通過Spring框架的支持,通過QQ郵箱來發送郵件,包括簡單文本,附件、以及內聯圖片、HTML以及HTTP圖片。

spring-context-support很早就內置支持郵件發送。

當然, 官方文檔明確指出, 需要依賴 JavaMail 這個庫。

在這個年代, 我們很少自己搭建 smtp 服務器來發送郵件, 一般都是使用郵件提供商的服務。 例如 QQ郵箱, 企業郵箱, 163, 或者阿里雲之類的廠商。

註冊一個賬號, 然後參考郵件服務商的幫助中心, 以及賬戶設置頁面, 獲取smtp服務器端口信息, 以及你註冊的賬號和密碼, 保存到一個比較安全的地方。

相關依賴。

pom.xml中的依賴如下:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.0.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.2</version>
</dependency>

其中, commons-io 根據需要決定, 本文中使用了 IOUtils工具類, 提供了很多方便又強大的IO工具方法, 有興趣可以研究一下。

Spring-Mail 相關的接口與實現類

  • MailSender , 發送簡單郵件的頂層接口。
  • JavaMailSender , 繼承頂層接口, 支持發送 MIME 郵件。
  • JavaMailSenderImpl 實現類, 顧名思義。
  • SimpleMailMessage 類, 簡單郵件信息, 包括 from, to, cc, subject 以及 text 字段。
  • MimeMessagePreparator 接口, 用於 MIME 郵件回調。
  • MimeMessageHelper 輔助類, 可用於創建 MIME 郵件。支持圖片、附件、以及 HTML 樣式等。

簡單測試代碼

下面是簡單的測試代碼。 實際使用時請參考本文末尾的相關鏈接。把代碼組織好看一點,好用一點。

package com.cncounter.test.spring;

import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;

public class TestSpringEmail {
    public static void main(String[] args) {
        //
        sendTextEmail();
    }
    public static void sendTextEmail() {
        //
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        // 參考QQ郵箱幫助中心
        mailSender.setHost("smtp.qq.com"); // QQ郵箱smtp發送服務器地址
        //mailSender.setPort(465); // QQ這個端口不可用
        mailSender.setPort(587);// 端口號
        mailSender.setUsername("[email protected]"); // 使用你自己的賬號
        mailSender.setPassword("usbusbcnzztbsbtob"); // 授權碼-發短信獲取
        // 郵件信息
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom("[email protected]"); // 發件人郵箱
        msg.setTo("[email protected]"); // 收件人郵箱
        msg.setSubject("測試Spring郵件"); // 標題
        msg.setText("您的訂單號碼: 20181120075; 請勿告訴別人!"); // 文本信息
        try {
            mailSender.send(msg);
            System.out.println("郵件發送成功!"); // 沒有報錯就是好消息 :-)
        } catch (MailException ex) {
            System.err.println("發送失敗:" + ex.getMessage());
        }
    }
}

測試結果如下圖所示:

05_01_text_mail.png

可以看到, 簡單驗證碼之類的文本, 通過這些封裝好的工具類, 代碼編寫很容易。

發送附件示例

以下是發送附件的示例。 根據需要, 可以發送多個附件。

package com.cncounter.test.spring;

import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.*;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.util.Properties;

public class TestSpringAttachEmail {
    public static void main(String[] args) throws Exception {
        // 發送帶附件的MIME郵件
        sendAttachmentEmail();
    }

    // 發送帶附件的MIME郵件
    public static void sendAttachmentEmail() throws MessagingException, IOException {
        // 郵件發送器
        JavaMailSender mailSender = getJavaMailSender();
        // MIME 郵件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        // 輔助類; 明確使用 UTF-8 編碼; 否則HTML報中文亂碼
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
        //
        boolean isHTML = true;
        // 郵件信息
        helper.setFrom("[email protected]"); // 發件人郵箱
        helper.setTo("[email protected]"); // 收件人郵箱
        helper.setSubject("測試Spring發送附件-1"); // 標題
        helper.setText("請點擊: <a href='http://www.yuledanao.com/dl/PWA_INTRO.zip'><b>PWA開發簡介.zip</b></a>;" +
                " 或者下載附件!", isHTML); // HTML-信息

        // 增加1個附件; 可以使用多種資源API
        String fileName1 = "E:/PWA開發簡介.zip";
        InputStream inputStream1 = new FileInputStream(fileName1);
        //
        // Java Mail 會打開2次 InputStreamResource
	// 第一次確定編碼, 第二次才執行編碼。
        ByteArrayResource byteResource1 =
                new ByteArrayResource(IOUtils.toByteArray(inputStream1));
        // 所以不能使用 InputStreamResource
        // InputStreamResource attachment1 = new InputStreamResource(inputStream1);
        helper.addAttachment("PWA開發簡介.zip", byteResource1);
        try {
            mailSender.send(mimeMessage);
            System.out.println("郵件發送成功!"); // 沒有報錯就是好消息 :-)
        } catch (MailException ex) {
            System.err.println("發送失敗:" + ex.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream1);
        }
    }

    // 獲取郵件發送器
    public static JavaMailSender getJavaMailSender() {
        //
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        // 參考QQ郵箱幫助中心
        mailSender.setHost("smtp.qq.com"); // QQ郵箱smtp發送服務器地址
        //mailSender.setPort(465); // QQ這個端口不可用? 爲什麼?
        mailSender.setPort(587);// 端口號
        mailSender.setUsername("[email protected]"); // 使用你自己的賬號
        mailSender.setPassword("usbusbcnzztbsbtob"); // 授權碼-發短信獲取
        //
        // 相關屬性配置, 也可以不修改,使用默認值
        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");// 協議
        props.put("mail.smtp.auth", "true");// 登錄
        props.put("mail.smtp.starttls.enable", "true");//使用SSL
        props.put("mail.debug", "true");// 調試信息輸出
        //
        return mailSender;
    }
}

當然, 具體的代碼請根據需要進行適當的封裝。 比如自定義工具類。

結果如下圖所示:

05_02_attachment_email.png

發送內聯圖片示例

有兩種手段,請根據需要選擇:

  1. HTML嵌入http路徑的圖片。
  2. 以內聯資源的方式發送圖片。

以下是這兩種內聯圖片的示例:

package com.cncounter.test.spring;

import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class TestSpringImageEmail {
    public static void main(String[] args) throws Exception {
        // 發送帶內聯圖片的MIME郵件
        sendImageEmail();
    }

    // 發送帶內聯圖片的MIME郵件
    public static void sendImageEmail() throws MessagingException, IOException {
        // 郵件發送器
        JavaMailSender mailSender = getJavaMailSender();
        // MIME 郵件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        // 輔助類; 明確使用 UTF-8 編碼; 否則HTML報中文亂碼
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
        //
        boolean isHTML = true;
        // 郵件信息
        helper.setFrom("[email protected]"); // 發件人郵箱
        helper.setTo("[email protected]"); // 收件人郵箱
        helper.setSubject("測試Spring發送內聯圖片-3"); // 標題
        helper.setText("<h1>測試圖片</h1>" +
                "海信電視-InLine:" +
                "<br/>" +
                "<a target='_blank' href='http://www.yuledanao.com/dl/haixin.png'><img src='cid:image1' /></a>" +
                "<br/>" +
                "img-src-http資源:" +
                "<br/>" +
                "<a target='_blank' href='http://www.yuledanao.com/dl/haixin.png'><img src='http://www.yuledanao.com/dl/haixin.png' /></a>" +
                "<br/>" +
                "<br/>" +
                "請點擊: <a target='_blank' href='http://www.yuledanao.com/dl/PWA_INTRO.zip'><b>PWA開發簡介.zip</b></a>;" +
                " 或者下載附件!", isHTML); // HTML-信息
        // cid - content-ID
        // 增加內聯圖片:
        // 不作爲附件發送
        String imageName1 = "E:/haixin.png";
        InputStream imageInputStream1 = new FileInputStream(imageName1);
        ByteArrayResource imageResource1 =
                new ByteArrayResource(IOUtils.toByteArray(imageInputStream1));
        helper.addInline("image1", imageResource1, "image/png");

        // 增加1個附件; 可以使用多種資源API
        String fileName1 = "E:/PWA開發簡介.zip";
        InputStream inputStream1 = new FileInputStream(fileName1);
        //
        // Java Mail 會打開2次 InputStreamResource;
        // 第一次確定編碼, 第二次才執行編碼。
        ByteArrayResource byteResource1 =
                new ByteArrayResource(IOUtils.toByteArray(inputStream1));
        // 所以不能直接使用 InputStreamResource
        // InputStreamResource attachment1 = new InputStreamResource(inputStream1);
        helper.addAttachment("PWA開發簡介.zip", byteResource1);
        try {
            mailSender.send(mimeMessage);
            System.out.println("郵件發送成功!"); // 沒有報錯就是好消息 :-)
        } catch (MailException ex) {
            System.err.println("發送失敗:" + ex.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream1);
        }
    }

    // 獲取郵件發送器
    public static JavaMailSender getJavaMailSender() {
        //
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        // 參考QQ郵箱幫助中心
        mailSender.setHost("smtp.qq.com"); // QQ郵箱smtp發送服務器地址
        //mailSender.setPort(465); // QQ這個端口不可用? 爲什麼?
        mailSender.setPort(587);// 端口號
        mailSender.setUsername("[email protected]"); // 使用你自己的賬號
        mailSender.setPassword("usbusbcnzztbsbtob"); // 授權碼-發短信獲取
        //
        // 相關屬性配置, 也可以不修改,使用默認值
        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");// 協議
        props.put("mail.smtp.auth", "true");// 登錄
        props.put("mail.smtp.starttls.enable", "true");//使用SSL
        //props.put("mail.debug", "true");// 調試信息輸出
        //
        return mailSender;
    }
}

如果在公網上沒有固定的HTTP服務器或者CDN服務器, 則需要使用內聯的方式來發送圖片。

可以從網絡上下載到圖片資源, 則引用 HTTP 資源更簡單便捷。

需要CSS樣式則設置HTML元素的style屬性即可。

執行結果如下圖所示:

05_03_image_mail.png

和發送附件並不衝突。如果需要發送很多圖片, 可以使用模板技術, 以及 Map/Bean來封裝傳入的數據。

更多信息, 請參考相關鏈接。

相關鏈接

Spring Email使用教程: http://www.baeldung.com/spring-email

spring集成Email文檔: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#mail

日期: 2018年4月8日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章