狂神说

Java邮件发送详解
邮件收发电子邮件要在网络上实现邮件功能,必须要有专门的邮件服务器。这些邮件服务器类似于现实生活中的邮局,它主要负责...
扫描右侧二维码阅读全文
19
2019/07

Java邮件发送详解

邮件收发

电子邮件

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

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

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

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

1563453631997.png

传输协议

SMTP协议

发送邮件:

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

POP3协议

接收邮件:

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

邮件收发原理

1563454915374.png

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

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

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

1563462029520.png

纯文本邮件

先在项目中导入jar包

1563456199217.png

QQ邮箱中获取对应的权限

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

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

1563461331601.png

1563461425898.png

编写测试代码

package com.kuang.mail;

import com.sun.mail.util.MailSSLSocketFactory;

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class SendEmail {

    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个步骤

        //创建定义整个应用程序所需的环境信息的 Session 对象

        Session session = Session.getDefaultInstance(prop, new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("24736743@qq.com", "授权码");
            }
        });


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

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

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

        //4、创建邮件

        //创建邮件对象
        MimeMessage message = new MimeMessage(session);

        //指明邮件的发件人
        message.setFrom(new InternetAddress("24736743@qq.com"));

        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("24736743@qq.com"));

        //邮件的标题
        message.setSubject("只包含文本的简单邮件");

        //邮件的文本内容
        message.setContent("你好啊!", "text/html;charset=UTF-8");

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

        ts.close();
    }

}

带图片和附件的邮件

先认识两个类一个名词:

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

MimeBodyPart类

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

MimeMultipart类

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

1563462870340.png

创建包含内嵌图片的邮件

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

package com.kuang.mail;

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 SendImageEmail {
    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 对象
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("24736743@qq.com", "授权码");
            }
        });


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

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

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

        //4、创建邮件

        //创建邮件
        MimeMessage message = new MimeMessage(session);

        // 设置邮件的基本信息
        //发件人
        message.setFrom(new InternetAddress("24736743@qq.com"));
        //收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("24736743@qq.com"));
        //邮件标题
        message.setSubject("带图片的邮件");

        // 准备邮件数据

        // 准备图片数据
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
        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("related");

        //设置到消息中,保存修改
        message.setContent(mm);
        message.saveChanges();

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

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

package com.kuang.mail;

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 SendFileMail {
    public static void main(String[] args) throws MessagingException, GeneralSecurityException {

        //创建一个配置文件保存并读取信息
        Properties properties = new Properties();

        //设置qq邮件服务器
        properties.setProperty("mail.host","smtp.qq.com");
        //设置发送的协议
        properties.setProperty("mail.transport.protocol","smtp");
        //设置用户是否需要验证
        properties.setProperty("mail.smtp.auth", "true");


        //=================================只有QQ存在的一个特性,需要建立一个安全的链接
        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //=================================准备工作完毕

        //1.创建一个session会话对象;
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("24736743@qq.com", "授权码");
            }
        });

        //可以通过session开启Dubug模式,查看所有的过程
        session.setDebug(true);


        //2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;
        Transport tp = session.getTransport();

        //3.连接服务器,需要抛出异常;
        tp.connect("smtp.qq.com","24736743@qq.com","授权码");

        //4.连接上之后我们需要发送邮件;
        MimeMessage mimeMessage = imageMail(session);

        //5.发送邮件
        tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());

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

    }


    public static MimeMessage imageMail(Session session) throws MessagingException {

        //消息的固定信息
        MimeMessage mimeMessage = new MimeMessage(session);

        //邮件发送人
        mimeMessage.setFrom(new InternetAddress("24736743@qq.com"));
        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;
        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("24736743@qq.com"));
        mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题


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

        //图片
        MimeBodyPart body1 = new MimeBodyPart();
        body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));
        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("src/resources/log4j.properties")));
        body3.setFileName("log4j.properties"); //附件设置名字

        MimeBodyPart body4 = new MimeBodyPart();
        body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));
        body4.setFileName(""); //附件设置名字

        //拼装邮件正文内容
        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消息中
        mimeMessage.setContent(allFile);
        mimeMessage.saveChanges();//保存修改


        return mimeMessage;

    }

}

JavaWeb发送邮件

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

代码实现:

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

1563465857863.png

  1. 编写对应的用户实体类

    package com.kuang.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 + '\'' +
                    '}';
        }
    }
  2. 前端注册页面

    <%@ 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>
  3. 邮件发送工具类

    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;
    
    public class Sendmail extends Thread {
    
        //用于给用户发送邮件的邮箱
        private String from = "24736743@qq.com";
        //邮箱的用户名
        private String username = "24736743@qq.com";
        //邮箱的密码
        private String password = "授权码";
        //发送邮件的服务器地址
        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("24736743@qq.com", "授权码");
                    }
                });
    
                //开启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);
            }
        }
    }
  4. 编写对应的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 request, HttpServletResponse response) throws ServletException, IOException {
            try {
                //接收用户请求,封装成对象
                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);
                //启动线程,线程启动之后就会执行run方法来发送邮件
                send.start();
    
                //注册用户
                request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");
                request.getRequestDispatcher("info.jsp").forward(request, response);
            } catch (Exception e) {
                e.printStackTrace();
                request.setAttribute("message", "注册失败!!");
                request.getRequestDispatcher("info.jsp").forward(request, response);
            }
        }
    
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
  5. 配置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>register</servlet-name>
            <servlet-class>com.kuang.servlet.RegisterServlet</servlet-class>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>register</servlet-name>
            <url-pattern>/RegisterServlet.do</url-pattern>
        </servlet-mapping>
    </web-app>
  6. 发送成功或失败的反馈页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>提示信息</title>
    </head>
    <body>
        ${message}
    </body>
    </html>
    

运行Tomcat测试!

邮件发送成功,OK!


--> 进入小狂神的腾讯课堂
--> 进入小狂神的哔哩哔哩
--> 领取阿里云2000元代金券
Last modification:July 19th, 2019 at 02:37 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment