JavaWeb邮件发送(感谢狂神)
电子邮件
要在网络上实现邮件功能,必须要有专门的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;
传输协议
-
SMTP协议发送邮件:我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
-
POP3协议接收邮件:我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
邮件收发原理
1、邮件服务器
①SMTP邮件服务器:替用户发送邮件和接收外面发送给本地用户的邮件
②POP3/IMAP邮件服务器:帮助用户读取SMTP邮件服务器接收进来的邮件
2、邮件传输协议
①电子邮件需要在邮件客户端和邮件服务器之间,以及两个邮件服务器之间进行邮件传递,那就必须要遵守一定的规则,这个规则就是邮件传输协议
②SMTP协议:全称为 Simple Mail Transfer Protocol,简单邮件传输协议。它定义了邮件客户端软件和SMTP邮件服务器之间,以及两台SMTP邮件服务器之间的通信规则
③POP3协议:全称为 Post Office Protocol,邮局协议。它定义了邮件客户端软件和POP3邮件服务器的通信规则
④IMAP协议:全称为 Internet Message Access Protocol,Internet消息访问协议,它是对POP3协议的一种扩展,也是定义了邮件客户端软件和IMAP邮件服务器的通信规则
我们说所有的邮件服务器和邮件客户端软件程序都是基于上面的协议编写的
概述
我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。 JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,
如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。 我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。 - 创建包含邮件服务器的网络连接信息的Session对象。 - 创建代表邮件内容的Message对象 - 创建Transport对象,连接服务器,发送Message,关闭连接 主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
1、传输协议:
-
SMTP协议
处理用户邮件发送的请求。
-
POP3协议
处理用户邮件接收请的求。
2、导包:
mail.jar
activation.jar
3、过程:
4、邮件分类
-
简单邮件:没有除了文字以外的其他所有文件(包括附件和图片、视频等),即纯文本邮件
- 复杂邮件:除了传统的文字信息外,还包括了一些非文字数据的邮件
5、代码:
//发送一封简单邮件
public class MailDemo01 {
public static void main(String[] args) throws GeneralSecurityException, MessagingException {
//要发送邮件需要获取协议,开启POP3和SMTP服务
Properties prop = new Properties();//创建一封邮件
//以下三项的Key的值都是固定的
prop.setProperty("mail.host", "smtp.qq.com");//设置邮件服务器
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发送邮件的6个步骤======
//1、创建定义整个应用程序所需要的环境信息的Session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication(){
//发件人邮箱的用户名和授权码(只有qq是授权码,其它的是密码)
return new PasswordAuthentication("username","password");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过Session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("SMTP.qq.com","username","password");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("username"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("username"));
//邮件的标题
message.setSubject("只是一个普通的纯文本邮件");
//邮件的文本内容
message.setContent("<h1 style='color:red'>嘿嘿嘿,嘿嘿嘿,哈哈哈!</h1>","text/html;charset=UTF-8");
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6、关闭连接
ts.close();
}
}
发送成功
6、带附件:
附件格式包含关系:
public class MailDemo02 {
/*
*MimeMessage类表示整封邮件。
*MimeBodyPart类表示邮件的一个MIME消息。
*MimeMultipart类表示一个由多个MIME消息组合成的组合MIME消息。
*/
//要发送邮件需要获取协议,开启POP3和SMTP服务
public static void main(String[] args) throws Exception {
Properties prop = new Properties();//创建一封邮件
//以下三项的Key的值都是固定的
prop.setProperty("mail.host","smtp.qq.com");//设置邮件服务器
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发送邮件的6个步骤======
//变量名字定义的有点乱,不想改了。将就下吧
//1、创建定义整个应用程序所需要的环境信息的Session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication(){
//发件人邮箱的用户名和授权码
return new PasswordAuthentication("username","password");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过Session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("SMTP.qq.com","username","password");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("username"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("username"));
//邮件的标题
message.setSubject("这是一个有文本、图片、附件的邮件");
//邮件的内容
//=================================================
//准备图片数据 DataHandler:处理除文本外的数据
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("D:\\java代码\\FunctionExpansion\\mail-java\\src\\1.png"));
image.setDataHandler(dh);//在我们的body中放入处理的图片数据
image.setContentID("gz.jpg");//设置图片ID
//ContentID用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标识号,在HTML格式的正文中可以使用这个唯一标识号来引用该内嵌资源。
//注意,在引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上“cid:”,以说明要采用唯一标识号对资源进行引用。
//准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一个带图片、文本、附件<img src='cid:gz.jpg'>的邮件","text/html;charset=UTF-8");
//准备附件数据
MimeBodyPart accessory = new MimeBodyPart();
DataHandler dh2 = new DataHandler(new FileDataSource("D:\\java代码\\FunctionExpansion\\mail-java\\src\\1.docx"));
accessory.setDataHandler(dh2);
accessory.setFileName(MimeUtility.encodeText("dsf.docx"));//给附件一个名字,发过去显示的就是这个设定的名字||MimeUtility.encodeText("")解决附件发送过去乱码;
//*****************************!!!!!!!**********************
/*
MimeBodyPart:表示复杂邮件的一个组成部分,它可以表示文本,附件,图片
DataHandler:表示可以读取图片或附件
MimeMultipart:表示二个邮件组成部分的关系,文本和图片的关系是"related"关系
Content-ID:表示图片的编号
related:图片|| mixed:附件
*/
//*****************************!!!!!!!**********************
//拼接图片和文本
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//将文本+图片封装成邮件的组成部分,即将关系看作成一个部分
MimeBodyPart context = new MimeBodyPart();
context.setContent(mm);
//把附件也加上
MimeMultipart file = new MimeMultipart();
file.addBodyPart(context);
file.addBodyPart(accessory);
file.setSubType("mixed");
//放到消息中
message.setContent(file);//把编辑好的内容放入消息中
message.saveChanges();//保存修改!
//=================================================
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());//message:发送的消息||message.getAllRecipients():获取保存在里面的地址
//6、关闭连接
ts.close();
}
//对于,复杂类型的邮件,位置关系特别注意和加入的顺利要一致
}
发送成功
网站注册发送邮件功能实现
分析:在我们注册的时候,前端我们填写的就是一个表单,这个表单提交给后端的servlet,这个servlet就向我们填写的那个邮箱中发送一封邮件
-
所以我们需要创建一个javaweb项目,因为要使用到前端页面+servlet
注册页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--注册填写邮箱的前端页面--%> <html> <head> <title>注册</title> </head> <body> <form action="${pageContext.request.contextPath}/RegisterServlet.do" 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>
提示成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>提示信息</title> </head> <body> <h2>thhh提醒您</h2> ${message} </body> </html>
servlet
public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、接收用户填写的表单数据 String username = req.getParameter("username"); String password = req.getParameter("password"); String email = req.getParameter("email"); // System.out.println(username+password+email); //2、向用户邮箱发送邮件,注意发送邮件很耗时,所以我们启动一个子线程去做这件事,而用户则是直接跳转注册成功页面,以免降低用户体验 User user = new User(username,password,email); Sendmail sendmail = new Sendmail(user);//获取子线程对象 new Thread(sendmail).start();//启动子线程 //3、视图跳转 req.setAttribute("message","注册成功!我们已经向您的邮箱发送了邮件,请您及时进行查收。由于网络原因,您收到邮件的时间存在延迟,敬请谅解~"); req.getRequestDispatcher("info.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
多线程工具类utils
//多线程实现邮件发送 //使用多线程的原因就是提高用户的体验,一旦一个页面3s及以上的时间白屏就可能被用户关掉 //所以我们在用户提交表单之后,将费时的邮件发送工作使用一个子线程来完成,而主线程还是去完成它自己的事情 //这么做就可以提高用户体验,不然用户等待邮件发送的时间 //多线程这种处理就可以称为异步处理 public class Sendmail implements Runnable{ private String from = "XXXX@qq.com";//我们用来向客户发送邮件的邮箱 private String username = "XXXX@qq.com";//用于登陆SMTP服务器的用户名 private String password = "授权码";//授权码 private User user; public Sendmail(User user) { this.user = user;//用于获取用户邮箱地址 } @Override public void run() { try { 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() {//获取和SMTP服务器的连接对象 public PasswordAuthentication getPasswordAuthentication() { //发件人邮件用户名、授权码 return new PasswordAuthentication("username", "password"); } }); //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 session.setDebug(true); //2、通过session得到transport对象 Transport ts = session.getTransport();//通过这一次和SMTP服务器的连接对象获取发送邮件的传输对象 //3、使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆 ts.connect("smtp.qq.com", username, password); //4、创建邮件对象MimeMessage——点击网页上的写信 //创建一个邮件对象 MimeMessage message = new MimeMessage(session); //指明邮件的发件人——在网页上填写发件人 message.setFrom(new InternetAddress(username));//设置发件人 //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发——在网页上填写收件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));//设置收件人 //邮件的标题——在网页上填写邮件标题 message.setSubject("欢迎注册thhh!");//设置邮件主题 //邮件的文本内容——在网页上填写邮件内容 message.setContent("<p><h2>恭喜注册成功!</h2></p>您的用户名为:<h4>"+user.getUsername()+"</h4>请妥善保管您的密码,如有问题请及时联系网站客服,再次欢迎您的加入!!", "text/html;charset=UTF-8");//设置邮件的具体内容 //5、发送邮件——在网页上点击发送按钮 ts.sendMessage(message, message.getAllRecipients()); //6、关闭连接对象,即关闭服务器上的连接资源 ts.close(); } catch (MessagingException e) { e.printStackTrace(); } catch (GeneralSecurityException e) { e.printStackTrace(); } } }
发送成功
【参考:狂神笔记、(127条消息) 网站注册邮件发送功能实现_꧁冰凝꧂的博客-CSDN博客、邮件收发原理你了解吗? 邮件发送基本过程与概念详解(一)_java_脚本之家 (jb51.net)】