邮件发送功能实现:
一、邮件收发原理:
二、传输协议:
-
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。 -
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
三、概述:
我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。 使用Java发送 E-mail 十分简单,但是首先你应该准备 JavaMail API 和Java Activation Framework 。 得到两个jar包: 1.mail.jar 2.activation.jar JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。 我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。 - 创建包含邮件服务器的网络连接信息的Session对象。 - 创建代表邮件内容的Message对象 - 创建Transport对象,连接服务器,发送Message,关闭连接 主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
四、简单邮件发送:
邮件分类
-
简单邮件:没有除了文字以外的其他所有文件(包括附件和图片、视频等),即纯文本邮件
-
复杂邮件:除了传统的文字信息外,还包括了一些非文字数据的邮件
需要发送邮件首先就要我们的邮箱账号支持POP3和SMTP协议,所以我们需要开启邮箱的POP3+SMTP服务,
然后我们需要复制下图中的授权码,这个授权码就相当于你的QQ密码,
你可以使用你的邮箱账号+授权码来发送邮件,而SMTP服务器也就是使用这个来识别你的身份
注意一点:不要while群发邮件,哈哈
以下简单邮件发送的7个固定步骤,如果你要使用,直接复制粘贴代码,并将你的邮箱+授权码填进去就可以用了
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 Demo01_简单邮件发送 { 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); //1、创建定义整个应用程序所需的环境信息的 Session 对象 //使用QQ邮箱的时候才需要,其他邮箱不需要这一段代码 Session session = Session.getDefaultInstance(prop, new Authenticator() {//获取和SMTP服务器的连接对象 @Override public PasswordAuthentication getPasswordAuthentication() { //发件人邮件用户名、授权码 return new PasswordAuthentication("xxx@qq.com", "fxeiispwzpmmfdgh"); } }); //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 session.setDebug(true); //2、通过session得到transport对象(和SMTP服务器的连接对象获取发送邮件的传输对象) Transport ts = session.getTransport(); //3、使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆 ts.connect("smtp.qq.com", "xxx@qq.com", "fxeiispwzpmmfdgh"); //4、创建邮件对象MimeMessage——点击网页上的写信 MimeMessage message = new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("xxx@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress("xxx@qq.com")); //邮件的标题 message.setSubject("平安夜"); //邮件的文本内容 message.setContent("<h2 style='color:red'>平安夜记得吃苹果!!</h2>", "text/html;charset=UTF-8"); //5、发送邮件——在网页上点击发送按钮 ts.sendMessage(message, message.getAllRecipients()); //6、关闭连接对象,即关闭服务器上的连接资源 ts.close(); } }
五、多功能邮件发送
复杂邮件就是非纯文本的邮件,可能还包含了图片和附件等资源
先认识两个类一个名词:
MIME(多用途互联网邮件扩展类型)
- MimeBodyPart类
javax.mail.internet.MimeBodyPart类表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
即一个MIME消息对应一个MimeBodyPart对象,而MimeBodyPart对象就是我们写的邮件内容中的元素
- MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。
一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
即一个MimeMultipart对象表示多个MimeBodyPart的集合,而一个MimeMultipart表示的就是我们一封邮件的内容
MimeMultipart对象的使用的时候需要设置setSubType()的属性值,一共就下面3种取值
- alternative:表明这个MimeMultipart对象中的MimeMessage对象的数据是纯文本文件
- related:表明这个MimeMultipart对象中的MimeMessage对象的数据包含非纯文本文件
- mixed:表明这个MimeMultipart对象中的MimeMessage对象的数据包含附件
我们在使得的时候如果不知道使用哪一个,直接使用mixed即可,使用这个属性值一定不会报错
相较于简单邮件,复杂邮件变化的地方只是在于邮件内容本身会发送变化,而其他的步骤都是一样的
1、准备一些参数
2、获取session对象
3、获取传输对象
4、登陆授权
5、写邮件 (和简单邮件相区别)
// 准备邮件数据 // 准备图片数据 MimeBodyPart image = new MimeBodyPart();//获取一个图片的MimeBodyPart对象 DataHandler dh = new DataHandler(new FileDataSource("图片的地址"));//由于图片需要字符化才能传输,所以需要获取一个DataHandler对象 image.setDataHandler(dh);//将图片序列化 image.setContentID("bz.jpg");//为图片的MimeBodyPart对象设置一个ID,我们在文字中就可以使用它了 // 准备正文数据 MimeBodyPart text = new MimeBodyPart();//获取一个文本的MimeBodyPart对象 text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件", "text/html;charset=UTF-8");//设置文本内容,注意在里面嵌入了<img src='cid:bz.jpg'> // 描述数据关系 MimeMultipart mm = new MimeMultipart();//获取MimeMultipart mm.addBodyPart(text);//将文本MimeBodyPart对象加入MimeMultipart中 mm.addBodyPart(image);//将图片MimeBodyPart对象加入MimeMultipart中 mm.setSubType("related");//设置MimeMultipart对象的相对熟悉为related,即发送的数据为文本+非附件资源 //设置到消息中,保存修改 message.setContent(mm);//将MimeMultipart放入消息对象中 message.saveChanges();//保存上面的修改
6、发送邮件
7、关闭服务器资源
完整代码:

