【沉浸式求职学习day51】【发送邮件】【javaweb结尾】

article/2025/6/20 21:30:58

沉浸式求职学习

  • 邮件发送原理及实现
    • 1.概述
    • 2.简单邮件
    • 3.复杂邮件
  • 网站注册发送邮件功能实现

邮件发送原理及实现

1.概述

传输协议

  • SMTP协议
    发送邮件:
    我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
  • POP3协议
    接收邮件:
    我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。

邮件收发原理

  • 请参考:连接

使用Java实现邮件发送需要使用到的类

  • 我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如A项目中利用邮件进行任务提醒等等。

  • 使用Java发送Emai分简单,但是首先你应该准备 JavaMail API和 Java Activation framework。

  • 得到两个jar包:

    • mail.jar
    • activation.jar
  • JavaMail是sωn公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用 JavaMail!API编写邮件时,无须考虑邮件的底层实现细节,只要调用 Javamail开发包中相应的API类就可以了。

  • 我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。

    • 创建包含邮件服务器的网络连接信息的Session对象。
    • 创建代表邮件内容的Message对象;
    • 创建Transport对象,连接服务器,发送Message,关闭连接;
  • 主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
    在这里插入图片描述

2.简单邮件

邮件分类

  • 简单邮件:没有除了文字以外的其他所有文件(包括附件和图片、视频等),即纯文本邮件;
  • 复杂邮件:除了传统的文字信息外,还包括了一些非文字数据的邮件;

需要发送邮件首先就要我们的邮箱账号支持POP3和SMTP协议,所以我们需要开启邮箱的POP3+SMTP服务,然后我们需要复制下图中的授权码,这个授权码就相当于你的QQ密码,你可以使用你的邮箱账号+授权码来发送邮件,而SMTP服务器也就是使用这个来识别你的身份的。

在这里插入图片描述

package com.github.test;import com.sun.mail.util.MailSSLSocketFactory;import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;/*** @Author: subei* @Description: 一封简单的邮件*/
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() {// 获取和SMTP服务器的连接对象@Overridepublic PasswordAuthentication getPasswordAuthentication() {// 发件人邮件用户名、授权码return new PasswordAuthentication("XXXX@qq.com", "授权码");}});// 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态session.setDebug(true);// 2.通过session得到transport对象Transport ts = session.getTransport();// 通过这一次和SMTP服务器的连接对象获取发送邮件的传输对象// 3.使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆ts.connect("smtp.qq.com", "XXXX@qq.com", "授权码");// 4.创建邮件对象MimeMessage——点击网页上的写信// 创建一个邮件对象MimeMessage message = new MimeMessage(session);// 指明邮件的发件人——在网页上填写发件人message.setFrom(new InternetAddress("XXXX@qq.com"));// 设置发件人// 指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发——在网页上填写收件人message.setRecipient(Message.RecipientType.TO, new InternetAddress("XXXX@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();}
}

运行测试:
在这里插入图片描述

3.复杂邮件

  • 复杂邮件就是非纯文本的邮件,可能还包含了图片和附件等资源。

  • 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. 写邮件 (和简单邮件相区别);
    6. 发送邮件;
    7. 关闭服务器资源。

发送包含图片的复杂邮件

