目录
邮件收发
电子邮件
要在网络上实现邮件功能,必须要有专门的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;
传输协议
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
邮件收发原理
- 大狂神通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
- 网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的Smtp服务器
- QQ将接收到的邮件存储在[email protected]这个邮件账号的空间中
- 小狂神通过Pop3协议连接到Pop3服务器收取邮件
- 从[email protected]这个邮件账号的空间中取出邮件
- 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邮件处理程序。
纯文本邮件
先在项目lib中导入jar包
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
QQ邮箱中获取对应的权限
QQ邮箱需要安全验证,我们需要获取他对应的权限;
QQ邮箱–>邮箱设置–>账户
点击开启,获得16位的授权码:
编写测试代码
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws Exception {
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");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
return new PasswordAuthentication("[email protected]","授权码");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts=session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
ts.connect("smtp.qq.com","[email protected]","授权码");
//4.创建邮件:写文件
//注意需要传递session
MimeMessage message=new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("[email protected]"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发.
message.setRecipient(Message.RecipientType.TO,new InternetAddress("[email protected]"));
//邮件标题
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对象。
创建包含内嵌图片的邮件
前面的例子中是单独的使用HTML或者是纯文本内容,但是有时候我们需要在纯文本中使用内嵌的方式显示一些图片,因此就要将纯文本和内嵌图片单独存放在MimeBodyPart中然后再将其存放在一个Mimemultipart对象中即可。
//发送一封带图片的邮件
public class MailDemo02 {
public static void main(String[] args) throws Exception {
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");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
return new PasswordAuthentication("[email protected]","授权码");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts=session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
ts.connect("smtp.qq.com","[email protected]","授权码");
//4.创建邮件:写文件
//注意需要传递session
MimeMessage message=new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("[email protected]"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发.
message.setRecipient(Message.RecipientType.TO,new InternetAddress("[email protected]"));
//邮件标题
message.setSubject("发送的主题");
//邮件的文本内容
===============准备图片数据===============
MimeBodyPart image=new MimeBodyPart();
//图片需要经过数据化的处理
DataHandler dh=new DataHandler(new FileDataSource("G:\\JavaSE\\SE\\code\\javaweb\\mail-java\\src\\1.jpg"));
//在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");
//描述数据关系
MimeMultipart mm=new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//设置到消息中,保存修改
message.setContent(mm);//把最后编辑好的邮件放到消息当中
message.saveChanges();//保存修改!
===============邮件的文本内容结束===============
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接
ts.close();
}
}
带图片和附件的复杂邮件发送
//发送一封带图片和附件的复杂邮件
public class MailDemo03 {
public static void main(String[] args) throws Exception {
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");
prop.put("mail.smtp.ssl.socketFactory",sf);
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
return new PasswordAuthentication("[email protected]","授权码");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts=session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器 [email protected]替换为获取授权码的QQ邮箱,授权码替换为获取的16位授权码
ts.connect("smtp.qq.com","[email protected]","授权码");
//4.创建邮件:写文件
//注意需要传递session
MimeMessage message=new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("[email protected]"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发.
message.setRecipient(Message.RecipientType.TO,new InternetAddress("[email protected]"));
//邮件标题
message.setSubject("发送的主题");
//邮件的文本内容
===============准备图片数据===============
MimeBodyPart image=new MimeBodyPart();
//图片需要经过数据化的处理
DataHandler dh=new DataHandler(new FileDataSource("G:\\JavaSE\\SE\\code\\javaweb\\mail-java\\src\\1.jpg"));
//在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("G:\\JavaSE\\SE\\code\\javaweb\\mail-java\\src\\1.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了。
代码实现:
-
新建一个JavaWeb项目,配置tomcat,添加jar包
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.activation/activation --> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> </dependencies>
-
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post"> 用户名:<input type="text" name="username"><br/> 密码:<input type="text" name="password"><br/> 邮箱:<input type="text" name="email"><br/> <input type="submit" value="注册"> </form> </body> </html>
-
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>xxx网站温馨提示</h1> ${message} </body> </html>
-
实体类
方法一:
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 + '\'' + '}'; } }
方法二(用工具):
<dependencies> <!--自动封装实体类 @Data 自动生成get,set @AllArgsConstructor 自动生成有参构造 @NoArgsConstructor 自动生成无参构造 --> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency> </dependencies>
@Data //自动生成get,set @AllArgsConstructor //自动生成有参构造 @NoArgsConstructor //自动生成无参构造 public class User { private String username; private String password; private String email; }
-
发送邮件核心工具(util里写)
这里引入多线程的目的是为了提高用户的体验,防止因发送文件时间过长,导致前端响应过久,因此这里采用异步响应。
//网站3秒原则:用户体验 //多线程实现用户体验! (异步处理) public class Sendmail extends Thread{ //用于给用户发送邮件的邮箱 private String from = "[email protected]" ; //邮箱的用户名 private String username = " [email protected]" ; //邮箱的密码 private String password = "授权码"; //发送邮件的服务器地址 private String host ="smtp.qq.com" ; private User user; public Sendmail(User user){ this.user=user; } //重写run方法的实现,在run 方法中发送邮件给指定的用户 @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,from,password); //4.创建邮件:写文件 //注意需要传递session MimeMessage message=new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress(from)); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail())); //邮件标题 message.setSubject("注册通知"); //邮件的文本内容 message.setContent("恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword(),"text/html;charset=UTF-8"); //5.发送邮件 ts.sendMessage(message,message.getAllRecipients()); //6.关闭连接 ts.close(); }catch (Exception e){ System.out.println(e); } } }
-
servlet
public class RegisterServlet 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 = new User(username, password, email); //用户注册成功之后,给用户发送一封邮件 //我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况; Sendmail send=new Sendmail(user); //启动线程,线程启动之后就会执行run方法来发送邮件 send.start(); //注册用户 req.setAttribute("message","注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!"); req.getRequestDispatcher( "info.jsp").forward(req,resp); System.out.println("success"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
配置servlet路径
<servlet> <servlet-name>RegisterServlet</servlet-name> <servlet-class>com.yingxu.servlet.RegisterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RegisterServlet</servlet-name> <url-pattern>/RegisterServlet.do</url-pattern> </servlet-mapping>