狂神。JavaWeb学习(3)(文件上传和邮件发送)

1、文件上传

1.1、准备工作

搭建一个空项目。细节不在赘述!😄

注意点

这个路径记得要检查一下,要不不知道自己建到哪去了。

在这里插入图片描述

这里不要忘记写。

在这里插入图片描述


项目搭建好后,建议先运行一下,测试项目框架是否搭建完成。

然后还需要导包:commons-fileupload-1.4.jar 和 commons-io-2.6.jar。

传送门——>

commons-fileupload-1.4.jar

commons-io-2.6.jar

有两种导包方式:

  • 如果我们建的是Mavne项目,把依赖复制到Pom.xml 中。
  • 如果我们建的普通项目,新建一个lib目录,在下图下载jar包,复制到lib目录下,然后右键点Add as Library。

在这里插入图片描述

注意这里问题的话,注意点一下修复。(本人在这里没检查导致项目运行不起啦,被坑了一次)

在这里插入图片描述

右键新建的Servlet爆红的话,快捷键导包:JavaEE 6~javaEE 6.

在这里插入图片描述

1.2、实现原理

在这里插入图片描述

文件上传的注意事项:

  1. 为保证服务器安全,上传的文件存放在外界无法直接访问的目录下,比如放在WEB-INF目录下。

  2. 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。(-时间戳、-uuid、-md5…)

  3. 限制上传文件的最大值。

  4. 可以限制上传文件的类型,在收到上传文件名时,判断后缀名知否合法。(.mp4、.txt、.jpg、.png、.doc…)

1.3、使用类介绍

需要用到的类详解:

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象, 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。

  • ServletFileUpload:在后端获取文件上传的文件数据,并将上传文件数据的表单中的每个输入项都封装为一个FileItem对象。
  • FileItem.
  • DiskFileItemFactory:使用ServletFileUpload解析前端表单传过来的文件数据时需要使DiskFileItemFactory对象,所以在获取ServletFileUpload对象之前我们需要先获取DiskFileItemFactory对象。
  • fileItemFactory属性:ServletFileUpload对象的一个属性。

文件上传用到的方法:

//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();//即:只要是上传的文件,返回的就是false

//getFieldName方法用于返回表单标签name属性的值。
String getFieldName();//获取这个input的name属性值

//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();//用字符串存储文件的数据流
    
//getName方法用于获得文件上传字段中的文件名
String getName();

//以流的形式返回上传文件的数据内容。
InputStream getInputStream()

//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();

1.4、编写项目

  • 文件上传的Servlet
