郵件是許多項目里都需要用到的功能,之前一直都是用JavaMail來發,現在Spring框架為使用JavaMailSender接口發送電子郵件提供了一個簡單的抽象,Spring Boot為它提供了自動配置以及啟動模塊。springboot參考手冊介紹:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-email
作為發送方,首先需要開啟POP3/SMTP服務,登錄郵箱后前往設置進行開啟,開啟后取得授權碼。
POP3 :
POP3是Post Office Protocol 3的簡稱,即郵局協議的第3個版本,規定怎樣將個人計算機連接到Internet的郵件服務器和下載電子郵件的電子協議。是因特網電子郵件的第一個離線協議標準,POP3允許用戶從服務器上把郵件存儲到本地主機(即自己的計算機)上,同時刪除保存在郵件服務器上的郵件,而POP3服務器則是遵循POP3協議的接收郵件服務器,用來接收電子郵件的。
SMTP:
SMTP 的全稱是“Simple Mail Transfer Protocol”,即簡單郵件傳輸協議。是一組用于從源地址到目的地址傳輸郵件的規范,通過來控制郵件的中轉方式。SMTP 協議屬于 TCP/IP 協議簇,幫助每臺計算機在發送或中轉信件時找到下一個目的地。SMTP 服務器就是遵循 SMTP 協議的發送郵件服務器。
maven引包,其中,郵件模板需要用到thymeleaf
<!-- springboot mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- thymeleaf模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- springboot web(MVC)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
appliaction.propertise配置文件
#設置服務端口
server.port=10010
# Email (MailProperties)
spring.mail.default-encoding=UTF-8
spring.mail.host=smtp.qq.com
spring.mail.username=huanzi.qch@qq.com #發送方郵件名
spring.mail.password=#授權碼
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
SpringBootMailServiceImpl.java
@Service
class SpringBootMailServiceImpl implements SpringBootMailService {
@Autowired
private JavaMailSender mailSender;
/**
* 發送方
*/
@Value("${spring.mail.username}")
private String from;
/**
* 發送簡單郵件
*
* @param to 接收方
* @param subject 郵件主題
* @param text 郵件內容
*/
@Override
public void sendSimpleMail(String to, String subject, String text) {
SimpleMailMessage message=new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
/**
* 發送HTML格式的郵件
*
* @param to 接收方
* @param subject 郵件主題
* @param content HTML格式的郵件內容
* @throws MessagingException
*/
@Override
public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
MimeMessage message=mailSender.createMimeMessage();
//true表示需要創建一個multipart message
MimeMessageHelper helper=new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(message);
}
/**
* 發送HTML格式的郵件,并可以添加附件
* @param to 接收方
* @param subject 郵件主題
* @param content HTML格式的郵件內容
* @param files 附件
* @throws MessagingException
*/
@Override
public void sendAttachmentsMail(String to, String subject, String content, List<File> files) throws MessagingException {
MimeMessage message=mailSender.createMimeMessage();
MimeMessageHelper helper=new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
//添加附件
for(File file : files){
helper.addAttachment(file.getName(), new FileSystemResource(file));
}
mailSender.send(message);
}
}
測試controller
@Autowired
private SpringBootMailService springBootMailService;
@Autowired
private TemplateEngine templateEngine;
@GetMapping("/index")
public String index() throws MessagingException {
//簡單郵件
springBootMailService.sendSimpleMail("1726639183@qq.com","Simple Mail","第一封簡單郵件");
//HTML格式郵件
Context context=new Context();
context.setVariable("username","我的小號");
springBootMailService.sendHtmlMail("1726639183@qq.com","HTML Mail",templateEngine.process("mail/mail",context));
//HTML格式郵件,帶附件
Context context2=new Context();
context2.setVariable("username","我的小號(帶附件)");
ArrayList<File> files=new ArrayList<>();
files.add(new File("C:\\Users\\Administrator\\Desktop\\上傳測試.txt"));
files.add(new File("C:\\Users\\Administrator\\Desktop\\上傳測試2.txt"));
springBootMailService.sendAttachmentsMail("1726639183@qq.com","Attachments Mail",templateEngine.process("mail/attachment",context2),files);
return "hello springboot!";
}
兩個html模板,路徑:myspringboot\src\main\resources\templates\mail\
mail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Mail Templates</title>
</head>
<body>
<h3><span th:text="${username}"></span>,你好!</h3>
<p style="color: red;">這是一封HTML格式的郵件。</p>
</body>
</html>
attachment.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Mail Templates Accessory</title>
</head>
<body>
<h3><span th:text="${username}"></span>,你好!</h3>
<p>這是一封HTML格式的郵件。請收下附件!</p>
</body>
</html>
Simple Mail
HTML Mail
Attachments Mail
本文章部分參考:https://www.cnblogs.com/yangtianle/p/8811732.html
代碼已經開源、托管到我的GitHub、碼云:
GitHub:https://github.com/huanzi-qch/springBoot
碼云:https://gitee.com/huanzi-qch/springBoot
作者:huanzi-qch
出處:https://www.cnblogs.com/huanzi-qch
若標題中有“轉載”字樣,則本文版權歸原作者所有。若無轉載字樣,本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利.
開啟郵箱 SMTP 服務
2) 在POP3/IMAP/SMAP/Exchage/CardDAV/CalDAV服務中,找到 POP3/SMTP 服務和 IMAP/SMTP 服務,點擊開啟。
使用 python 自帶的模塊:smptlib、email
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 發送郵件的步驟
import smtplib
from email.mime.text import MIMEText # 用來構造文本類型的郵件
from email.header import Header # 用來構造郵件的頭部
# 第一步:創建一個SMTP的對象
s=smtplib.SMTP()
# 第二步:連接到SMTP的服務器
host='smtp.163.com' # 設置163郵箱服務器,端口為:25
port=25
# host='smtp.qq.com' port=465 # 設置qq郵箱服務器,端口為:465
s.connect(host,port) # 連接服務器
# s.connect(host='smtp.163.com',port=25)
# 第三步:登錄SMTP服務器
mail_user='18814726725@163.com' # 163郵箱的用戶名
mail_pass='password' # 注意:此處填寫的是郵箱的SMTP服務器授權碼
s.login(user=mail_user,password=mail_pass)
# 第四步:構建郵件內容
content='使用python測試發送郵件' # 構建郵件內容
msg=MIMEText(content,_charset='utf8') # _charset 指定編碼格式
msg['Subject']=Header('測試報告','utf8') # 郵件主題
msg['From']='wl18814726725@163.com' # 發件人郵箱,可傳入列表,用于給多個人發送文件
msg['To']='1572533878@qq.com' # 收件人
# 第五步:發送郵件
s.sendmail(from_addr=msg['From'],to_addrs=msg['To'],msg=msg.as_string()) #將郵件內容轉換為字符串
import smtplib
from email.mime.text import MIMEText # 文本類型的郵件,用來構造郵件
from email.header import Header # 用來構造郵件的頭部
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart # 用來構造附件
# 發送郵件的步驟
# 第一步:創建一個SMTP的對象
s=smtplib.SMTP()
# 第二步:連接到SMTP的服務器
host='smtp.163.com' # 設置163郵箱服務器,端口為:25
port=25
# host='smtp.qq.com' # 設置qq郵箱服務器,端口為:465
s.connect(host,port) # 連接服務器
# 第三步:登錄SMTP服務器
mail_user='wl18814726725@163.com' # 163郵箱的用戶名
mail_pass='wl987654321' # 注意:此處填寫的是郵箱的SMTP服務器授權碼
s.login(user=mail_user,password=mail_pass)
# 構造文本郵件內容
content='使用python測試發送郵件' # 構建郵件內容
textcontent=MIMEText(content,_charset='utf8') # _charset 指定編碼格式
# 構造附件(二進制字節流形式)
part=MIMEApplication(open("report.html",'rb').read(),_subtype=None)
# part=MIMEApplication(open("report.html",'rb').read()) 需要查看_subtype=None 是否會引發異常
part.add_header('content-disposition', 'attachment', filename='report18.html') # 對方收到郵件之后,附件在郵件中顯示的名稱
# 封裝一封郵件
msg=MIMEMultipart()
# 加入文本內容
msg.attach(textcontent)
msg.attach(part)
# 發送郵件
msg['From']='wl18814726725@163.com' #發件人郵箱
msg['To']='1572533878@qq.com' #收件人
#第五步:發送郵件
s.sendmail(from_addr='wl18814726725@163.com',to_addrs='1572533878@qq.com',msg=msg.as_string()) # 將郵件內容轉換為字符串
import smtplib
from email.mime.text import MIMEText #文本類型的郵件,用來構造郵件
from email.header import Header #用來構造郵件的頭部
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart #用來構造附件
def send_email(filepath):
"""
:param filepath: #傳入報告文件的路徑
:return:
"""
# 發送郵件的步驟
# 第一步:創建一個SMTP的對象
s=smtplib.SMTP()
# 第二步:連接到SMTP的服務器
host='smtp.163.com' #設置163郵箱服務器,端口為:25
port=25
# host='smtp.qq.com' #設置qq郵箱服務器,端口為:465
s.connect(host,port) #連接服務器
# 第三步:登錄SMTP服務器
mail_user='wl18814726725@163.com' #163郵箱的用戶名
mail_pass='wl987654321' #注意:此處填寫的是郵箱的SMTP服務器授權碼
s.login(user=mail_user,password=mail_pass)
#構造文本郵件內容
content='使用python測試發送郵件' #構建郵件內容
textcontent=MIMEText(content,_charset='utf8') #_charset 指定編碼格式
#構造附件(二進制字節流形式)
part=MIMEApplication(open(filepath,'rb').read())
part.add_header('content-disposition', 'attachment', filename='report988.html') #對方收到郵件之后,附件在郵件中顯示的名稱
# 封裝一封郵件
msg=MIMEMultipart()
#加入附件和文本內容
msg.attach(textcontent)
msg.attach(part)
#發送郵件
msg['From']='wl18814726725@163.com' #發件人郵箱
msg['To']='1572533878@qq.com' #收件人
#第五步:發送郵件
s.sendmail(from_addr=msg['From'],to_addrs=msg['To'],msg=msg.as_string()) #將郵件內容轉換為字符串
send_email('report.html')
錯誤 1:smtplib.SMTPAuthenticationError: (550, b'User has no permission') 。
我們使用 python 發送郵件時相當于自定義客戶端根據用戶名和密碼登錄,然后使用 SMTP 服務發送郵件,新注冊的 163 郵箱是默認不開啟客戶端授權的(對指定的郵箱大師客戶端默認開啟),因此登錄總是被拒絕,解決辦法(以 163 郵箱為例):進入 163 郵箱 - 設置 - 客戶端授權密碼 - 開啟(授權碼是用于登錄第三方郵件客戶端的專用密碼)。上述有專門的設置方法。
錯誤 2:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') 。
以 163 郵箱為例,在開啟 POP3/SMTP 服務,并開啟客戶端授權密碼時會設置授權碼,將這個授權碼代替 smtplib.SMTP().login(user,password) 方法中的 password 即可。
錯誤 3:給多人發送郵件是,可能會出現 “AttributeError: 'list' object has no attribute 'encode'” 或者寫了多個人,實際只給第一個人發了郵件等錯誤。
當我們在一個網站中進行注冊賬戶成功后,通常會收到一封來自該網站的郵件。郵件中顯示我們剛剛申請的賬戶和密碼以及一些其他的廣告信息。在上一篇中用Java實現了發送qq郵件的功能,今天我們來實現一個這樣的功能,用戶注冊成功后,網站將用戶的注冊信息(賬號和密碼等)以Email的形式發送到用戶的注冊郵箱當中。
電子郵件在網絡中傳輸和網頁一樣需要遵從特定的協議,常用的電子郵件協議包括 SMTP,POP3,IMAP。其中郵件的創建和發送只需要用到 SMTP協議,所以本文也只會涉及到SMTP協議。SMTP 是 Simple Mail Transfer Protocol 的簡稱,即簡單郵件傳輸協議。
我們平時通過 Java 代碼打開一個 http 網頁鏈接時,通常可以使用已經對 http 協議封裝好的 HttpURLConnection 類來快速地實現。Java 官方也提供了對電子郵件協議封裝的 Java 類庫,就是JavaMail,但并沒有包含到標準的 JDK 中,需要我們自己去官方下載。
需要兩個jar包 activation.jar / mail.jar
所要用到的授權碼:qq郵件登錄 -> 設置 -> 賬戶
其中
SMTP是接收協議
POP3是接收協議
public class User {
private String name;
private String password;
private String email;
public User(String name, String password, String email) {
this.name=name;
this.password=password;
this.email=email;
}
//省略get/set和toString方法...
}
index.jsp:一個簡單的表單 包含用戶名、密碼、郵箱
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/mail.do" method="post">
用戶名: <input type="text" name="username" value="賬戶">
<br>
密碼: <input type="password" name="password" value="密碼">
<br>
郵箱: <input type="text" name="email" value="郵箱">
<br>
<input type="submit" value="注冊">
</form>
</body>
</html>
發送郵件的步驟
這里用到了多線程,因為發送郵件是需要時間去連接郵箱的服務器,若不使用多線程,則會卡在提交的網頁中不斷加載直至響應 使用多線程可以異步處理,提高用戶的體驗度
public class SendMail extends Thread {
private String from="發件人郵箱";
private String username="發件人用戶名";
private String password="授權碼";
private String host="smtp.qq.com"; //QQ郵箱的主機協議
private User user;
public SendMail(User user) {
this.user=user;
}
public void run() {
Transport ts=null;
try {
Properties prop=new Properties();
prop.setProperty("mail.host",host);
prop.setProperty("mail.transport.protocol","smtp");
prop.setProperty("mail.smtp.auth","true");
//關于QQ郵箱 還要設置SSL加密
MailSSLSocketFactory sf=new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用JavaMail發送郵件的5個步驟
//1.創建定義整個應用程序所需的環境信息的sessio對象
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username,password);
}
});
session.setDebug(true);//開啟debug模式 看到發送的運行狀態
//2.通過session得到transport對象
ts=session.getTransport();
//3.使用郵箱的用戶名和授權碼連上郵件服務器
ts.connect(host,username,password);
//4.創建純文本的簡單郵件
MimeMessage message=new MimeMessage(session);
message.setSubject("只包含文本的普通郵件");//郵件主題
message.setFrom(new InternetAddress(from));// 發件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));//收件人
String info="注冊成功!你的賬號信息為: username=" + user.getName() + "password=" + user.getPassword();
message.setContent("<h1 style='color: red'>" + info + "</h1>","text/html;charset=UTF-8");//郵件內容
message.saveChanges();//保存設置
//5.發送郵件
ts.sendMessage(message,message.getAllRecipients());
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} finally {
//關閉連接
try {
ts.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}
public class MailServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取前端數據
String username=req.getParameter("username");
String password=req.getParameter("password");
String email=req.getParameter("email");
//封裝成一個User對象
User user=new User(username,password,email);
SendMail send=new SendMail(user);
send.start();//啟動線程
req.setAttribute("message","已發送 請等待");
req.getRequestDispatcher("info.jsp").forward(req,resp);//發送成功跳轉到提示頁面
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>mail</servlet-name>
<servlet-class>com.xiaoyao.servlet.MailServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mail</servlet-name>
<url-pattern>/mail.do</url-pattern>
</servlet-mapping>
</web-app>
測試ok!
工作中我用的是JavaMail 1.6.2的版本遇到過以下這個問題
這個問題就是沒有使用授權碼引起的,需要去發件人郵箱設置開啟授權碼;
1、怎么獲取授權碼?
先進入設置,帳戶頁面找到入口,按照以下流程操作。
(1)點擊“開啟”
(2)驗證密保
(3)獲取授權碼
1、使用JavaMail發送郵件時發現,將郵件發送到sina或者sohu的郵箱時,不一定能夠馬上收取得到郵件,總是有延遲,有時甚至會延遲很長的時間,甚至會被當成垃圾郵件來處理掉,或者干脆就拒絕接收,有時候為了看到郵件發送成功的效果
2、在執行到 message.saveChanges(); 方法報錯無法進行保存設置,也有可能時你的mail版本較低造成的。
在書寫 File file=new File(); 時注意修改正確的路徑,也可以寫在form表單里用file進行傳值,主題和內容也寫在了方法里因人而異如果其他需求可以需改參數進行傳值。
3、在執行到 File file=new File(“D:\Chat_Software\sky.JPG”);時出現錯誤,之前寫的是xlsx文件,測試期間可以對.xls,jpg,文本,.doc文件進行發送。發送xlsx文件時出現報錯。 問題解決方案: .xls文件擴展名對應的是Microsoft Office EXCEL 2003及以前的版本。 .xlsx文件擴展名對應的是Microsoft Office EXCEL 2007及后期的版本。 有可能時你下載的mai不是1.6以上版本的,建議下載1.6以上版本的mail
*請認真填寫需求信息,我們會在24小時內與您取得聯系。