文章目录
邮件收发
要在网络上实现邮件功能,必须要有专门的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,
- 它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
- 对应:接收和发送
- 接收:POP3协议
- 发送:SMTP协议
SMTP服务器地址:一般是smtp.xxx.com,每一个网站都有自己的服务器地址(固定的)
- 比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。
- 比如我们要使用QQ邮箱,就需要开通邮箱功能。
SMTP服务器地址
例如:QQ邮箱
设置 - - ->账号
常用邮件客户端软件设置_QQ邮箱帮助中心
传输协议
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
邮件发送原理图
(1)张三通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
(2)网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的Smtp服务器
(3)QQ将接收到的邮件存储在lisi@qq.com这个邮件账号的空间中
(4)李四通过Pop3协议连接到Pop3服务器收取邮件
(5)从lisi@qq.com这个邮件账号的空间中取出邮件
(6)Pop3服务器将取出来的邮件送到李四手中
【注意】
有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。
这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。
解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试
Java发送邮件
概述
我们将用代码完成邮件的发送,这在实际项目中应用的非常广泛。
- 比如注册需要发送邮件进行账号激活,
- 再比如OA项目中利用邮件进行任务提醒等等。
使用Java发送 E-mail 十分简单,但是首先你应该准备
-
JavaMail API
-
Java Activation Framework 。(发送邮件的支持包)
得到两个jar包:网络协议的
-
mail.jar
-
activation.jar
JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,
它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME(附件和图片)等。
我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。
我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。
-
创建包含邮件服务器的网络连接信息的Session对象。
-
创建代表邮件内容的Message对象
-
创建Transport对象,连接服务器,发送Message,关闭连接
主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
Session:定义整个程序,所有的信息。比如:smtp.qq.com、邮箱账号、密码
Transport:发送邮件
Message:信息的内容。对应:收件人、主题、正文
纯文本邮件
导包
先在项目中导入jar包
权限
QQ邮箱中获取对应的权限
QQ邮箱需要安全验证,我们需要获取他对应的权限;
QQ邮箱–>邮箱设置–>账户
点击开启,获得16位的授权码:
总结
-
简单邮件:没有附件和图片,纯文本图片
-
复杂邮件:有附件和图片
-
要发送邮件,需要获得协议和支持!开启服务POP3/SMTP服务
-
QQ授权码:……
步骤
1、准备消息
2、发送到哪里去
代码实现
package com.yin;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
//简单邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
//Properties中 设置属性
Properties prop=new Properties();
prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
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");//使用安全的连接为true
prop.put("mail.smtp.ssl.socketFactory",sf);//socket工厂,使用自己的socket工厂
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session= Session.getDefaultInstance(prop, new Authenticator() {//获取默认的实例
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮箱、授权码
return new PasswordAuthentication("1455272942@qq.com","evdqbmnahqxjhfbi");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","1455272942@qq.com","evdqbmnahqxjhfbi");
//4.创建邮件:写邮件
//需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("1455272942@qq.com"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("1455272942@qq.com"));
//邮件的标题 只包含文本的简单邮件
message.setSubject("发送的标题");
//邮件的文本内容
message.setContent("你好","text/html;charset=UTF-8");
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接,一切网络都需要关闭
ts.close();
}
}
带图片和附件的邮件
两个类
先认识两个类一个名词:
MIME(多用途互联网邮件扩展类型)
-
MimeBodyPart类 (内容的主体)
-
javax.mail.internet.MimeBodyPart类
-
表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
-
-
MimeMultipart类 (内容的封装)
-
javax.mail.internet.MimeMultipart是抽象类
-
Multipart的实现子类,它用来组合多个MIME消息。
-
一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
-
流程图
邮件
在MimeBodyPart中有三个属性
- mixed:附件
- related:内嵌资源
- alternative:超文本正文
代码实现
package com.yin;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
//带图片和附件的邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
//Properties中 设置属性
Properties prop=new Properties();
prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
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");//使用安全的连接为true
prop.put("mail.smtp.ssl.socketFactory",sf);//socket工厂,使用自己的socket工厂
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session= Session.getDefaultInstance(prop, new Authenticator() {//获取默认的实例
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮箱、授权码
return new PasswordAuthentication("1455272942@qq.com","evdqbmnahqxjhfbi");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","1455272942@qq.com","evdqbmnahqxjhfbi");
//4.创建邮件:写邮件
//需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("1455272942@qq.com"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("1455272942@qq.com"));
//邮件的标题 只包含文本的简单邮件
message.setSubject("发送的标题");
//邮件的文本内容
message.setContent("你好","text/html;charset=UTF-8");
/*==================图片和附件的邮件=========================*/
//=================================准备图片数据
MimeBodyPart image = new MimeBodyPart();
//图片需要经过数据化的处理 DataHandler:数据处理 FileDataSource:加载文件的资源
DataHandler dh = new DataHandler(new FileDataSource("D:\\学习资料\\MarkDown学习\\狂神说java\\javaWeb\\功能扩展\\功能扩展.assets\\邮件发送.png"));
//在part中放入这个处理的图片数据
image.setDataHandler(dh);
//给这个part设置一个ID名字
image.setContentID("bz.jpg");
//=================================准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");
//=================================准备附件数据
MimeBodyPart body1= new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("D:\\学习资料\\MarkDown学习\\狂神说java\\javaWeb\\功能扩展\\功能扩展.txt")));
body1.setFileName("1.txt");
//描述数据关系
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(body1);
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("mixed");
//设置到消息中,保存修改
message.setContent(mm);
message.saveChanges();
/*===========================================*/
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接,一切网络都需要关闭
ts.close();
}
}
JavaWeb发送邮件
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。
思路:把收件人地址改成从前端接收过来的参数
代码实现:
1.先搭建框架
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/RegisterServlet" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
邮箱:<input type="text" name="email"><br/>
<input type="submit" value="注册">
</form>
</body>
</html>
RegisterServlet类
package com.yin.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
脚手架
通过这个框架,可以往里边不断添加功能
*/
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接收用户请求
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
System.out.println(username);
System.out.println(password);
System.out.println(email);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
======
123
1233123
12312
配置:Web.xml
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.yin.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet</url-pattern>
</servlet-mapping>
结果
2.实体类
package com.yin.pojo;
import java.io.Serializable;
/*
实体类
要序列化,为了安全
*/
public class User implements Serializable {
private String username;
private String password;
private String email;
public User() {
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
//方便调试
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
3.工具类
package com.yin.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import com.yin.pojo.User;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
/*
网站3秒原则:用户体验
让用户不等待,事情也还做?
用户执行完这个方法,它还走它的东西,我走我的页面
通过多线程,实现用户体验!(异步处理)
*/
public class SendMail extends Thread{
//用于给用户发送邮件的邮箱
private String from = "1455272942@qq.com" ;
//邮箱的用户名
private String username = " 1455272942@qq.com" ;
//邮箱的密码
private String password = "evdqbmnahqxjhfbi";
//发送邮件的服务器地址
private String host ="smtp.qq.com" ;
//导入一个类
private User user;
public SendMail(User user){
this.user = user;
}
@Override
public void run() {
try {
Properties prop = new Properties();
prop.setProperty("mail.host",host);///设置QQ邮件服务器
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.创建定义整个应用程序所需要的环境信息的session对象
Session session= Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from,password);
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect(host,username,password);
//4.创建邮件:写文件
//注意需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress(from));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));//从前端接收的
//邮件标题
message.setSubject("注册通知");
//邮件的文本内容
String info = "恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword();
message.setContent(info,"text/html;charset=UTF-8");
message.saveChanges();//保存更改
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接
ts.close();
}catch (Exception e){
System.out.println(e);
}
}
}
4.Servlet类
package com.yin.servlet;
import com.yin.pojo.User;
import com.yin.utils.SendMail;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
脚手架
通过这个框架,可以往里边不断添加功能
*/
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接收用户请求
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
//把用户的请求封装成一个对象
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 doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
5.提示页面
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>网站温馨提示</h1>
${message}
</body>
</html>
流程
从index.jsp进入页面,点击提交的时候,走RegisterServlet.do
RegisterServlet.do通过web.xml找到RegisterServlet
RegisterServlet
- 接收用户
- 收成一个对象
- 通过线程发送
- 发送成功跳转回info.jsp页面
项目环境上的问题:
- Project Structure:项目结构
效果