第1天学习打卡(Javaweb 邮件发送:原理、发送简单文本邮件、发送带图片和附件邮件、网站注册发送邮件Servlet实现)

本文详细介绍了如何使用JavaMail API通过SMTP和POP3协议发送简单邮件和带图片、附件的复杂邮件,包括设置SMTP服务器、创建Session、MimeMessage和MimeMultipart的使用,以及在网站注册过程中发送验证邮件的实战示例。
摘要由CSDN通过智能技术生成

六、邮件收发

电子邮件

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

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

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

电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。

传输协议

SMTP协议

发送邮件:

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

POP3协议

接收邮件:

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

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

Java发送邮件

概述:

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

使用java发送E-mail十分简单,但是首先你应该准备JavaMail和Java Activation Framework.

得到两个jar包:

  • mail.jar

    下载地址:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7

  • activation.jar

    下载地址:https://mvnrepository.com/artifact/javax.activation/activation/1.1.1

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

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

  • 创建包含邮件服务器的网络连接信息的Session对象。

  • 创建代表邮件内容的Message对象

  • 创建Transport对象,连接服务器,发送Message,关闭连接

主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。

image-20210703173132105

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

简单邮件:没有附件和图片,纯文本邮件
复杂邮件:有附件和图片,不是纯文本邮件

发送简单邮件

使用JavaMail发送邮件五个步骤:

1.创建定义整个应用程序所需的环境信息的Session对象
2.通过Session得到transport对象
3.使用邮箱的用户名和授权码连上邮件服务器
4.创建邮件:写邮件【主体】
5.发送邮件
6.关闭连接

纯文本邮件

注意QQ邮箱SSL加密有两个地方不同于其他邮箱

package com.kuang.servlet;

import com.sun.mail.util.MailSSLSocketFactory;

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

//简单邮件:文本
public class MailDemo01 {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        Properties prop=new Properties();
        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发送邮件五个步骤
        1.创建定义整个应用程序所需的环境信息的Session对象
        2.通过Session得到transport对象
        3.使用邮箱的用户名和授权码连上邮件服务器
        4.创建邮件:写邮件【主体】
        5.发送邮件
        6.关闭连接
         */

        //1.创建定义整个应用程序所需的环境信息的Session对象
        //QQ邮箱才需在初始化Session时,需要授权new Authenticator(),其他邮箱不用
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人邮箱用户名,授权码
                return new PasswordAuthentication("xxxx@qq.com","授权码");

            }
        });

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

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

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

        //4.创建邮件:写邮件
        //主要专递session
        MimeMessage message=new MimeMessage(session);

        //指明邮件的发件人
        message.setFrom(new InternetAddress("xxxx@qq.com"));
        //指明邮件收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("18260036612@163.com"));
        //邮件的主题
        message.setSubject("简单邮件");
        //邮件的文本内容
        message.setContent("<h1 style='color:red'>只有文本的简单邮件<h1>","text/html;charset=utf-8");

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

        //6.关闭连接
    }
}

带图片和附件的邮件

先认识两个类一个名词:

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

MimeBodyPart类

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

MimeMultipart类

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

image-20210703174311271

文本中嵌入图片的邮件

只有邮件的内容发生了改变

MimeBodyPart相当于是一层封装,文本、图片、附件各自有封装,最后再封装一次

package com.kuang.servlet;

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.security.GeneralSecurityException;
import java.util.Properties;

//文本+嵌入文本的内容
public class MailDemo02 {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        Properties prop=new Properties();
        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发送邮件五个步骤
        1.创建定义整个应用程序所需的环境信息的Session对象
        2.通过Session得到transport对象
        3.使用邮箱的用户名和授权码连上邮件服务器
        4.创建邮件:写邮件【主体】
        5.发送邮件
        6.关闭连接
         */

        //1.创建定义整个应用程序所需的环境信息的Session对象
        //QQ邮箱才需在初始化Session时,需要授权new Authenticator(),其他邮箱不用
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人邮箱用户名,授权码
                return new PasswordAuthentication("xxxx@qq.com","授权码");

            }
        });

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

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

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

        //4.创建邮件:写邮件
        //主要专递session
        MimeMessage message=new MimeMessage(session);

        //指明邮件的发件人
        message.setFrom(new InternetAddress("xxxx@qq.com"));
        //指明邮件收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("xxxx@qq.com"));
        //邮件的主题
        message.setSubject("简单邮件");

        //********************只有邮件的内容发生了改变*******************
        //邮件的内容:文本+嵌入文本的图片
        //MimeBodyPart相当于是一层封装,文本、图片、附件各自有封装,最后再封装一次
        //1)准备图片,需要经过数据处理
        MimeBodyPart image=new MimeBodyPart();
        DataHandler dataHandler=new DataHandler(new FileDataSource("E:\\winfile\\桌面\\javaweb\\maven\\mail\\src\\1.png"));
        image.setDataHandler(dataHandler);
        image.setContentID("bz.jpg");

        //2)准备正文数据
        MimeBodyPart text=new MimeBodyPart();
        text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件","text/html;charset=UTF-8");

        //3)图片和文本封装在一起,描述数据关系
        MimeMultipart mm=new MimeMultipart();
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("related");

        //4)设置到消息中,保存修改
        message.setContent(mm); //把最后编辑好的文件放到消息中去
        message.saveChanges(); //保存修改

        //***********************************************************

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

        //6.关闭连接
    }
}


文本中嵌入图片、带有附件的邮件

邮件内容提取成一个方法

  1. 图片,需要经过数据处理 MimeBodyPart1
  2. 文本 MimeBodyPart2
  3. 附件 MimeBodyPart3
  4. 图片和文本嵌套 MimeBodyPart1+MimeBodyPart2=>MimeMultipart1
  5. MimeMultipart=>multipart1再封装成MimeBodyPart,将imageText和附件组合 >MimeMultipart1=>MimeBodyPart4 MimeBodyPart4+MimeBodyPart3=>MimeMultipart allFile
  6. 放到message消息中
package com.kuang.servlet;

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.security.GeneralSecurityException;
import java.util.Properties;

//文本+嵌入文本的内容
public class MailDemo03 {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        Properties prop=new Properties();
        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发送邮件五个步骤
        1.创建定义整个应用程序所需的环境信息的Session对象
        2.通过Session得到transport对象
        3.使用邮箱的用户名和授权码连上邮件服务器
        4.创建邮件:写邮件【主体】
        5.发送邮件
        6.关闭连接
         */

        //1.创建定义整个应用程序所需的环境信息的Session对象
        //QQ邮箱才需在初始化Session时,需要授权new Authenticator(),其他邮箱不用
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人邮箱用户名,授权码
                return new PasswordAuthentication("xxxx@qq.com","授权码");

            }
        });

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

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

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

        //********************只有邮件的内容发生了改变*******************

        //4.创建邮件:写邮件
        //邮件的内容:文本+嵌入文本的图片+附件
        //MimeBodyPart相当于是一层封装,文本、图片、附件各自有封装,最后再封装一次
        //此处将邮件内容提取成了一个方法
        MimeMessage message=imageMail(session);

        //***********************************************************

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

        //6.关闭连接
    }
    
    
    

     /**
     * 邮件内容提取成一个方法
     * @param session
     * @return
     * @throws MessagingException
     */
    public static MimeMessage imageMail(Session session) throws MessagingException {
        //主要专递session
        MimeMessage message=new MimeMessage(session);

        //指明邮件的发件人
        message.setFrom(new InternetAddress("xxxx@qq.com"));
        //指明邮件收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("xxxx@qq.com"));
        //邮件的主题
        message.setSubject("简单邮件");

        //********************只有邮件的内容发生了改变(文本、图片、附件)*******************
        /*
        1)图片,需要经过数据处理 MimeBodyPart1
        2)文本 MimeBodyPart2
        3)附件 MimeBodyPart3
        4)图片和文本嵌套 MimeBodyPart1+MimeBodyPart2=>MimeMultipart1
        5)MimeMultipart=>multipart1再封装成MimeBodyPart,将imageText和附件组合 >MimeMultipart1=>MimeBodyPart4 MimeBodyPart4+MimeBodyPart3=>MimeMultipart allFile
        6)放到message消息中
         */

        //1)图片,需要经过数据处理
        MimeBodyPart image=new MimeBodyPart();
        DataHandler dataHandler=new DataHandler(new FileDataSource("E:\\winfile\\桌面\\javaweb\\maven\\mail\\src\\1.png"));
        image.setDataHandler(dataHandler);
        image.setContentID("bz.jpg"); //图片设置ID

        //2)文本
        MimeBodyPart text=new MimeBodyPart();
        text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件","text/html;charset=UTF-8");

        //3)附件
        MimeBodyPart fujian=new MimeBodyPart();
        fujian.setDataHandler(new DataHandler(new FileDataSource("E:\\winfile\\桌面\\javaweb\\maven\\mail\\src\\刘杰.pdf")));
        fujian.setFileName("fujian.pdf"); //附件设置名字【图片设置很相似】

        //4)图片和文本嵌套
        MimeMultipart multipart1=new MimeMultipart(); //注意区分MimeBodyPart和MimeMultipart
        multipart1.addBodyPart(image);
        multipart1.addBodyPart(text);
        multipart1.setSubType("related");


        //MimeMultipart=>multipart1再封装成MimeBodyPart
        MimeBodyPart imageText=new MimeBodyPart();
        imageText.setContent(multipart1);
        //5)将imageText和附件组合
        MimeMultipart allFile=new MimeMultipart();
        allFile.addBodyPart(imageText);
        allFile.addBodyPart(fujian);
        allFile.setSubType("mixed");

        //6)放到message消息中
        message.setContent(allFile);
        message.saveChanges(); //保存修改

        return message;

    }

}

网站注册发送邮件Servlet实现

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

image-20210704003413185

用户注册页面 index.jsp

<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>

image-20210704003431513

用户注册成功页面 info.jsp

采用线程异步的形式,“邮件发送”和“舔砖用户注册成功页面”并发,因为邮件发送过程较慢,防止用户等待和页面加载时间过长;

<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>xx网站提示</h1>
    ${message}
</body>
</html>

邮件发送成功结果

image-20210704003554898

结构:

image-20210704004216451

用户通过index.jsp页面注册,交给RegisterServlet处理;

RegisterServlet通过Sendmail发送邮件,并转发到结果页面info.jsp

【易错】注意导包、引用包;

在structure中的Artifact的查看lib的包是否真的在程序运行是导入了,如果没有点击+号导入

image-20210704004603070

pojo包中实体类User

package com.kuang.pojo;

//实体类首先实现序列化接口Serializable,以方便进行网络传输
public class User {
    private String username;
    private String password;
    private String email;

    //构造方法
    public User(){

    }
    public User(String username, String password, String mail) {
        this.username = username;
        this.password = password;
        this.email = mail;
    }

    //getter和setter
    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 + '\'' +
                '}';
    }
}

utils包中Sendmail

将邮件发送提取成一个工具类

实现thread方法,便于使用线程

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秒原则:用户体验,网页不能白屏超过3s
//多线程实现用户体验(异步处理)
public class Sendmail extends Thread{
    //用于给用户发送邮件的邮箱
    private String from="840493237@qq.com";
    //邮箱用户名
    private String username="840493237@qq.com";
    //邮箱密码,授权码
    private String password="xdcptgfkrsmzbdjj";

    private String host="smtp.qq.com";

    private User user;
    public Sendmail(User user){
        this.user=user;
    }

    //重写run方法,在run方法中发送邮件给指定的用户
    public void run(){
        try {
            System.out.println(user.toString());

            Properties prop = new Properties();
            prop.setProperty("mail.host",host);///设置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时,需要授权new Authenticator(),其他邮箱不用
            Session session=Session.getDefaultInstance(prop, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    //发件人邮箱用户名,授权码
                    return new PasswordAuthentication("840493237@qq.com","ishrfshafzpybeid");

                }
            });

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

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

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

            //4.创建邮件:写邮件
            //主要专递session
            MimeMessage message=new MimeMessage(session);

            //指明邮件的发件人
            message.setFrom(new InternetAddress("840493237@qq.com"));
            //指明邮件收件人
            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");

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

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

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

}

servlet包中RegisterServlet

采用线程,异步处理“邮件发送”和“邮件发送成功”页面

package com.kuang.servlet;

import com.kuang.pojo.User;
import com.kuang.utils.Sendmail;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        String email=request.getParameter("email");

        User user = new User(username, password, email);

        //用户注册成功之后,给用户放松一封邮件
        //【关键】我们使用线程来专门发送邮件,防止出现耗时,和网址注册人数过多的情况
        Sendmail send=new Sendmail(user);
        //启动线程
        send.start();
        //send.run(); //这个不是多线程,它会等到程序结束才会弹出相应结果

        //注册用户
        request.setAttribute("message","注册成功,我们已经发了一封带注册信息的电子邮件,请查收!由于网络原因,您收到邮件的时间存在延迟,敬请谅解~");

        request.getRequestDispatcher("info.jsp").forward(request,response);
    }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值