1. 程式人生 > >SpringBoot2.0高階案例(03):整合 JavaMail ,實現非同步傳送郵件

SpringBoot2.0高階案例(03):整合 JavaMail ,實現非同步傳送郵件

本文原始碼
碼雲地址:知了一笑
https://gitee.com/cicadasmile/middle-ware-parent

一、JavaMail的核心API

1、API功能圖解

2、API說明

(1)、Message 類: javax.mail.Message 類是建立和解析郵件的一個抽象類 子類javax.mail.internet.MimeMessage :表示一份電子郵件。 傳送郵件時,首先創建出封裝了郵件資料的 Message 物件, 然後把這個物件傳遞給郵件傳送Transport 類,執行傳送。 接收郵件時,把接收到的郵件資料封裝在Message 類的例項中,從這個物件中解析收到的郵件資料。

(2)、Transport 類 javax.mail.Transport 類是傳送郵件的核心API 類 建立好 Message 物件後, 只需要使用郵件傳送API 得到 Transport 物件, 然後把 Message 物件傳遞給 Transport 物件, 並呼叫它的傳送方法, 就可以把郵件傳送給指定的郵件伺服器。

(3)、Store 類 javax.mail.Store 類是接收郵件的核心 API 類 例項物件代表實現了某個郵件接收協議的郵件接收物件,接收郵件時, 只需要得到 Store 物件, 然後呼叫 Store 物件的接收方法,就可以從指定的郵件伺服器獲得郵件資料,並把這些郵件資料封裝到表示郵件的 Message 物件中。

(4)、Session 類: javax.mail.Session 類定義郵件伺服器的主機名、埠號、協議等 Session 物件根據這些資訊構建用於郵件收發的 Transport 和 Store 物件, 以及為客戶端建立 Message 物件時提供資訊支援。

二、郵件伺服器配置

以 smtp 為例

1、smtp.mxhichina.com  
阿里雲企業郵箱配置(賬號+密碼)

2、smtp.aliyun.com
阿里雲個人郵箱配置(賬號+密碼)

3、smtp.163.com
網易郵箱配置(賬號+授權碼)

三、公共程式碼塊

1、郵件通用配置

package com.email.send.param;
/**
 * 郵箱傳送引數配置
 */
public class EmailParam {
    /**
     * 郵箱伺服器地址
     */
    // public static final String emailHost = "smtp.mxhichina.com" ; 阿里雲企業郵箱配置(賬號+密碼)
    // public static final String emailHost = "smtp.aliyun.com" ; 阿里雲個人郵箱配置(賬號+密碼)
    public static final String emailHost = "smtp.163.com" ; // 網易郵箱配置(賬號+授權碼)
    /**
     * 郵箱協議
     */
    public static final String emailProtocol = "smtp" ;
    /**
     * 郵箱發件人
     */
    public static final String emailSender = "[email protected]" ;
    /**
     * 郵箱授權碼
     */
    public static final String password = "authCode";
    /**
     * 郵箱授權
     */
    public static final String emailAuth = "true" ;
    /**
     * 郵箱暱稱
     */
    public static final String emailNick = "知了一笑" ;
}

2、常用常量

package com.email.send.param;
/**
 * 郵件傳送型別
 */
public enum EmailType {
	EMAIL_TEXT_KEY("email_text_key", "文字郵件"),
	EMAIL_IMAGE_KEY("email_image_key", "圖片郵件"),
	EMAIL_FILE_KEY("email_file_key", "檔案郵件");
	private String code;
	private String value;
	EmailType(String code, String value) {
		this.code = code;
		this.value = value;
	}
	public static String getByCode(String code) {
		EmailType[] values = EmailType.values();
		for (EmailType emailType: values) {
			if (emailType.code.equalsIgnoreCase(code)) {
				return emailType.value;
			}
		}
		return null;
	}
	// 省略 get set
}

四、郵件傳送封裝

1、純文字郵件傳送

(1)、程式碼封裝

/**
 * 郵箱傳送模式01:純文字格式
 */