package com.github.test;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: subei* @Description: 图片的邮件*/
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() {// 获取和SMTP服务器的连接对象@Overridepublic PasswordAuthentication getPasswordAuthentication() {// 发件人邮件用户名、授权码return new PasswordAuthentication("XXXX@qq.com", "授权码");}});// 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态session.setDebug(true);// 2.通过session得到transport对象Transport ts = session.getTransport();// 通过这一次和SMTP服务器的连接对象获取发送邮件的传输对象// 3.使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆ts.connect("smtp.qq.com", "XXXX@qq.com", "授权码");// 4.创建邮件对象MimeMessage——点击网页上的写信// 创建一个邮件对象MimeMessage message = new MimeMessage(session);// 指明邮件的发件人——在网页上填写发件人message.setFrom(new InternetAddress("XXXX@qq.com"));// 设置发件人// 指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发——在网页上填写收件人message.setRecipient(Message.RecipientType.TO, new InternetAddress("XXXX@qq.com"));// 设置收件人// 邮件的标题——在网页上填写邮件标题message.setSubject("简单邮件发送实现");// 设置邮件主题System.out.println("=============================复杂邮件的邮件内容设置==================================");// 准备邮件数据// 准备图片数据// 获取一个图片的MimeBodyPart对象MimeBodyPart image = new MimeBodyPart();// 由于图片需要字符化才能传输,所以需要获取一个DataHandler对象DataHandler dh = new DataHandler(new FileDataSource("图片的绝对地址"));// 将图片序列化image.setDataHandler(dh);// 为图片的MimeBodyPart对象设置一个ID,我们在文字中就可以使用它了image.setContentID("p6.jpg");// 准备正文数据MimeBodyPart text = new MimeBodyPart();// 获取一个文本的MimeBodyPart对象text.setContent("这是一封邮件正文带图片<img src='cid:p6.jpg'>的邮件", "text/html;charset=UTF-8");// 设置文本内容,注意在里面嵌入了<img src='cid:p6.jpg'>// 描述数据关系// 获取MimeMultipartMimeMultipart mm = new MimeMultipart();// 将文本MimeBodyPart对象加入MimeMultipart中mm.addBodyPart(text);// 将图片MimeBodyPart对象加入MimeMultipart中mm.addBodyPart(image);// 设置MimeMultipart对象的相对熟悉为related,即发送的数据为文本+非附件资源mm.setSubType("related");// 设置到消息中,保存修改message.setContent(mm);// 将MimeMultipart放入消息对象中message.saveChanges();// 保存上面的修改System.out.println("===============================================================");// 5.发送邮件——在网页上点击发送按钮ts.sendMessage(message, message.getAllRecipients());// 6.关闭连接对象,即关闭服务器上的连接资源ts.close();}
}

测试运行:
在这里插入图片描述

网站注册发送邮件功能实现

package com.github.pojo;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;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +'}';}
}

编写工具类Sendmail.java:

package com.github.util;/*** 多线程实现邮件发送* 使用多线程的原因就是提高用户的体验,一旦一个页面3s及以上的时间白屏就可能被用户关掉* 所以我们在用户提交表单之后,将费时的邮件发送工作使用一个子线程来完成,而主线程还是去完成它自己的事情* 这么做就可以提高用户体验,不然用户等待邮件发送的时间*/import com.github.pojo.User;
import com.sun.mail.util.MailSSLSocketFactory;import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;/*** @author subei* 多线程这种处理就可以称为异步处理*/
public class Sendmail extends Thread{// 用于向客户发送邮件的邮箱private String from = "XXXX@qq.com";// 用于登陆SMTP服务器的用户名private String username = "XXXX@qq.com";// 授权码private String password = "授权码";// 发送邮件的地址private String host = "smtp.qq.com";private User user;public Sendmail(User user) {this.user = user;}@Overridepublic void run() {try {Properties prop = new Properties();// 设置QQ邮件服务器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);// 1.创建定义整个应用程序所需的环境信息的 Session 对象// 使用QQ邮箱的时候才需要,其他邮箱不需要这一段代码// 获取和SMTP服务器的连接对象Session session = Session.getDefaultInstance(prop, new Authenticator() {@Overridepublic PasswordAuthentication getPasswordAuthentication() {// 发件人邮件用户名、授权码return new PasswordAuthentication("XXXX@qq.com", "授权码");}});// 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态session.setDebug(true);// 2.通过session得到transport对象Transport ts = session.getTransport();// 3.使用邮箱的用户名和授权码连上SMTP邮件服务器,即登陆ts.connect(host, 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><p>您的密码:" + user.getPassword() +"</p><p>请妥善保管您的密码,如有问题请及时联系网站客服,再次欢迎您的加入!!</p>", "text/html;charset=UTF-8");// 5.发送邮件——在网页上点击发送按钮ts.sendMessage(message, message.getAllRecipients());// 6.关闭连接对象,即关闭服务器上的连接资源ts.close();} catch (Exception e) {e.printStackTrace();}}
}

编写Servlet.java:

package com.github.servlet;import com.github.pojo.User;
import com.github.util.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 {@Overrideprotected 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);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