package com.zhixi; 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; /** * @author zhangzhixi */ public class Demo02_复杂邮件发送 { 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); //1、创建定义整个应用程序所需的环境信息的 Session 对象 //使用QQ邮箱的时候才需要,其他邮箱不需要这一段代码 Session session = Session.getDefaultInstance(prop, new Authenticator() {//获取和SMTP服务器的连接对象 @Override public PasswordAuthentication getPasswordAuthentication() { //发件人邮件用户名、授权码 return new PasswordAuthentication("zhang_zhixi@qq.com", "fxeiispwzpmmfdgh"); } }); //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 session.setDebug(true); //2、通过session得到transport对象(和SMTP服务器的连接对象获取发送邮件的传输对象) Transport ts = session.getTransport(); //3、使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆 ts.connect("smtp.qq.com", "zhang_zhixi@qq.com", "fxeiispwzpmmfdgh"); //4、创建邮件对象MimeMessage——点击网页上的写信 MimeMessage message = new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("zhang_zhixi@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress("zhang_zhixi@qq.com")); //邮件的标题 message.setSubject("测试"); // 准备图片数据 MimeBodyPart image = new MimeBodyPart(); DataHandler dh = new DataHandler(new FileDataSource("文件绝对路径")); //将图片序列化 image.setDataHandler(dh); //可以给图片起一个别名 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("mixed"); //设置到消息中,保存修改 message.setContent(mm); message.saveChanges();//保存上面的修改 //5、发送邮件——在网页上点击发送按钮 ts.sendMessage(message, message.getAllRecipients()); //6、关闭连接对象,即关闭服务器上的连接资源 ts.close(); } }
六、复杂邮件的附件功能:
复杂邮件的邮件内容设置:也就是修改上面写的第五步
/* 编写邮件内容 1.图片 2.附件 3.文本 */ //图片 MimeBodyPart body1 = new MimeBodyPart(); body1.setDataHandler(new DataHandler(new FileDataSource("图片的绝对地址"))); body1.setContentID("yhbxb.png"); //图片设置ID //文本 MimeBodyPart body2 = new MimeBodyPart(); body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8"); //附件 MimeBodyPart body3 = new MimeBodyPart(); body3.setDataHandler(new DataHandler(new FileDataSource("附件1的绝对地址"))); body3.setFileName("test.c"); //附件设置名字 MimeBodyPart body4 = new MimeBodyPart(); body4.setDataHandler(new DataHandler(new FileDataSource("附件2的绝对地址"))); body4.setFileName("test.txt"); //附件设置名字 //拼装邮件正文内容 MimeMultipart multipart1 = new MimeMultipart(); multipart1.addBodyPart(body1); multipart1.addBodyPart(body2); multipart1.setSubType("related"); //1.文本和图片内嵌成功! //将拼装好的正文内容设置为主体 MimeBodyPart contentText = new MimeBodyPart(); contentText.setContent(multipart1); //拼接附件 MimeMultipart allFile =new MimeMultipart(); allFile.addBodyPart(body3); //附件 allFile.addBodyPart(body4); //附件 allFile.addBodyPart(contentText);//正文 allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed; //设置到消息中,保存修改 message.setContent(allFile);//将MimeMultipart放入消息对象中 message.saveChanges();//保存上面的修改
全部代码:

package com.zhixi; 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 Demo03_带附件的邮件 { 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); //1、创建定义整个应用程序所需的环境信息的 Session 对象 //使用QQ邮箱的时候才需要,其他邮箱不需要这一段代码 Session session = Session.getDefaultInstance(prop, new Authenticator() {//获取和SMTP服务器的连接对象 @Override public PasswordAuthentication getPasswordAuthentication() { //发件人邮件用户名、授权码 return new PasswordAuthentication("zhang_zhixi@qq.com", "fxeiispwzpmmfdgh"); } }); //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 session.setDebug(true); //2、通过session得到transport对象(和SMTP服务器的连接对象获取发送邮件的传输对象) Transport ts = session.getTransport(); //3、使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆 ts.connect("smtp.qq.com", "zhang_zhixi@qq.com", "fxeiispwzpmmfdgh"); //4、创建邮件对象MimeMessage——点击网页上的写信 MimeMessage message = new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("zhang_zhixi@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress("zhang_zhixi@qq.com")); //邮件的标题 message.setSubject("测试"); System.out.println("=============================复杂邮件的邮件内容设置=================================="); /* 编写邮件内容 1.图片 2.附件 3.文本 */ //图片 MimeBodyPart body1 = new MimeBodyPart(); body1.setDataHandler(new DataHandler(new FileDataSource("文件绝对地址"))); body1.setContentID("zzx.png"); //图片设置ID //文本 MimeBodyPart body2 = new MimeBodyPart(); body2.setContent("请注意,我不是广告<img src='cid:zzx.png'>","text/html;charset=utf-8"); //附件 MimeBodyPart body3 = new MimeBodyPart(); body3.setDataHandler(new DataHandler(new FileDataSource("文件绝对地址"))); body3.setFileName("test.jar"); //附件设置名字 MimeBodyPart body4 = new MimeBodyPart(); body4.setDataHandler(new DataHandler(new FileDataSource("F:\\Maven\\Web功能扩展\\邮件发送\\src\\resources\\demo.properties"))); body4.setFileName("test.properties"); //附件设置名字 //拼装邮件正文内容 MimeMultipart multipart1 = new MimeMultipart(); multipart1.addBodyPart(body1); multipart1.addBodyPart(body2); multipart1.setSubType("related"); //1.文本和图片内嵌成功! MimeBodyPart contentText = new MimeBodyPart(); //将拼装好的正文内容设置为主体 contentText.setContent(multipart1); //拼接附件 MimeMultipart allFile =new MimeMultipart(); allFile.addBodyPart(body3); //附件 allFile.addBodyPart(body4); //附件 allFile.addBodyPart(contentText);//正文 allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed; //设置到消息中,保存修改 message.setContent(allFile);//将MimeMultipart放入消息对象中 message.saveChanges();//保存上面的修改 //5、发送邮件——在网页上点击发送按钮 ts.sendMessage(message, message.getAllRecipients()); //6、关闭连接对象,即关闭服务器上的连接资源 ts.close(); } }
七、网站注册发送邮件功能:
登录页面index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--注册填写邮箱的前端页面--%> <html> <head> <title>注册</title> </head> <body> <form action="${pageContext.request.contextPath}/login.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>
成功页面info.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>提示信息</title> </head> <body> <h2>站长温馨提示</h2> ${message} </body> </html>
实体类User:
package pojo; /** * @author zhangzhixi */ public class User { 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 + '\'' + '}'; } }
工具类Sendmail:
package utils; import com.sun.mail.util.MailSSLSocketFactory; import pojo.User; import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.security.GeneralSecurityException; import java.util.Properties; //多线程这种处理就可以称为异步处理 public class Sendmail implements Runnable{ private String username = "zhang_zhixi@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服务器的连接对象 @Override 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("欢迎注册小张的小破站!");//设置邮件主题 //邮件的文本内容——在网页上填写邮件内容 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(); } } }
servlet:
package Servlets; import pojo.User; import 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; /** * @author zhangzhixi */ public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); //1、接收用户填写的表单数据 String username = req.getParameter("username"); String password = req.getParameter("password"); String email = req.getParameter("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); } }
web.xml:
<?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>LoginServlet</servlet-name> <servlet-class>Servlets.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login.do</url-pattern> </servlet-mapping> </web-app>
2020-12-25 00:12:56看了狂神的视频真的是学到很多。还有老杜也是我人生导师,总之就像我的签名那样“人生没有白走的路,每走一步都算数”
加油吧年轻人!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话