public static void sendEmail01(String receiver, String title, String body) throws Exception {
	Properties prop = new Properties();
	prop.setProperty("mail.host", EmailParam.emailHost);
	prop.setProperty("mail.transport.protocol", EmailParam.emailProtocol);
	prop.setProperty("mail.smtp.auth", EmailParam.emailAuth);
	//使用JavaMail傳送郵件的5個步驟
	//1、建立session
	Session session = Session.getInstance(prop);
	//開啟Session的debug模式,這樣就可以檢視到程式傳送Email的執行狀態
	session.setDebug(true);
	//2、通過session得到transport物件
	Transport ts = session.getTransport();
	//3、使用郵箱的使用者名稱和密碼連上郵件伺服器,傳送郵件時,發件人需要提交郵箱的使用者名稱和密碼給smtp伺服器,使用者名稱和密碼都通過驗證之後才能夠正常傳送郵件給收件人。
	ts.connect(EmailParam.emailHost, EmailParam.emailSender, EmailParam.password);
	//4、建立郵件
	// Message message = createEmail01(session,receiver,title,body);
	Message message = createEmail01(session, receiver, title, body);
	//5、傳送郵件
	ts.sendMessage(message, message.getAllRecipients());
	ts.close();
}
/**
 * 建立文字郵件
 */
private static MimeMessage createEmail01(Session session, String receiver, String title, String body)
throws Exception {
	//建立郵件物件
	MimeMessage message = new MimeMessage(session);
	//指明郵件的發件人
	String nick = javax.mail.internet.MimeUtility.encodeText(EmailParam.emailNick);
	message.setFrom(new InternetAddress(nick + "<" + EmailParam.emailSender + ">"));
	//指明郵件的收件人
	message.setRecipient(Message.RecipientType.TO, new InternetAddress(receiver));
	//郵件的標題
	message.setSubject(title);
	//郵件的文字內容
	message.setContent(body, "text/html;charset=UTF-8");
	//返回建立好的郵件物件
	return message;
}

(2)、執行效果圖

2、文字+圖片+附件郵件

(1)、程式碼封裝

/**
 * 郵箱傳送模式02:複雜格式
 */
public static void sendEmail02(String receiver, String title, String body) throws Exception {
	Properties prop = new Properties();
	prop.setProperty("mail.host", EmailParam.emailHost);
	prop.setProperty("mail.transport.protocol", EmailParam.emailProtocol);
	prop.setProperty("mail.smtp.auth", EmailParam.emailAuth);
	//使用JavaMail傳送郵件的5個步驟
	//1、建立session
	Session session = Session.getInstance(prop);
	//開啟Session的debug模式,這樣就可以檢視到程式傳送Email的執行狀態
	session.setDebug(true);
	//2、通過session得到transport物件
	Transport ts = session.getTransport();
	//3、使用郵箱的使用者名稱和密碼連上郵件伺服器,傳送郵件時,發件人需要提交郵箱的使用者名稱和密碼給smtp伺服器,使用者名稱和密碼都通過驗證之後才能夠正常傳送郵件給收件人。
	ts.connect(EmailParam.emailHost, EmailParam.emailSender, EmailParam.password);
	//4、建立郵件
	// Message message = createEmail01(session,receiver,title,body);
	Message message = createEmail02(session, receiver, title, body);
	//5、傳送郵件
	ts.sendMessage(message, message.getAllRecipients());
	ts.close();
}
private static MimeMessage createEmail02(Session session, String receiver, String title, String body)
throws Exception {
	//建立郵件物件
	MimeMessage message = new MimeMessage(session);
	//指明郵件的發件人
	String nick = javax.mail.internet.MimeUtility.encodeText(EmailParam.emailNick);
	message.setFrom(new InternetAddress(nick + "<" + EmailParam.emailSender + ">"));
	//指明郵件的收件人
	message.setRecipient(Message.RecipientType.TO, new InternetAddress(receiver));
	//郵件的標題
	message.setSubject(title);
	//文字內容
	MimeBodyPart text = new MimeBodyPart();
	text.setContent(body, "text/html;charset=UTF-8");
	//圖片內容
	MimeBodyPart image = new MimeBodyPart();
	image.setDataHandler(new DataHandler(new FileDataSource("ware-email-send/src/gzh.jpg")));
	image.setContentID("gzh.jpg");
	//附件內容
	MimeBodyPart attach = new MimeBodyPart();
	DataHandler file = new DataHandler(new FileDataSource("ware-email-send/src/gzh.zip"));
	attach.setDataHandler(file);
	attach.setFileName(file.getName());
	//關係:正文和圖片
	MimeMultipart multipart1 = new MimeMultipart();
	multipart1.addBodyPart(text);
	multipart1.addBodyPart(image);
	multipart1.setSubType("related");
	//關係:正文和附件
	MimeMultipart multipart2 = new MimeMultipart();
	multipart2.addBodyPart(attach);
	// 全文內容
	MimeBodyPart content = new MimeBodyPart();
	content.setContent(multipart1);
	multipart2.addBodyPart(content);
	multipart2.setSubType("mixed");
	// 封裝 MimeMessage 物件
	message.setContent(multipart2);
	message.saveChanges();
	// 本地檢視檔案格式
	message.writeTo(new FileOutputStream("F:\\MixedMail.eml"));
	//返回建立好的郵件物件
	return message;
}