在这里插入图片描述
🎉🎉全剧终🎉🎉


http://www.hkcw.cn/article/WMcXUPkViE.shtml

相关文章

标题:2025海外短剧爆发年:APP+H5双端系统开发,解锁全球流量与变现新大陆

描述&#xff1a; 2025年出海新风口&#xff01;深度解析海外短剧系统开发核心&#xff08;APPH5双端&#xff09;&#xff0c;揭秘高效开发策略与商业化路径&#xff0c;助您抢占万亿美元市场&#xff01; 全球娱乐消费模式正在剧变。2025年&#xff0c;海外短剧市场已从蓝海…

uni-app学习笔记十六-vue3页面生命周期(三)

uni-app官方文档页面生命周期部分位于页面 | uni-app官网。 本篇再介绍2个生命周期 1.onUnload&#xff1a;用于监听页面卸载。 当页面被关闭时&#xff0c;即页面的缓存被清掉时触发加载onUnload函数。 例如:在demo6页面点击跳转到demo4&#xff0c;在demo4页面回退不了到d…

钉钉红包性能优化之路

一、业务背景 请客红包、小礼物作为饿了么自研的业务产品&#xff0c;在钉钉的一方化入口中常驻&#xff0c;作为高UV、PV的toB产品&#xff0c;面对不同设备环境的用户&#xff0c;经常会偶尔得到一些用户反馈&#xff0c;如【页面白屏太久了】、【卡住了】等等&#xff0c;本…

鲲鹏Arm+麒麟V10 K8s 离线部署教程

针对鲲鹏 CPU 麒麟 V10 的离线环境&#xff0c;手把手教你从环境准备到应用上线&#xff0c;所有依赖包提前打包好&#xff0c;步骤写成傻瓜式操作指南。 一、环境规划# 准备至少两台机器。 架构OS作用Arm64任意&#xff0c;Mac 也可以下载离线包Arm64麒麟 V10单机部署 K8s…

Redis主从复制详解

概述 Redis 的主从复制&#xff08;Master-Slave Replication&#xff09;是实现数据备份、读写分离和水平扩展的核心机制之一。通过主从复制&#xff0c;一个主节点&#xff08;Master&#xff09;可以将数据同步到多个从节点&#xff08;Slave&#xff09;&#xff0c;从节点…

16.进程间通信(二)

一、命名管道 1.概念 匿名管道解决了具有血缘关系的进程之间的通信&#xff0c;如果两个进程毫不相干&#xff0c;如何进行通信呢&#xff1f;通过文件&#xff0c;管道文件。 对于两个不同进程&#xff0c;打开同一路径下的同一文件&#xff0c;inode和文件内核缓冲区不会加载…

优化的两极:凸优化与非凸优化的理论、应用与挑战

在机器学习、工程设计、经济决策等众多领域&#xff0c;优化问题无处不在。而在优化理论的世界里&#xff0c;凸优化与非凸优化如同两个截然不同的 “王国”&#xff0c;各自有着独特的规则、挑战和应用场景。今天&#xff0c;就让我们深入探索这两个优化领域的核心差异、算法特…

day15 leetcode-hot100-29(链表8)

19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 1.暴力法 思路 &#xff08;1&#xff09;先获取链表的长度L &#xff08;2&#xff09;然后再次遍历链表到L-n的位置&#xff0c;直接让该指针的节点指向下下一个即可。 2.哈希表 思路 &#xff0…

rtpinsertsound:语音注入攻击!全参数详细教程!Kali Linux教程!

简介 2006年8月至9月期间&#xff0c;我们创建了一个用于将音频插入指定音频&#xff08;即RTP&#xff09;流的工具。该工具名为rtpinsertsound。 该工具已在Linux Red Hat Fedora Core 4平台&#xff08;奔腾IV&#xff0c;2.5 GHz&#xff09;上进行了测试&#xff0c;但预…

谷歌Stitch:AI赋能UI设计,免费高效新利器

在AI技术日新月异的今天&#xff0c;各大科技巨头都在不断刷新我们对智能工具的认知。最近&#xff0c;谷歌在其年度I/O开发者大会期间&#xff0c;除了那些聚光灯下的重磅发布&#xff0c;还悄然上线了一款令人惊喜的AI工具——Stitch。这是一款全新的、完全免费的AI驱动UI&am…