package com.kuang.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class FileServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //判断上传的表单是 普通表单(比如字符串) 还是 带文件的表单 ,是返回true,否返回false;
        if (!ServletFileUpload.isMultipartContent(request)){
            return;//如果这是一个普通文件我们直接返回.否则,说明我们的表单是带文件上传的.
        }

        //创建上传文件的保存目录,为了安全建议在WEB-INF目录下,用户无法访问。安全。
        String uploadpath = this.getServletContext().getRealPath("WEB-INF/Upload");//获取上传文件的保存路径。
        File uploadfile = new File(uploadpath);
        if (!uploadfile.exists()){
            uploadfile.mkdir();//如果目录不存在就创建这样一个目录。
        }

        //临时文件
        //临时路径,如果上传的文件超过预期的大小,我们将它存放到一个临时目录中,过几天自动删除,或者提醒用户转存为永久。
        String tmppath = this.getServletContext().getRealPath("WEB-INF/tmp");
        File file = new File(tmppath);
        if (!file.exists()){
            file.mkdir();//如果目录不存在就创建这样临时目录。
        }

        //处理上传的文件一般需要通过流来获取,我们可以通过request.getInputstream(),原生态文件上传流获取,十分麻烦。
        //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;

        try {
            //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小。
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2、获取ServletFileUpload.
            ServletFileUpload upload = getServletFileUpload(factory);
            //3、处理上传文件
            String msg = uploadParseRequest(upload,request,uploadpath);
            //Servlet请求转发消息
            request.setAttribute("msg",msg);
            request.getRequestDispatcher("/info.jsp").forward(request,response);
        }catch (FileUploadException e){
            e.printStackTrace();
        }
    }


    public static DiskFileItemFactory getDiskFileItemFactory(File file){
        //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小.
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;
        //这里不设置的话也有默认的。
        factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M.
        factory.setRepository(file);
        return factory;
    }


    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        //2、获取ServletFileUpload。
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度。
        upload.setProgressListener(new ProgressListener() {
            public void update(long pBytesRead, long lpContentLenght, int i) {
                //pBytesRead:已读取到的文件大小。
                //pContentLenght:文件大小。
                System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);//在这里还可以加进度。
            }
        });
        //处理乱码问题.
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值.
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置总共能够上传文件的大小.
        //1024 = 1kb * 1024 = 1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);
        return upload;
    }


    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException {
        String msg = "";
        //3、处理上传文件。
        //把前端的请求解析,封装成一个FileItem对象。
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单。
                //getFieldName指的是前端表单控件的name。
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8");//处理乱码。
                System.out.println(name+":"+value);
            }else {//判断它是带文件的表单。

                //======================处理文件=======================//

                //拿到文件的名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:"+uploadFileName);

                if (uploadFileName.trim().equals("") || uploadFileName == null){
                    continue;
                }

                //获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要。
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                //获得文件的后缀名。
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                /*
                如果文件后缀名fileExtName不是我们所需要的。
                就直接return,不处理,告诉用户文件类型不对。
                */

                //可以使用UUID(唯一识别的通用码),保证文件名唯一。
                //UUID.randomUUID,随机生一个唯一识别的通用码。

                //网络传输中的东西,都需要序列化。
                //pojo,实体类,如果想要在多个电脑运行,传输--->需要吧对象都序列化了。
                //JNI=java Native Interface
                //implements Serializable :标记接口,JVM--->java栈 本地方法栈 native-->c++

                String uuidPath= UUID.randomUUID().toString();

                System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");

                //可以使用UUID(唯一通用识别码)来保证文件名的统一。
                String uuidFileName = UUID.randomUUID().toString();

                //=======================传输文件=========================//

                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);

                //创建一个缓冲区
                byte[] buffer = new byte[1024 * 1024];

                //判断是否读取完毕
                int len = 0;

                //如果大于0,说明还存在数据
                while ((len=inputStream.read(buffer))>0){
                    fos.write(buffer,0,len);
                }

                //关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete();//上传成功,清除临时文件
            }
        }
        return msg;
    }

}
  • 主页

注意:如果一个表单中包含文件数据,那么该表单如果想要提交文件数据,那么它必须包含enctype属性,且属性值必须为enctype=“multipart/form-data”

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Title</title>
</head>
<body>


<%--
通过表单上传文件:
get:上传文件大小有限制,方式只能提交4-5kb的数据。
post:上传文件大小没有限制。
注意:文件一般比较大,所以上传文件都是使用post方式提交。
${pageContext.request.contextPath}:获取到webapp路径。
--%>
<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
  <p>上传用户:<input type="text" name="username"><br/></p>
  <p>上传文件1:<input type="file" name="file1"></p>
  <p>上传文件2:<input type="file" name="file2"></p>
  <p><input type="submit" value="点击上传"> | <input type="reset" value="重置"></p>
</form>


</body>
</html>
  • 文件上传成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>提示信息</title>
</head>
<body>

${msg}

</body>
</html>
  • 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>FileServlet</servlet-name>
        <servlet-class>com.kuang.servlet.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FileServlet</servlet-name>
        <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>

</web-app>

1.5、测试结果

选择上文件上传:

在这里插入图片描述

上传成功:

在这里插入图片描述


我们上传的文件到了哪里呢?

在项目结构中添加out文件:找到我们上传的文件。

在这里插入图片描述

2、邮件发送

2.1、电子邮件

  • 要在网络上实现邮件功能,必须要有专门的邮件服务器

  • 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。

  • SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。

  • 电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能。

2.2、传输协议

SMTP协议:发送邮件:

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

POP3协议:接收邮件:

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

邮件收发原理:

在这里插入图片描述

  1. 大狂神通过smtp协议连接到smtp服务器,然后发送一封邮件给网易的邮件服务器.
  2. 网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的smtp服务器.
  3. QQ将接收到的邮件存储在24736743@qq.com这个邮件账号的空间中.
  4. 小狂神通过Pop3协议连接到Pop3服务器收取邮件.
  5. 24736743@qq.com这个邮件账号的空间中取出邮件.
  6. Pop3服务器将取出来的邮件送到小狂神手中.

注意:有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试。

2.3、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邮件处理程序。

在这里插入图片描述

2.4、Java发送纯文本邮件

  1. 先在项目中导入两个jar包:

在这里插入图片描述

  1. QQ邮箱中获取对应的权限:

QQ邮箱需要安全验证,我们需要获取他对应的权限:

QQ邮箱–>邮箱设置–>账户

在这里插入图片描述

在这里插入图片描述

  1. 编写测试代码:
package com.kuang;

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 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() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码。
                return new PasswordAuthentication("717560396@qq.com", "yvaryyxadocabeii");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态。
        session.setDebug(true);

        //2、通过session得到transport对象。
        Transport ts = session.getTransport();

        //3、使用邮箱的用户名和授权码连上SMTP邮件服务器。
        ts.connect("smtp.qq.com", "717560396@qq.com", "yvaryyxadocabeii");

        //4、创建邮件:写邮件。
        //注意需要传递Session。
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("717560396@qq.com"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发。
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("717560396@qq.com"));
        //邮件的标题。
        message.setSubject("简单邮件发送实现");
        //邮件的文本内容。可以写html语句。
        message.setContent("<h2 style='color:red'>你好啊!</h2>", "text/html;charset=UTF-8");

        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());

        //6、关闭连接
        ts.close();
    }
}

2.5、Java发送带图片和附件的邮件

先认识两个类一个名词:

MIME(多用途互联网邮件扩展类型)

MimeBodyPart类:

javax.mail.internet.MimeBodyPart类,表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。

MimeMultipart类:

javax.mail.internet.MimeMultipart是抽象类,Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。

MimeMultipart对象的使用的时候需要设置setSubType()的属性值,一共就下面3种取值:

我们在使得的时候如果不知道使用哪一个,直接使用mixed即可,使用这个属性值一定不会报错。

在这里插入图片描述

创建包含内嵌图片的邮件

前面的例子中是单独的使用HTML或者是纯文本内容,但是有时候我们需要在纯文本中使用内嵌的方式显示一些图片,因此就要将纯文本和内嵌图片单独存放在MimeBodyPart中然后再将其存放在一个Mimemultipart对象中即可。

package com.kuang;

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 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() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码。
                return new PasswordAuthentication("717560396@qq.com", "yvaryyxadocabeii");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态。
        session.setDebug(true);

        //2、通过session得到transport对象。
        Transport ts = session.getTransport();

        //3、使用邮箱的用户名和授权码连上SMTP邮件服务器。
        ts.connect("smtp.qq.com", "717560396@qq.com", "yvaryyxadocabeii");

        //4、创建邮件:写邮件。
        //注意需要传递Session。
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("717560396@qq.com"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发。
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("717560396@qq.com"));
        //邮件的标题。
        message.setSubject("简单邮件发送实现");


        //发送包含图片的复杂邮件==========================================

        //准备图片数据。
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("/Users/wangcheng/IdeaProjects/功能拓展/mail-java/src/image/基德.jpg"));
        image.setDataHandler(dh);//在我们的Body中放入这个处理的图片数据。
        image.setContentID("bz.jpg");//给图片设置一个id,我们在后面可以使用!

        // 准备正文数据。
        MimeBodyPart text = new MimeBodyPart();
        //这里的cid就是上面的哪个setContentID。
        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");//设置MimeMultipart对象的相对熟悉为related,即发送的数据为文本+非附件资源。

        //设置到消息中,保存修改。
        message.setContent(mm);//把最后编辑好的邮件放到消息当中。
        message.saveChanges();//保存上面的修改。

        //发送包含图片的复杂邮件==========================================


        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());

        //6、关闭连接
        ts.close();
    }
}

2.6、Java发送带图片和附件的复杂邮件发送

