Java邮件发送

  • 介绍

    1. 传输协议

      • SMTP协议(Simple Mail Transfer Protocol)
        • 属于TCP/IP协议族
        • 控制信件的中转方式,帮助找到下一个目的地
        • SMTP邮件服务器
        • 发送协议
      • POP3协议(Post Office Protocol - version 3)
        • 属于TCP/IP协议族
        • 远程管理自己在服务器上的邮件
        • POP服务器
        • 接收协议(登录管理协议)
    2. 邮件服务器

      要在网络上实现邮件功能,要使用专门的邮件服务器。

      • SMTP服务器 :一般是smtp.xxx.com。如163邮箱smtp.163.com,QQ邮箱smtp.qq.com。
      • POP服务器:一般是pop.xxx.com。如163邮箱pop.163.com,QQ邮箱pop.qq.com。

    邮件发送实现

    • 需要JavaMail API 和 Java Activation Framework

    • 对应两个jar包:mail.jar activation.jar

    • 要发送邮件 需要获得协议和支持 开启服务POP3/SMTP服务

    • 普通邮件:不包含附件和图片,纯文本邮件

    • 复杂邮件:非纯文本邮件

    • pom.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     <!-- https://mvnrepository.com/artifact/javax.mail/mail -->
    <!-- <dependency>-->
    <!-- <groupId>javax.mail</groupId>-->
    <!-- <artifactId>mail</artifactId>-->
    <!-- <version>1.4.7</version>-->
    <!-- </dependency>-->
    <!-- 上面那个包会出错 大概是ssl协议的问题 换成下下面这个包就可以了
    或者 打开java安装路径->jre/lib/security
    然后编辑java.security文件,把SSLv3跟TSL开头的都删掉,然后重启一下服务
    -->
    <!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail -->
    <dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.activation/activation -->
    <dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
    </dependency>
    • 核心类介绍

      • Session对象

        定义整个程序所需环境信息,比如主机名、端口号、采用的邮件发送协议和接收协议

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        // 获取实例对象
        Session getDefaultInstance(Properties props)

        Session getDefaultInstance(Properties props, Authenticator authenticator)

        // 开启Debug模式
        void setDebug(boolean debug)

        // 获取Transport对象
        Transport getTransport()
      • Transport对象

        用来发送邮件

        1
        2
        3
        4
        5
        6
        7
        8
        // 连接到邮件服务器
        void connect(String host, String user, String password)

        // 发送邮件
        void sendMessage(Message var1, Address[] var2)

        // 关闭连接
        void close()
      • Message对象

        表示一封电子邮件,被Transport对象引用

      • Store对象

        用来接收邮件,被Session对象引用,同时创建Message对象

      • MailSSLSocketFactory

        设置SSL加密

        1
        2
        3
        4
        5
        // SSL加密:QQ邮箱需要设置,通过以下4行代码
        MailSSLSocketFactory mssf = new MailSSLSocketFactory();
        mssf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", mssf);
      • MimePart接口实现类:MimeMessage类

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        // 设置发件人
        void setFrom(Address address)

        // 设置收件人
        void setRecipient(Message.RecipientType type, Address address)

        // 设置主题
        void setSubject(String subject)

        // 设置内容
        void setContent(Object o, String type)

        // 保存修改:添加图片、附件时需要
        void saveChanges()
      • MimePart接口实现类:MimeBodyPart类

        复杂邮件所需

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        // 文本:设置内容
        void setContent(Object o, String type)

        // 图片、附件:设置数据处理
        void setDataHandler(DataHandler dh)

        // 图片:设置CID,在文本中通过src引用
        void setContentID(String cid)

        // 附件:设置附件名
        void setFileName(String filename)
      • MimePart接口实现类:MimeMultiPart类

        组合多个代表MIME消息的MimeBodyPart对象。

        1
        2
        3
        4
        5
        // 添加MIME消息
        void addBodyPart(BodyPart part)

        // 描述数据关系:alternative/related/mixed
        void setSubType(String subtype)
    • 步骤

      1. 创建Session对象
      2. 获得Transport对象
      3. 创建邮件(普通邮件和复杂邮件有区别
      4. 发送Message,关闭连接

    Java实现

    • 发送简单邮件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    package xyz.yiochin;

    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 MailSend01 {
    public static void main(String[] args) throws Exception {
    Properties prop = new Properties();

    //set qq mail server
    prop.setProperty("mail.host","smtp.qq.com");
    //set send protocol
    prop.setProperty("mail.transport.protocol","smtp");
    //validate name and password
    prop.setProperty("mail.smtp.auth","true");

    //qq need ssl
    MailSSLSocketFactory sf = new MailSSLSocketFactory();
    sf.setTrustAllHosts(true);
    prop.put("mail.smtp.ssl.enable","true");
    prop.put("mail.smtp.ssl.socketFactory",sf);

    // use Java send a mail needs 5 steps
    // 1、创建定义整个应用程序所需要的环境信息的Session对象
    // qq needs others dont
    Session session = Session.getDefaultInstance(prop, new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
    //username validation
    return new PasswordAuthentication("****@qq.com","****");
    }
    });
    // 开始Session的debug模式可以看到程序发送email的运行状态
    session.setDebug(true);

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

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


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

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

    // 指明收件人
    message.setRecipient(Message.RecipientType.TO, new InternetAddress("****@163.com"));

    // 邮件的标题
    message.setSubject("This is a simple email sent by Java.");

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

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

    ts.close();
    }
    }
    • 发送复杂邮件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    package xyz.yiochin;

    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 MailSend02 {
    public static void main(String[] args) throws Exception {
    MailSend02 mailSend02 = new MailSend02();
    mailSend02.sendMail();
    }

    void sendMail() throws MessagingException, GeneralSecurityException {
    // set properties
    final String host = "smtp.qq.com";
    final String authCode = "wlnjptkrsfuebhjc";
    final String addresser = "397040338@qq.com";
    final String addressee = "18326497503@163.com";

    //Configuration parameters
    Properties prop = new Properties();
    prop.setProperty("mail.host",host);
    prop.setProperty("mail.transport.protocol","smtp");
    prop.setProperty("mail.smtp.auth","true");

    // SSL
    MailSSLSocketFactory mailSSLSocketFactory = new MailSSLSocketFactory();
    mailSSLSocketFactory.setTrustAllHosts(true);
    prop.put("mail.smtp.ssl.enable","true");
    prop.put("mail.smtp.ssl.socketFactory",mailSSLSocketFactory);

    // 1、创建定义整个应用程序所需要的环境信息的Session对象
    Session session = Session.getDefaultInstance(prop, new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(addresser, authCode);
    }
    });

    //开启debug
    session.setDebug(true);

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

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

    // 4、创建邮件
    MimeMessage message = makeMixedMessage(session, addresser, addressee);

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

    ts.close();
    }

    //创建复杂邮件
    private MimeMessage makeMixedMessage(Session session,String addresser,String addressee) throws MessagingException {
    MimeMessage message = new MimeMessage(session);

    //sender
    message.setFrom(new InternetAddress(addresser));
    //receiver
    message.setRecipient(Message.RecipientType.TO,new InternetAddress(addressee));
    //subject
    message.setSubject("This is a mixed email");

    // text
    MimeBodyPart textPart = new MimeBodyPart();
    textPart.setContent("There is a picture to you: <img src='cid:img'>This","text/html;charset=utf-8");

    // picture
    MimeBodyPart imgPart = new MimeBodyPart();
    DataHandler dataHandler = new DataHandler(new FileDataSource("src\\main\\resources\\img\\img.png"));
    imgPart.setDataHandler(dataHandler);
    imgPart.setContentID("img");

    // attachment
    MimeBodyPart attachPart = new MimeBodyPart();
    DataHandler dataHandler1 = new DataHandler(new FileDataSource("src\\main\\resources\\md\\test.md"));
    attachPart.setDataHandler(dataHandler1);
    attachPart.setFileName("fileUpload.md");//have a suffix name better

    //describe data relationship:alternative/related/mixed
    MimeMultipart mm = new MimeMultipart();
    mm.addBodyPart(textPart);
    mm.addBodyPart(attachPart);
    mm.addBodyPart(imgPart);
    mm.setSubType("mixed");

    // set to MimeMessage message and save modification
    message.setContent(mm);
    message.saveChanges();

    return message;
    }
    }

    JavaWeb实现

    • 网站的注册功能通常有邮件的激活步骤,用到了邮件的发送
    • javax.mail、activation、servlet-api、jsp-api、jstl、lombok、junit
    • 目录结构:

      image-202203251626269654

      image-20220325162715911

    • 前端

      • register.jsp

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        <%@ page contentType="text/html;charset=UTF-8" language="java" %>
        <html>
        <body>
        <form action="register.do" method="post">
        <label>
        账号:<input type="text" name="username">
        <br>
        </label>
        <label>
        密码:<input type="password" name="password">
        <br>
        </label>
        <label>
        邮箱:<input type="text" name="mail">
        <br>
        </label>
        <input type="submit">|<input type="reset">
        </form>
        </body>
        </html>

      • seccess.jsp

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        <%--
        Created by IntelliJ IDEA.
        User: oho
        Date: 2022/3/25
        Time: 15:24
        To change this template use File | Settings | File Templates.
        --%>
        <%@ page contentType="text/html;charset=UTF-8" language="java" %>
        <html>
        <head>
        <title>成功</title>
        </head>
        <body>
        <h1>${msg}</h1>
        </body>
        </html>

    • Servlet

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26

      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 mailAddress = req.getParameter("mail");

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

      // 启动线程来发送邮件,优化注册等待时间
      MailThread mailThread = new MailThread(user);
      mailThread.start();//run只是调用方法 start才是开始多线程

      req.setAttribute("msg","注册成功,稍后会收到一封邮件");

      req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req,resp);
      }

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

      }

    • web.xml

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      <?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>xyz.yiochin.servlet.RegisterServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>RegisterServlet</servlet-name>
      <url-pattern>/register.do</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
      <welcome-file>/register.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
    • 实体类:User

      1
      2
      3
      4
      5
      6
      7
      8
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
      private String username;
      private String password;
      private String mailAddress;
      }
    • 工具类:MailThread

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64

      public class MailThread extends Thread{
      final String host = "smtp.qq.com";
      final String authCode = "wlnjptkrsfuebhjc";
      final String addresser = "397040338@qq.com";
      final private User user;

      public MailThread(User user) {
      this.user = user;
      }

      @Override
      public void run() {
      try {
      //配置参数
      Properties prop = new Properties();
      prop.setProperty("mail.host",host);
      prop.setProperty("mail.transport.protocol","smtp");
      prop.setProperty("mail.stmp.auth","true");

      //SSL
      MailSSLSocketFactory mailSSLSocketFactory = new MailSSLSocketFactory();
      mailSSLSocketFactory.setTrustAllHosts(true);
      prop.put("mail.smtp.ssl.enable","true");
      prop.put("mail.stmp.ssl.socketFactory",mailSSLSocketFactory);

      // 1、创建Session
      Session session = Session.getDefaultInstance(prop, new Authenticator() {
      @Override
      protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(addresser, authCode);
      }
      });

      session.setDebug(true);
      // 2、session 得到 transport
      Transport ts = session.getTransport();

      // 3、使用用户名和授权码链接服务器
      ts.connect(host,addresser,authCode);
      // 4、创建邮件
      MimeMessage message = new MimeMessage(session);
      message.setFrom(addresser);
      message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getMailAddress()));
      message.setSubject("用户注册邮件");

      String info = "注册成功,您的用户名:"+user.getUsername()+",密码"+user.getPassword();
      //test
      System.out.println("=======================================");
      System.out.println(user.getUsername() +":"+user.getPassword());
      System.out.println("=======================================");


      message.setContent(info,"text/html;charset=utf-8");

      // 5、发送邮件,关闭连接
      ts.sendMessage(message,new InternetAddress[]{new InternetAddress(user.getMailAddress())});
      ts.close();
      } catch (GeneralSecurityException | MessagingException e) {
      e.printStackTrace();
      }

      }
      }

    作者: Meow Mii

    本文链接: https://blog.yiochin.top/p/99746608.html

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议,转载请注明出处!


    📝 Comment