1.文件上传

新建空项目

准备工作

在maven仓库里下载commons io 和 commons fileupload两个jar包

实用类介绍

文件上传注意事项

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

  • 为防止文件覆盖现象发生,要为上传文件产生一个唯一的文件名:可以使用时间戳、uuid、MD5等方式解决文件重名问题

  • 要限制上传文件的最大值

  • 可以上至上传文件的类型,在收到上传文件名时,判断后缀名是否合法

需要用到的类详解

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

FileItem类

在HTML页面中必须有name

<form action="" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"><br>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file1"></p>
    <p><input type="submit">   <input type="reset"></p>
</form>

浏览器表单的类型如果为multipart/form-data,在服务器端想要获取数据就要通过流

常用方法介绍

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

//getName方法用于获得文件上传字段中的文件名
String getName();

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

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

ServletFileUpload类

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用其parseRequest(HttpServletRequest)方法可以将通过表单中每一个Html标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回,使用该方法处理上传文件简单易用

代码编写

FileServlet代码

package com.tang.servlet;

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;

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;

public class FileServlet extends HttpServlet {

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

        //判断上传的文件是普通表单还是带文件的表单
        if(!ServletFileUpload.isMultipartContent(req)){
            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();//创建这个临时目录
        }

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

        try {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2、获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3、处理上传文件。
            String msg = uploadParseRequest(upload,req,uploadPath);
            //Servlet请求转发消息
            req.setAttribute("msg",msg);
            req.getRequestDispatcher("/info.jsp").forward(req,resp);
        }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 req,String uploadPath) throws IOException, FileUploadException {
        String msg = "";
        //3、处理上传文件。
        //把前端的请求解析,封装成一个FileItem对象,需要从ServletFileUpLoad对象中获取
        List<FileItem> fileItems = upload.parseRequest(req);
        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+"】");
                //======================存放地址=======================//
                //存到哪?uploadPath
                //文件真实存在的路径 realPath
                String realPath = uploadPath+"/"+uuidPath;
                //给每一个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if(!realPathFile.exists()){
                    realPathFile.mkdir();
                }
                //======================文件传输=======================//
                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);

                //创建一个缓冲区
                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;
    }
    @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>FileServlet</servlet-name>
        <servlet-class>com.tang.servlet.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FileServlet</servlet-name>
        <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>
</web-app>

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: twq
  Date: 2022/8/3
  Time: 17:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--通过表单上传文件
    get:上传文件大小有限制
    post:上传文件大小没有限制
--%>
<%--${pageContext.request.contextPath}获取服务器路径--%>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"><br>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file1"></p>
    <p><input type="submit">   <input type="reset"></p>
</form>
</body>
</html>

info.jsp


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

运行结果图

2.邮件发送

电子邮件

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

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

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

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

传输协议

SMTP协议

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

POP3协议

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

邮件收发送原理图


原理图的描述:

  • 大Twq通过smtp协议连接到smtp服务器,然后发送一封邮件给网易的邮件服务器.

  • 网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的smtp服务器.

  • QQ将接收到的邮件存储在1430953131@qq.com这个邮件账号的空间中.

  • 小Twq通过Pop3协议连接到Pop3服务器收取邮件.

  • 从1430953131@qq.com这个邮件账号的空间中取出邮件.

  • Pop3服务器将取出来的邮件送到小Twq手中.

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

概述

我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如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邮件处理程序。


测试代码如下

package com.tang;

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() {
                                //发件人邮件用户名、ctoigssycmpybaaj授权码在开启QQ邮箱的POP3协议之后会自动生成,复制下来即可。
                                return new PasswordAuthentication("1430953131@qq.com", "ctoigssycmpybaaj");
                        }
                });

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

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

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

                //4、创建邮件:写邮件。
                //注意需要传递Session。
                MimeMessage message = new MimeMessage(session);
                //指明邮件的发件人
                message.setFrom(new InternetAddress("1430953131@qq.com"));
                //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发。
                message.setRecipient(Message.RecipientType.TO, new InternetAddress("1430953131@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();

        }

}