package com.kuang;

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 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() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码。
                return new PasswordAuthentication("717560396@qq.com", "yvaryyxadocabeii");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态。
        session.setDebug(true);

        //2、通过session得到transport对象。
        Transport ts = session.getTransport();

        //3、使用邮箱的用户名和授权码连上SMTP邮件服务器。
        ts.connect("smtp.qq.com", "717560396@qq.com", "yvaryyxadocabeii");

        //4、创建邮件:写邮件。
        //注意需要传递Session。
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("717560396@qq.com"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发。
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("717560396@qq.com"));
        //邮件的标题。
        message.setSubject("简单邮件发送实现");


        //发送包含附件的复杂邮件=====================================================

        /*
        编写邮件内容
        1.图片
        2.附件
        3.文本
         */

        //图片
        MimeBodyPart body1 = new MimeBodyPart();
        body1.setDataHandler(new DataHandler(new FileDataSource("/Users/wangcheng/IdeaProjects/功能拓展/mail-java/src/image/基德.jpg")));
        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("/Users/wangcheng/IdeaProjects/功能拓展/mail-java/src/image/TrainPlan.docx")));
        body3.setFileName("test.c"); //附件设置名字

        MimeBodyPart body4 = new MimeBodyPart();
        body4.setDataHandler(new DataHandler(new FileDataSource("/Users/wangcheng/IdeaProjects/功能拓展/mail-java/src/image/TrainPlan.docx")));
        body4.setFileName("test.txt"); //附件设置名字

        //拼装邮件正文内容
        MimeMultipart multipart1 = new MimeMultipart();
        multipart1.addBodyPart(body1);
        multipart1.addBodyPart(body2);
        multipart1.setSubType("related"); //1.文本和图片内嵌成功!

        //new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体
        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();
    }
}

2.7、JavaWeb发送邮件

​ 现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。

代码实现:

  1. 新建一个JavaWeb项目,配置tomcat,添加jar包。

在这里插入图片描述

  1. 编写对应的用户实体类。
package com.kuang.pojo;

//User实体类.
//等学到框架就不用写这么多东西了,用注解。
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 + '\'' +
                '}';
    }
}
  1. 前端注册页面。
<%@ 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>
  1. 邮件发送工具类。
package com.kuang.utils;

import com.kuang.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;

//网站3秒原则:用户体验。
//多线程实现用户体验!(异步处理)
public class Sendmail extends Thread{

    //用于给用户发送邮件的邮箱。
    private String from = "717560396@qq.com";
    //邮箱的用户名。
    private String username = "717560396@qq.com";
    //邮箱的密码。
    private String password = "yvaryyxadocabeii";
    //发送邮件的服务器地址。
    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);
            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 对象。
            Session session = Session.getDefaultInstance(prop, new Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    //发件人邮件用户名、授权码
                    return new PasswordAuthentication("717560396@qq.com", "yvaryyxadocabeii");
                }
            });

            //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态。
            session.setDebug(true);

            //2、通过session得到transport对象。
            Transport ts = session.getTransport();

            //3、使用邮箱的用户名和授权码连上邮件服务器。
            ts.connect(host, username, password);

            //4、创建邮件。
            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();

            //发送邮件。
            ts.sendMessage(message, message.getAllRecipients());
            ts.close();

        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
  1. 编写对应的servlet处理类。
package com.kuang.servlet;

import com.kuang.pojo.User;
import com.kuang.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 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 sendmail = new Sendmail(user);
        //启动线程,线程启动之后会执行run方法来发送邮件。
        new Thread(sendmail).start();

        //注册用户。
        req.setAttribute("message","注册成功!我们已经向您的邮箱发送了邮件,请您及时进行查收。由于网络原因,您收到邮件的时间存在延迟,敬请谅解~");
        req.getRequestDispatcher("info.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

}
  1. 配置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>RegisterServlet</servlet-name>
        <servlet-class>com.kuang.servlet.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/RegisterServlet.do</url-pattern>
    </servlet-mapping>


</web-app>
  1. 发送成功或失败的反馈页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>xxx网站温顺提示!</h1>
${message}

</body>
</html>

  1. Pom.xml导入servlet的依赖!

    运行Tomcat测试!(注意tomcat要重新配置)

在这里插入图片描述

在这里插入图片描述

邮件发送成功,OK!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值