PowerBI企业运营分析——线性回归销售预测

PowerBI企业运营分析——线性回归销售预测 欢迎来到Powerbi小课堂&#xff0c;在竞争激烈的市场环境中&#xff0c;企业运营分析平台成为提升竞争力的核心工具。 该平台通过整合多源数据&#xff0c;实现关键指标的实时监控&#xff0c;从而迅速洞察业务动态&#xff0c;精准…

<4>, Qt窗口

目录 一&#xff0c;菜单栏 二&#xff0c;工具栏 三&#xff0c;状态栏 四&#xff0c;浮动窗口 五&#xff0c;对话框 一&#xff0c;菜单栏 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);// 创建菜单栏…

多目标粒子群优化算法(MOPSO),用于解决无人机三维路径规划问题,Matlab代码实现

多目标粒子群优化算法&#xff08;MOPSO&#xff09;&#xff0c;用于解决无人机三维路径规划问题&#xff0c;Matlab代码实现 目录 多目标粒子群优化算法&#xff08;MOPSO&#xff09;&#xff0c;用于解决无人机三维路径规划问题&#xff0c;Matlab代码实现效果一览基本介绍…

具有离散序列建模的统一多模态大语言模型【AnyGPT】

第1章 Instruction 在人工智能领域、多模态只语言模型的发展正迎来新的篇章。传统的大型语言模型(LLM)在理解和生成人类语言方面展现出了卓越的能力&#xff0c;但这些能力通常局限于 文本处理。然而&#xff0c;现实世界是一个本质上多模态的环境&#xff0c;生物体通过视觉、…

嵌入式学习笔记 - STM32 HAL库以及标准库内核以及外设头文件区别问题

一 CMSIS内核驱动文件夹 标准库中CMSIS内核驱动文件夹中&#xff0c;仅包含两个.h文件&#xff0c;其中stm32f10x.h 为stm10系列底层文件如总线以及各片上外设模块寄存器地址&#xff0c;system_stm32f10x.h为系统底层配置文件&#xff0c;主要为时钟配置。 HAL库中CMSIS内核驱…

LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表

LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表 第 一 题 - - - 移 除 链 表 元 素方 法 一 - - - 原 地 删 除方 法 二 - - - 双 指 针方 法 三 - - - 尾 插 第 二 题 - - - 反 转 链 表方 法 一 - - - 迭 代方 法 二 - - - 采 用 头 插 创 建 新 链 表 总 结 &a…

Ros真(node?package?)

Ros中 都是靠一个个节点相互配合的 如同APP之间的配合 然后节点不好单独存在&#xff0c; 我们一般把他们放在一个包里 也就是Package。 也可以自己设立一个包 如图这种 ———————————— 建立包 流程 &#xff1a; —————— 我们弄好之后 在VSCODE SRC右键 …

电路图识图基础知识-常用仪表识图及接线(九)

一、 直流电流表的使用和接线 用来测量直流电流的仪表&#xff0c;我们称为直流电流表&#xff0c;下图所示为直流电流表。 直流电流表有两种接入方式&#xff1a;直接接入法、间接接入法。下图所示为直流电流表接线方 法 。 4.1.2 交流电流表的使用和接线 交流电流表也是一种…

分享两款使用免费软件,dll修复工具及DirectX修复工具

装软件老是弹窗报错&#xff1f;两个小工具解决系统运行库问题 安装软件时弹出DLL缺失&#xff1f;别急&#xff0c;这里有办法 安装软件的时候&#xff0c;突然跳出个弹窗&#xff0c;提示缺少什么“MSVCP140.dll”或者“VCRUNTIME140.dll”&#xff0c;完全不懂。这种情况并…

L56.【LeetCode题解】 电话号码的字母组合

目录 1.17. 电话号码的字母组合 2.分析 举例 枚举算法:使用递归(dfs) 递推 回归 特殊情况的考虑 代码 提交结果 事后回顾: 递归调用的部分展开图 1.17. 电话号码的字母组合 https://leetcode.cn/problems/letter-combinations-of-a-phone-number/ 给定一个仅包含数字…