概述
這個技術是做什么?學習該技術的原因,技術的難點在哪里。
這個技術能使項目具備發送郵件的功能,這個技術我是作為技術儲備來學習的,沒想到在學習后沒多久就能夠有用武之地。該項技術總體難度不大,硬要說難的地方就在於整合模板引擎發送模板郵件,因為還要同時了解一些模板引擎的知識,不過如果有JSP相關知識會容易應付得多。
整合郵件發送功能
Spring Boot 2.x集成了mail模塊
在pom.xml中引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
郵箱配置
一些必要的名詞解釋
-
什么是POP3、SMTP和IMAP?
他們是三種郵件協議。簡單來說,POP3和IMAP是用來從服務器上下載郵件的。SMTP適用於發送或中轉信件時找到下一個目的地。所以我們發送郵件應該使用SMTP協議。 -
什么是郵箱客戶端授權碼?
郵箱客戶端授權碼是為了避免郵箱密碼被盜后,盜號者通過客戶端登錄郵箱而設計的安防功能。
QQ郵箱配置
網頁登錄QQ郵箱→設置→開啟相應服務並生成授權碼
spring boot配置:
spring: mail: host: smtp.qq.com #發送郵件服務器 username: xx@qq.com #QQ郵箱 password: xxxxxxxxxxx #客戶端授權碼 protocol: smtp #發送郵件協議 properties.mail.smtp.auth: true properties.mail.smtp.port: 465 #端口號465或587 properties.mail.display.sendmail: aaa #可以任意 properties.mail.display.sendname: bbb #可以任意 properties.mail.smtp.starttls.enable: true properties.mail.smtp.starttls.required: true properties.mail.smtp.ssl.enable: true #開啟SSL default-encoding: utf-8
網易系(126/163/yeah)郵箱配置
網頁登錄網易郵箱→設置→POP3/SMTP/IMAP
spring boot配置:
spring: mail: host: smtp.126.com #發送郵件服務器 username: xx@126.com #網易郵箱 password: xxxxxxxx #客戶端授權碼 protocol: smtp #發送郵件協議 properties.mail.smtp.auth: true properties.mail.smtp.port: 994 #465或者994 properties.mail.display.sendmail: aaa #可以任意 properties.mail.display.sendname: bbb #可以任意 properties.mail.smtp.starttls.enable: true properties.mail.smtp.starttls.required: true properties.mail.smtp.ssl.enable: true #開啟SSL default-encoding: utf-8 from: xx@126.com
- 126郵箱SMTP服務器地址:smtp.126.com
- 163郵箱SMTP服務器地址:smtp.163.com
- yeah郵箱SMTP服務器地址:smtp.yeah.net
發送簡單的文本郵件
寫個郵件服務Service
@Service public class MailService { // Spring官方提供的集成郵件服務的實現類,目前是Java后端發送郵件和集成郵件服務的主流工具。 @Resource private JavaMailSender mailSender; // 從配置文件中注入發件人的姓名 @Value("${spring.mail.username}") private String fromEmail; /** * 發送文本郵件 * * @param to 收件人 * @param subject 標題 * @param content 正文 * @throws MessagingException */ public void sendSimpleMail(String to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(fromEmail); // 發件人 message.setTo(to); message.setSubject(subject); message.setText(content); mailSender.send(message); } }
在業務中調用該服務的方法即可
mailService.sendSimpleMail("xxxxxx@xx.com","普通文本郵件","普通文本郵件內容");
發送html郵件
為了方便,在原來的Service里直接添加一個方法
/** * 發送html郵件 */ public void sendHtmlMail(String to, String subject, String content) throws MessagingException { //注意這里使用的是MimeMessage MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); //第二個參數:格式是否為html helper.setText(content, true); mailSender.send(message); }
調用該方法,直接傳入html代碼的字符串作為正文參數:
mailService.sendHtmlMail("xxxxxx@xx.com","一封html測試郵件","
"<div style=\"text-align: center;position: absolute;\" >\n"
+"<h3>\"一封html測試郵件\"</h3>\n"
+ "<div>一封html測試郵件</div>\n"
+ "</div>");
像上面直接傳遞html字符串發送html郵件,在java類里寫html代碼總有點怪怪的,而且有很明顯的缺點,若是要用相同樣式發送不同的內容,代碼冗余度就會增加;而且若是需要發送一個復雜的html頁面,代碼看起來就一團亂麻,而且不方便調整郵件的樣式。
我們希望html和java分離開,在java里就只管java,頁面代碼乖乖到頁面文件里面,需要時直接調取該頁面文件,整合模板引擎就是一個不錯的解決方案。👇
發送基於模板的郵件(以模板引擎freemarker為例)
該方法本質上還是發送html郵件,只不過是有一個把模板轉換成html字符串的過程,thymeleaf也可以實現。這個方法還能使你的系統發出的郵件更加美觀。
說明:這里不詳細介紹freemarker的內容,在這里只描述它的一個使用場景——生成電子郵件,想要進一步了解freemarker請行學習
添加依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
springboot配置
spring:
#freemarker默認存放路徑
freemarker:
template-loader-path: classpath:/templates/freemarker/
suffix: .ftl
cache: false
charset: UTF-8
settings:
classic_compatible: true
在存放模板的文件夾下寫一個html模板
內容如下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8" /> <title>freemarker簡單示例</title> </head> <body> <h1>Hello Freemarker</h1> <div>My name is ${myname}</div> </body> </html>
仍然為了方便,在原來的Service里直接添加代碼
@Autowired private FreeMarkerConfigurer freeMarkerConfigurer; @Test public void sendTemplateMail(String to, String subject, String template) throws IOException, TemplateException, MessagingException { // 獲得模板 Template template = freeMarkerConfigurer.getConfiguration().getTemplate(template); // 使用Map作為數據模型,定義屬性和值 Map<String,Object> model = new HashMap<>(); model.put("myname","ZYF"); // 傳入數據模型到模板,替代模板中的占位符,並將模板轉化為html字符串 String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template,model); // 該方法本質上還是發送html郵件,調用之前發送html郵件的方法 this.sendHtmlMail(to, subject, templateHtml); }
要用的時候調用即可
mailService.sendTemplateMail("xxxxx@xx.com", "基於模板的html郵件", "fremarkertemp.html");
發送帶附件的郵件
話不多說上代碼:
/** * 發送帶附件的郵件 */ public void sendAttachmentsMail(String to, String subject, String content, String filePath) throws MessagingException { MimeMessage message = mailSender.createMimeMessage(); //要帶附件第二個參數設為true MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(fromEmail); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); FileSystemResource file = new FileSystemResource(new File(filePath)); String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); helper.addAttachment(fileName, file); mailSender.send(message); }
調用時傳入文件路徑:
String filePath = "D:\\projects\\springboot\\template.png";
mailService.sendAttachmentsMail("xxxx@xx.com", "帶附件的郵件", "郵件中有附件", filePath);
郵箱服務實戰
這是我某次實踐中郵箱服務的運用,目的是為了能夠定時發送郵件,由於發送郵件是耗時操作,為了不妨礙系統處理用戶請求,添加了@Async注解,定時任務將會在獨立的線程中被執行,下面放上鏈接:
我的踩坑記錄
郵件服務器連接失敗
org.springframework.mail.MailSendException: Mail server connection failed; ... nested exception is: java.net.UnknownHostException: smtp.163.com ...
-
網絡問題
控制台輸入
ping smtp.163.com
看看是否能ping通; -
配置問題
檢查一下application.yml的郵件服務器配置有沒有拼寫或格式錯誤(比如多按了一個空格);
開啟SSL時使用587端口時是無法連接QQ郵件服務器的,請使用465端口。
授權失敗
org.springframework.mail.MailAuthenticationException: Authentication failed;nested exception is javax.mail.AuthenticationFailedException: 550 User has no permission ...
這個坑是我在教同學時遇到的
按照上文去打開郵箱的stmp服務即可解決
消息發送失敗
org.springframework.mail.MailSendException: Failed messages: com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM 163 smtp11,D8CowACX7CmSHB5b3SrlCA--.26635S3 1528700051,please see http://mail.163.com/help/help_spam_16.htm?ip=182.138.102.204&hostid=smtp11&time=1528700051 ...
點進報錯信息提供的網址瞧瞧,是網易官方的退信代碼說明,也就是說我們發送的消息被退回來了:
注意到報錯信息的退信代碼554,看看554是啥來頭:
原來是被識別為垃圾郵件了,檢查一下郵件的主題及內容,使用合法信息,我當時是因為郵件內容包含test、測試這些字眼所以被攔截了。
轉載自:https://www.cnblogs.com/sillyby/p/13131340.html