(2)、執行效果

3、實現非同步傳送

(1)、配置非同步執行執行緒

package com.email.send.util;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
 * 定義非同步任務執行執行緒池
 */
@Configuration
public class TaskPoolConfig {
    @Bean("taskExecutor")
    public Executor taskExecutor () {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心執行緒數10:執行緒池建立時候初始化的執行緒數
        executor.setCorePoolSize(10);
        // 最大執行緒數20:執行緒池最大的執行緒數,只有在緩衝佇列滿了之後才會申請超過核心執行緒數的執行緒
        executor.setMaxPoolSize(15);
        // 緩衝佇列200:用來緩衝執行任務的佇列
        executor.setQueueCapacity(200);
        // 允許執行緒的空閒時間60秒:當超過了核心執行緒數之外的執行緒在空閒時間到達之後會被銷燬
        executor.setKeepAliveSeconds(60);
        // 執行緒池名的字首:設定好了之後可以方便定位處理任務所在的執行緒池
        executor.setThreadNamePrefix("taskExecutor-");
        /*
        執行緒池對拒絕任務的處理策略:這裡採用了CallerRunsPolicy策略,
        當執行緒池沒有處理能力的時候,該策略會直接在 execute 方法的呼叫執行緒中執行被拒絕的任務;
        如果執行程式已關閉,則會丟棄該任務
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 設定執行緒池關閉的時候等待所有任務都完成再繼續銷燬其他的Bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 設定執行緒池中任務的等待時間,如果超過這個時候還沒有銷燬就強制銷燬,以確保應用最後能夠被關閉,而不是阻塞住。
        executor.setAwaitTerminationSeconds(600);
        return executor;
    }
}

(2)、業務方法使用

注意兩個註解 @Component @Async("taskExecutor")

@Component
@Service
public class EmailServiceImpl implements EmailService {
    @Async("taskExecutor")
    @Override
    public void sendEmail(String emailKey, SendEmailModel model) {
        try{
            // 非同步執行
            Thread.sleep(1000);
            String textBody = EmailUtil.convertTextModel(BodyType.getByCode(emailKey),"知了","一笑");
            // 傳送文字郵件
            EmailUtil.sendEmail01(model.getReceiver(), EmailType.getByCode(emailKey),textBody);
            // 傳送複雜郵件:文字+圖片+附件
            String body = "自定義圖片:<img src="cid:gzh.jpg">,網路圖片:<img src="https://oscimg.oschina.net/oscnet/8800276_184927469000_2.png">";
            // EmailUtil.sendEmail02(model.getReceiver(),"文字+圖片+附件",body);
        } catch (Exception e){
            e.printStackTrace();
        }

    }
}

(3)、啟動類註解

@EnableAsync

@EnableAsync
@SpringBootApplication
public class EmailApplication {
    public static void main(String[] args) {
        SpringApplication.run(EmailApplication.class,args) ;
    }
}

五、原始碼地址

GitHub地址:知了一笑
https://github.com/cicadasmile/middle-ware-parent
碼雲地址:知了一笑
https://gitee.com/cicadasmile/middle-ware-parent

相關推薦

SpringBoot2.0高階案例(03)整合 JavaMail ,實現非同步傳送郵件

本文原始碼 碼雲地址:知了一笑 https://gitee.com/cicadasmile/middle-ware-parent

SpringBoot2.0高階案例(02) 整合 RocketMQ ,實現請求非同步處理

本文原始碼 碼雲地址:知了一笑 https://gitee.com/cicadasmile/middle-ware-parent

SpringBoot2.0高階案例(06)整合 QuartJob ,實現定時器實時管理

一、QuartJob簡介 1、一句話描述 Quartz是一個完全由java編寫的開源作業排程框架,形式簡易,功能強大。 2、核心A

SpringBoot2.0高階案例(05)整合 Swagger2 ,構建介面管理介面

一、Swagger2簡介 1、Swagger2優點 整合到Spring Boot中,構建強大RESTful API文件。省去介面文

SpringBoot2.0高階案例(09)整合 ElasticSearch框架,實現高效能搜尋引擎

本文原始碼 碼雲地址:知了一笑 https://gitee.com/cicadasmile/middle-ware-parent

SpringBoot2.0高階案例(12)整合 SpringSecurity 框架,實現使用者許可權安全管理

一、Security簡介 1、基礎概念 Spring Security是一個能夠為基於Spring的企業應用系統提供宣告式的安全訪

SpringBoot2.0高階案例(10)整合 JWT 框架,解決Token跨域驗證問題

GitHub原始碼地址:知了一笑 https://github.com/cicadasmile/middle-ware-paren

SpringBoot2.0高階案例(08)整合 Dubbo框架 ,實現RPC服務遠端呼叫

一、Dubbo框架簡介 1、框架依賴 圖例說明: 1)圖中小方塊 Protocol, Cluster, Proxy, Servi

SpringBoot2.0高階案例(07) 整合Redis叢集 ,實現訊息佇列場景

本文原始碼 GitHub地址:知了一笑 https://github.com/cicadasmile/middle-ware-pa

SpringBoot2高階案例(11)整合 FastDFS 中介軟體,實現檔案分散式管理

一、FastDFS簡介 1、FastDFS作用 FastDFS是一個開源的輕量級分散式檔案系統,它對檔案進行管理,功能包括:檔案儲

SpringBoot--01.SpringBoot2.0入門案例

一、SpringBoot簡介 1、SpringBoot概述(簡化配置、開箱即用) - 為所有 Spring 的開發者提供一個非常快速的、廣泛接受的入門體驗 - 開箱即用(啟動器starter-其實就是SpringBoot提供的一個jar包),但通過自己設定參 (.properties),

微服務 SpringBoot 2.0(九)整合Mybatis

我是SQL小白,我選Mybatis —— Java面試必修 引言 在第五章我們已經整合了Thymeleaf頁面框架,第七章也整合了JdbcTemplate,那今天我們再結合資料庫整合Mybatis框架 在接下來的文章中,我會用一個開源的部落格原始碼來做講解

Springboot2.0啟動報錯java.lang.NoClassDefFoundError: ch/qos/logback/core/spi/LifeCycle

springboot2.0啟動報錯: java.lang.NoClassDefFoundError: ch/qos/logback/core/spi/LifeCycle     at java.lang.ClassLoader.defineClass1(Native Met

springBoot2.0 MyBatis Redis 及RedisCache 整合附demo

springboot2.0 + mybatis 或者 springboot2.0 + redis 在網上可以找到很多資料,但是大都不全或者有這樣那樣的問題,所以便自己動手寫了個demo,能只用 yaml 配置的,儘量不再寫程式碼。 pom.xml <?xml ver

springboot學習入門簡易版四---springboot2.0靜態資源訪問及整合freemarker視圖層

nbsp 規則 pri stat path 整合 位置 啟動程序 -- 2.4.4 SpringBoot靜態資源訪問(9) Springboot默認提供靜態資源目錄位置需放在classpath下,目錄名需要符合如下規則 /static /public /resour

微服務架構案例(03)資料庫選型簡介,業務資料規劃設計

更新進度(共6節): 01:專案技術選型簡介,架構圖解說明 02:業務架構設計,系統分層管理 03:資料庫選型,業務資料設計規劃 一、資料庫選擇 1、資料庫分類 資料庫型別 常見資料庫 關係型 MySQL、Oracle、DB2、SQLServer等。 非關係型 Hbase、Red

精通SpringBoot——第七篇整合Redis實現快取

專案中用到快取是很常見的事情, 快取能夠提升系統訪問的速度,減輕對資料庫的壓力等好處。今天我們來講講怎麼在spring boot 中整合redis 實現對資料庫查詢結果的快取。 首先第一步要做的就是在pom.xml檔案新增spring-boot-starter-data-redis。 要整合快取,必

ionic學習(七)問答社群03登入功能實現 總結篇

登入功能整整搞了一天,期間各種錯誤不斷,剛接觸ionic,對Angular也不太熟悉,沒正規的學過html,css,js等前端知識。 整理一下流程: 1.製作登入頁面 2.構造登入等待遮罩層和登入錯誤遮罩層 3.通過storge儲存登入的資訊 4.通過判斷是否登入,並顯示相應頁面 備

Spring Cloud 安全整合OAuth2實現身份認證和單點登入

1、概述 Spring Cloud 的安全模組可以為Spring Boot應用提供基於令牌的安全特性。具體講就是支援OAuth2協議來實現單點登入(SSO),可以很方便地在資源服務之間傳遞身份令牌,以及使用嵌入式的ZUUL代理來配置下游服務的認證。 在這篇文

最課程階段大作業03用半天實現淘寶首頁?

       每一個在最課程學習的學生,到了最後幾乎都會來問我一個問題:老師,是不是實際的開發中,都會有一個前端開發工程師,把靜態頁面做好了,然後才交給我們後臺開發啊?        我只能說:你想多了。        我知道你這麼問的意思,HTML+CSS+各類前端框架學習起來太繁瑣了,是不是就沒有