运行结果

发送带图片和附件的邮件

发送带图片的和文本

先认识两个类一个名词:

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.tang;

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 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"); // 需要验证用户名密码。


                //使用JavaMail发送邮件的5个步骤:

                //1、创建定义整个应用程序所需的环境信息的 Session 对象。
                //QQ才有!其他邮箱不需要。
                Session session = Session.getDefaultInstance(prop, new Authenticator() {
                        public PasswordAuthentication getPasswordAuthentication() {
                                //发件人邮件用户名、ctoigssycmpybaaj授权码在开启QQ邮箱的POP3协议之后会自动生成,复制下来即可。
                                return new PasswordAuthentication("1430953131@qq.com", "ctoigssycmpybaaj");
                        }
                });

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

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

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

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

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

                //准备图片数据。
                MimeBodyPart image = new MimeBodyPart();
                //图片需要经过数据处理.. DataHadnler:数据处理
                DataHandler dh = new DataHandler(new FileDataSource("/Users/twq/Downloads/Javaweb-FileUpLoad/MailSending/src/1.png"));
                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();

        }

}

运行结果图

发送含文本,图片和附件的邮件

package com.tang;

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 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"); // 需要验证用户名密码。


                //使用JavaMail发送邮件的5个步骤:

                //1、创建定义整个应用程序所需的环境信息的 Session 对象。
                //QQ才有!其他邮箱不需要。
                Session session = Session.getDefaultInstance(prop, new Authenticator() {
                        public PasswordAuthentication getPasswordAuthentication() {
                                //发件人邮件用户名、ctoigssycmpybaaj授权码在开启QQ邮箱的POP3协议之后会自动生成,复制下来即可。
                                return new PasswordAuthentication("1430953131@qq.com", "ctoigssycmpybaaj");
                        }
                });

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

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

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

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

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

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

                //图片
                MimeBodyPart body1 = new MimeBodyPart();
                body1.setDataHandler(new DataHandler(new FileDataSource("/Users/twq/Downloads/Javaweb-FileUpLoad/MailSending/src/1.png")));
                body1.setContentID("Twq.png"); //图片设置ID

                //文本
                MimeBodyPart body2 = new MimeBodyPart();
                body2.setContent("请注意,我不是广告<img src='cid:Twq.png'>","text/html;charset=utf-8");

                //附件
                MimeBodyPart body3 = new MimeBodyPart();
                body3.setDataHandler(new DataHandler(new FileDataSource("/Users/twq/Downloads/Javaweb-FileUpLoad/MailSending/src/1.txt")));
                body3.setFileName("test.c"); //附件设置名字

                MimeBodyPart body4 = new MimeBodyPart();
                body4.setDataHandler(new DataHandler(new FileDataSource("/Users/twq/Downloads/Javaweb-FileUpLoad/MailSending/src/1.txt")));
                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();

        }

}

JavaWeb发送邮件

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

代码实现:
项目包结构

User实体类代码

package com.tang.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;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

}

RegisterServlet代码

package com.tang.servlet;

import com.tang.pojo.User;
import com.tang.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);
    }

}

Sendmail代码

package com.tang.utils;

import com.tang.pojo.User;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class Sendmail extends Thread{
    //用于给用户发送邮件的邮箱。
    private String from = "1430953131@qq.com";
    //邮箱的用户名。
    private String username = "1430953131@qq.com";
    //邮箱的密码。
    private String password = "ctoigssycmpybaaj";
    //发送邮件的服务器地址。
    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("1430953131@qq.com", "ctoigssycmpybaaj");
                }
            });

            //开启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);
        }
    }
}

注册界面

<%@ 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="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</title>
</head>
<body>
<h1>xxx网站温顺提示!</h1>
${message}
</body>
</html>

web.xml注册代码

   <servlet>
        <servlet-name>WebMail</servlet-name>
        <servlet-class>com.tang.servlet.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>WebMail</servlet-name>
        <url-pattern>/RegisterServlet.do</url-pattern>
    </servlet-mapping>

运行结果图