Spring Boot筆記(七) springboot 集成 JavaMail 實現郵箱認證


個人博客網:https://wushaopei.github.io/    (你想要這里多有)

一、JavaMail

1、什么是JavaMail?

JavaMail,顧名思義,提供給開發者處理 電子郵件相關的編程接口。它是Sun發布的用來處理email的API。它可以方便的執行一些常用的郵件傳輸。我們可以基於JavaMaiil開發出類似於 Microsoft Outlook的應用程序。

2、關於要使用JavaMail的原因?

基於現在WEB開發中對JavaMail的需求,例如:

用戶注冊后,網站發送一封激活郵件驗證;

用戶過生日,系統發送生日祝福郵件;

將最新活動和優惠以郵件的形式告知會員等等........

以上的需求都需要通過編程語言實現發送郵件功能,而JavaMail便能滿足這一需求。

3、電子郵箱及郵件服務器

什么是電子郵箱?

  電子郵箱(E-mail 地址) 需要在郵件服務器上進行申請,確切的說,電子郵箱其實就是用戶在郵件服務器上申請的一個賬戶,用戶在郵件服務器上申請了一個賬號后,郵件服務器就會為這個賬號分配一定的空間,用戶從而可以使用這個賬號以及空間,發送電子郵件和保存別人發送過來的電子郵件。

什么是郵箱服務器?

服務器指的是一台電腦安裝了一個服務器軟件,那么這台電腦就可以稱為是WEB服務器,那么同樣的一台電腦安裝了郵件服務器軟件,那么這台電腦稱為是郵件服務器

基於互聯網的電子郵件功能:

要在Internet上提供電子郵件功能,必須有專門的電子郵件服務器,例如目前網絡上提供郵件服務的廠商:新浪、搜狐、網易等等他們都有自己的郵件服務器

4、郵件收發協議

(1)SMTP協議(發送郵件)

 簡單郵件傳輸協議 (Simple Mail Transfer Protocol, SMTP) 是在Internet傳輸email事實標准。(百度百科)

SMTP是一個相對簡單的基於文本協議。在其之上指定了一條消息的一個或多個接收者(在大多數情況下被確認是存在的),然后消息文本會被傳輸。可以很簡單地通過telnet程序來測試一個SMTP服務器。SMTP使用TCP端口25。要為一個給定的域名決定一個SMTP服務器,需要使用MX (Mail eXchange) DNS。(百度百科)

用戶臉上郵件服務器后,要想給它發送一封電子郵件,需要遵循一定的通訊規則,SMTP協議就是用於定義這種規則的。因此,通常我們也把處理用戶SMTP請求(郵件發送請求)的郵件服務器稱之為SMTP服務器。

(2)POP3協議(接收郵件)

POP3,全名為“Post Office Protocol - Version 3”,即“郵局協議版本3”。是TCP/IP協議族中的一員,由RFC1939 定義。本協議主要用於支持使用客戶端遠程管理在服務器上的電子郵件。提供了SSL加密的POP3協議被稱為POP3S。(百度百科)

POP 協議支持“離線”郵件處理。其具體過程是:郵件發送到服務器上,電子郵件客戶端調用郵件客戶機程序以連接服務器,並下載所有未閱讀的電子郵件。這種離線訪問模式是一種存儲轉發服務,將郵件從郵件服務器端送到個人終端機器上,一般是PC機或 MAC。一旦郵件發送到 PC 機或MAC上,郵件服務器上的郵件將會被刪除。但目前的POP3郵件服務器大都可以“只下載郵件,服務器端並不刪除”,也就是改進的POP3協議。(百度百科)

同樣,用戶若想從郵件服務器管理的電子郵件中接受一封電子郵件的話,他臉上郵件服務器后,也需要遵循一定的通訊格式,POP3協議用於定義這種通訊格式。

因而,通常我們也把處理用戶POP3請求(郵件接受請求)的郵件服務器稱之為POP3服務器。

(3)郵件收發過程的介紹:

郵件的發送、接受,在客戶端軟件中,由SMTP服務器進行發送操作,接受是由POP3服務器進行接收。

1、郵件發送協議-SMTP,默認端口號25

用於把用戶郵件從一個服務器轉到下一個服務器

2、郵件接收協議-POP3,默認端口號110

用於支持使用客戶端遠程管理在服務器上的電子郵件

二、郵件發送代碼實現

1、環境搭建

(1)創建數據庫和表

CREATE TABLE `NewTable` ( `uid` int(11) NOT NULL AUTO_INCREMENT , `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `password` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `nickname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `email` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `state` int(11) NULL DEFAULT NULL , `code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , PRIMARY KEY (`uid`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=22 ROW_FORMAT=DYNAMIC ;

(2)創建一個springboot工程,創建相應的包,並配置相應的pom.xml依賴

pom.xml

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<!--<version>5.1.41</version> -->
			<version>8.0.13</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>RELEASE</version>
			<scope>test</scope>
		</dependency>
		<!-- lombok 簡化 java 代碼 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<!--郵箱發送-->

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

(3)創建User類並配置application.yml

User類:

@Data public class User { private Integer uid; private String username; private String password; private String nickname; private String email; private Integer state; private String code; }

application.yml

server:
  port: 80

spring:
  datasource:
    url: jdbc:mysql://localhost:3333/regist_web?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
    username: root
    password: root
    driver-class-name:  com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath*:/mybatis/mappers/*Mapper.xml
  type-aliases-package: com.entities

#郵件配置(發件人)
email:
  host: smtp.163.com
  username: 1***9746***@163.com
  password: 1***9746**
  senderName: 1***9746***@163.com

(4)設計注冊頁面

index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="jquery-1.11.3.js"></script> </head> <body> <h1>用戶注冊的頁面</h1> <form action="/get/getParam/user" method="get"> <table width="600" border="1"> <tr> <td>用戶名</td> <td><input type="text" name="username"/></td> </tr> <tr> <td>密碼</td> <td><input type="password" name="password"/></td> </tr> <tr> <td>昵稱</td> <td><input type="text" name="nickname"/></td> </tr> <tr> <td>郵箱</td> <td><input type="text" name="email"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="注冊"/></td> </tr> </table> </form> </body> </html>

(5)Handler :創建接口,接收form 表單數據並進行封裝,並經過dao 層 添加到對應的數據庫表中

@ResponseBody @RequestMapping ("/get/getParam/user") public Object getParam(@RequestParam("username")String username, @RequestParam("password")String password, @RequestParam("nickname")String nickname, @RequestParam("email")String email, HttpServletRequest request ) { Map<String,Object> map = null; try { request.setCharacterEncoding("UTF-8"); if(username.equals("") && password.equals("") && nickname.equals("") && email.equals("")){ return "請不要留空"; } //封裝數據 User user = new User(); user.setUsername(username); user.setPassword(password); user.setNickname(nickname); user.setEmail(email); user.setState(0);// 0 : 未激活 1: 已經激活 //使用 UUID 隨機生成激活碼 String code = UUIDUtils.getUUID()+ UUIDUtils.getUUID(); user.setCode(code); map = new HashMap<>(); //調用業務層處理數據 userService.addUser(user); map.put("state","0"); map.put("message", "發送成功"); //頁面跳轉 } catch (Exception e) { // map.put("state","1"); map.put("message", "發送失敗"); e.printStackTrace(); throw new RuntimeException(); } return map; }

(6)創建一個UUIDUtils 工具類,使用UUID隨機生成激活碼

/** * @ClassName UUIDUtils 生成隨機字符串工具類 * @Description TODO * @Author wushaopei * @Date 2019/9/8 13:52 * @Version 1.0 */ public class UUIDUtils { public static String getUUID(){ return UUID.randomUUID().toString().replace("-",""); } } 

(7)創建郵箱參數實體EmailConfig.java和發送郵件工具類MailUtils.java

EmailConfig.java

package com.utils; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @ClassName EmailConfig * @Description TODO * @Author wushaopei * @Date 2019/7/25 10:24 * @Version 1.0 */ @Configuration @ConfigurationProperties(prefix = "email", ignoreUnknownFields = false) //@PropertySource("classpath:/application.yml") public class EmailConfig { private String host; private String username; private String password; private String senderName; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSenderName() { return senderName; } public void setSenderName(String senderName) { this.senderName = senderName; } @Override public String toString() { return "EmailConfig{" + "host='" + host + '\'' + ", username='" + username + '\'' + ", password='" + password + '\'' + ", senderName='" + senderName + '\'' + '}'; } }

MailUtils.java

package com.utils; import com.mysql.cj.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.Properties; /** * @ClassName MailUtils * @Description TODO * @Author wushaopei * @Date 2019/9/8 14:49 * @Version 1.0 */ @Component public class MailUtils { @Autowired private EmailConfig emailConfig; private final Logger logger = LoggerFactory.getLogger(MailUtils.class); /** * 發送郵件的方法 * @Param to :給誰發郵件 * @Param code : 郵件的激活碼 * @Param subject : 主題 * @Param text : 內容 * */ public void sendMail(String toEmail, String code,final String subject,final String text){ try{ //1、創建郵件對象 JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); //2、發郵件人郵箱 javaMailSender.setUsername(emailConfig.getUsername()); //3、發郵件人郵箱密碼(默認使用客戶端的授權碼) javaMailSender.setPassword(emailConfig.getPassword()); //4、設置郵件服務器主機名 SMTP服務器地址 javaMailSender.setHost(emailConfig.getHost()); //5、SMTP服務器: 默認端口 javaMailSender.setPort(25); //6、//發送郵件協議名稱 javaMailSender.setProtocol("smtp"); //7、編碼格式 javaMailSender.setDefaultEncoding("UTF-8"); //8、創建連接對象,連接到郵箱服務器 Properties mailProperties = new Properties(); //發送服務器需要身份驗證,要采用指定用戶名密碼的方式去認證 mailProperties.put("mail.smtp.auth", true); mailProperties.put("mail.smtp.starttls.enable", true); //9、添加連接對象到郵件對象中 javaMailSender.setJavaMailProperties(mailProperties); int count = 1; //10、創建 //可以發送幾封郵件:可以這里 for循環多次 MimeMessage mimeMessage = getMimeMessage(toEmail,subject,text, javaMailSender); //11、發送郵件 javaMailSender.send(mimeMessage); logger.info("發送 第"+ count + "封郵件" ); count ++; logger.info("發往 "+toEmail+" 郵件發送成功"); } catch (MessagingException e) { logger.error("發往 "+toEmail+" 郵件發送異常", e); } } //聲明一個Message對象(代表一封郵件),從session中創建 private MimeMessage getMimeMessage(String toEmail,String subject,String text, JavaMailSenderImpl javaMailSender) throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); //發件人 mimeMessageHelper.setFrom(emailConfig.getSenderName()); //收件人 : 可以發送給多個收件人,該方法有一個重載的 數組形參 mimeMessageHelper.setTo(toEmail); // mimeMessage.setContent(); //郵件主題 mimeMessageHelper.setSubject(subject); //郵件內容 mimeMessageHelper.setText(text, true); return mimeMessage; } } 

(8)在(4)中的接口接收注冊參數並寫入數據庫后,進行激活郵件的發送

        //調用業務層處理數據
        userService.addUser(user);

UserServiceimpl.java

        @Override public Integer addUser(User user) { //將數據存入到數據庫 Integer integer = userMapper.addUser(user); //發送一封激活郵件 mailUtils.sendMail("18620307785@163.com",user.getCode(),"來自郵箱測試接口郵件","<h1>來自wto網站激活郵件,激活請點擊以下鏈接:</h1><h3><a href='http://wj7ei8.natappfree.cc/regist_web/activateServlet?code="+user.getCode()+"'>http://wj7ei8.natappfree.cc/regist_web/activateServlet?code="+user.getCode()+"</a></h3>"); return integer; }

完整 業務層代碼:

UserService.java


public interface UserService { List<User> getAll(); Integer addUser(User user); User findByCode(String code); void updateUser(User user); }

UserServiceImpl.java


@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private MailUtils mailUtils; public List<User> getAll() { return userMapper.selectAll(); } @Override public Integer addUser(User user) { //將數據存入到數據庫 Integer integer = userMapper.addUser(user); //發送一封激活郵件 mailUtils.sendMail("18620307785@163.com",user.getCode(),"來自郵箱測試接口郵件","<h1>來自wto網站激活郵件,激活請點擊以下鏈接:</h1><h3><a href='http://wj7ei8.natappfree.cc/regist_web/activateServlet?code="+user.getCode()+"'>http://wj7ei8.natappfree.cc/regist_web/activateServlet?code="+user.getCode()+"</a></h3>"); return integer; } @Override public User findByCode(String code) { return userMapper.findByCode(code); } @Override public void updateUser(User user) { userMapper.updateUser(user); } }

(9)UserMapper.java 和 UserMapper.xml

@Component @Mapper public interface UserMapper { List<User> selectAll(); Integer addUser(User user); User findByCode(@Param("code") String code); void updateUser(User user); }

 

	<select id="selectAll"
		resultType="User">
		select *
		from
		user
	</select>
	<insert id="addUser" parameterType="com.entities.User"
			useGeneratedKeys="true"
			keyProperty="id" >
		INSERT INTO user (
			username,
			password,
			nickname,
			email,
			state,
			code
		)
		VALUES
			(
				#{username},
				#{password},
				#{nickname},
				#{email},
				#{state},
				#{code}
			)
	</insert>

	<select id="findByCode"
			resultType="com.entities.User">
		SELECT
			*
		FROM
			user u
		WHERE
			u. CODE = #{code}
	</select>

	<update id="updateUser" parameterType="com.entities.User">
		UPDATE user
		<trim prefix="set" suffixOverrides=",">
			<if test="username != null">
				username=#{username},
			</if>
			<if test="password != null">
				password=#{password},
			</if>
			<if test="nickname != null">
				nickname=#{nickname},
			</if>
			<if test="email!=null">
				email=#{email},
			</if>
				state=#{state},
				code=#{code}
		</trim>
		WHERE uid=#{uid}
	</update>

(10)創建用戶激活接口:

  /* * 用戶激活的 接口 * */ @ResponseBody @GetMapping("/regist_web/activateServlet") public Object activateServlet(@RequestParam("code")String code, HttpServletRequest request,HttpServletResponse response) { Map<String,Object> map = null; try { map = new HashMap<>(); User user = userService.findByCode(code); if(user != null){ //已經查詢到,修改用戶的狀態 user.setState(1);//已經激活 user.setCode(null); //激活后修改用戶的激活碼及狀態 userService.updateUser(user); map.put("state","0"); map.put("message", "您的激活碼已激活!請去登錄"); }else { //根據激活碼沒有查詢到該用戶 // map.put("state","0"); map.put("message", "您的激活碼有誤!請重新激活"); } }catch (Exception e){ e.printStackTrace(); map.put("state","1"); map.put("message", "發送失敗"); throw new RuntimeException(); } return map; } 

小結:

發送激活郵件正文,正文內容使用 html 的語法進行修飾,用戶郵箱POP3接受到郵件后會自動根據標簽及樣式進行解析。

激活郵件的原理:

發送郵件給用戶,用戶根據接收到的郵件的連接點擊並跳轉到對應的controller請求接口執行code驗證碼查詢到用戶,並根據當前激活碼的作用對用戶執行激活賬戶、業務等操作!!!

https://github.com/wushaopei/SPRING_BOOT/tree/master/spring-boot-JSP-email

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM