需求:

每月1日发送邮件,使用JavaEmail实现

常见的邮件协议包括:

SMTP: 简单邮件传输协议,用于发送电子邮件的传输协议。(默认端口25),邮件客户端和SMTP邮件服务器之间通信规则。
POP/ POP3: 用于接收电子邮件的标准协议。(默认端口110),把存储在POP协议邮件服务器的邮件下载到用户计算机中,但不能对邮件进行在线操作。
IMAP: 互联网消息访问协议,是POP3的替代协议。(默认端口143),可以通过客户端直接对服务器上的邮件在线操作。
这三种协议都有对应的SSL加密传输的协议,分别是SMTPS、POP3S和IMAPS。

JavaMail的关键对象:

1. Properties

属性

类型

说明

mail.smtp.host


string

smtp服务器地址

mail.smtp.port

int

smtp服务器端口,默认25

mail.smtp.auth

boolean

smtp服务器是否需要用户认证,默认false

mail.smtp.user

string

smtp默认的登录用户名

mail.smtp.from

string

默认的邮件发送源地址

mail.smtp.socketFactory.class

String

必须实现javax.net.SocketFactory接口

mail.smtp.socketFactory.port

int

指定socket工厂类所用的端口号

mail.smtp.socketFactory.fallback

boolean

设定为true时,当使用指定的socket类创建socket失败后,将使用java.net.Socket创建socket,默认为true

mail.smtp.timeout

int

连接超时时间,单位为ms,默认为永不超时

2.Session: 会话对象, 是一堆配置信息的集合。
3.Transport和Store: 传输和存储。

pom依赖:

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.0</version>
</dependency>

结果本地测试启动时报了如下错误:
java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger
原因:
MailLogger --是JavaMail的一部分,包含在Java EE环境里面,但是不包含在Java SE环境里面,出现这个错误很大的原因是在SE环境里面测试邮件的发送;
javax.mail-api只适合编译,但是如果你实在要运行代码,必须完全实现JavaMail
修改pom依赖:

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>

相关链接:
线上生产环境的pom依赖:

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.5</version >
</dependency>
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.5.4</version>
</dependency>

发送邮件:

一、封装工具类

在发送邮件之前,每次都会创建Session连接,这里可以定义一个JavaMailUtils工具类,每次创建连接时,只需要调用createSession()方法,不必频繁写重复代码了。(看业务需求 封不封装都可)

@Component
public class JavaEmailUtils {

    /**
     * 创建Session连接
     * @return
     */
    public static Session createSession() {
        //服务器地址
        String smtp ="smtp.163.com";
        //发件人的邮箱
        String userName = "xxx.@163.com";
        //发件人密码 | 授权码
        String password = "xxxxxxx";
        //SSL链接端口
        String emailPort = "465";

        Properties props = new Properties();
        // 是否打开验证:只能设置true,必须打开
        props.setProperty("mail.smtp.auth", "true");
        //stmp协议
        props.setProperty("mail.transport.protocol", "smtp");
        // 使用JSSE的SSL
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        // 只处理SSL的连接,对于非SSL的连接不做处理
        props.put("mail.smtp.socketFactory.fallback", "false");
        // smtp服务器地址
        props.put("mail.smtp.host", smtp);
        props.put("mail.smtp.port",emailPort);
        props.put("mail.smtp.socketFactory.port", emailPort);
        props.put("mail.smtp.ssl.enable", true);
        props.put("mail.smtp.starttls.enable","true");


        Session session = Session.getInstance(props, new Authenticator() {

            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // TODO Auto-generated method stub
                return new PasswordAuthentication(userName, password);
            }

        });

        session.setDebug(true);

        return session;
    }

}

封装工具类参考链接:
网易邮箱获取授权码参考链接:

二、创建邮件(不使用封装工具类进行邮件的发送)
public ResultVO sendFjEmail(GsbSendEmail gsbSendEmail, String emailAccounts, String emailAuthorizationCode, String emailPort, String title, String content) {
        try {
            // 1. 创建一封邮件
            Properties props = new Properties();
            // 是否打开验证:只能设置true,必须打开
            props.setProperty("mail.smtp.auth", "true");
            //stmp协议
            props.setProperty("mail.transport.protocol", "smtp");
            //smtp协议
            String smtp = "smtp.163.com";

            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");// 使用JSSE的SSL
            props.put("mail.smtp.socketFactory.fallback", "false");  // 只处理SSL的连接,对于非SSL的连接不做处理
            // 设置主机地址 smtp.qq.com smtp.126.com smtp.163.com
            props.put("mail.smtp.port", emailPort);
            props.put("mail.smtp.socketFactory.port", emailPort);
            props.put("mail.smtp.ssl.enable", true);
            props.put("mail.smtp.host", smtp);// smtp服务器地址

            // 用于连接邮件服务器的参数配置(发送邮件时才需要用到)
            // 根据参数配置,创建会话对象(为了发送邮件准备的)
            Session session = Session.getInstance(props);
            session.setDebug(true);

            //创建邮件对象
            Message msg = new MimeMessage(session);
            //Subject: 邮件主题
            msg.setSubject(title);
            //发件人邮箱(我的163邮箱)
            msg.setFrom(new InternetAddress(emailAccounts));
            //收件人邮箱(我的网易云邮箱) 可增加收件人邮箱
            msg.setRecipient(Message.RecipientType.TO, new InternetAddress(“邮箱”));

            //创建附件“节点”
            MimeBodyPart attachment = new MimeBodyPart();
            // 读取本地文件
            // 模板地址
            String filePath = "src" + File.separator + "main" + File.separator + "resources" + File.separator + "template" + File.separator + "xxx.docx";
            DataHandler dh2 = new DataHandler(new FileDataSource(filePath));
            // 将附件数据添加到“节点”
            attachment.setDataHandler(dh2);
            // 设置附件的文件名(需要编码)
            attachment.setFileName(MimeUtility.encodeText(dh2.getName()));

            //正文 将文本封装成一个节点
            MimeBodyPart body = new MimeBodyPart();
            body.setContent(content, "text/html;charset=utf-8");

            //设置文本和附件的关系
            Multipart msgPart = new MimeMultipart();
            msgPart.addBodyPart(body);
//            msgPart.addBodyPart(attachment);

            //Content: 邮件正文(可以使用html标签)设置整个邮件的关系(将最终的混合“节点”作为邮件的内容添加到邮件对象)
            msg.setContent(msgPart);

            //保存前面的设置(邮件生成的最后一步)
            msg.saveChanges();

            Transport transport = session.getTransport();
            transport.connect(emailAccounts, emailAuthorizationCode);//发件人邮箱,授权码(可以在邮箱设置中获取到授权码的信息)
            transport.sendMessage(msg, msg.getAllRecipients());
            transport.close();

            //todo 邮件发送成功,记录日志信息
            setLogger(gsbSendEmail,"1","邮件发送成功!");
            return new ResultVO().addData("data", "OK");
        } catch (Exception e) {
            // TODO: 邮件发送失败,记录日志信息
            setLogger(gsbSendEmail,"0",e.toString());
            return new ResultVO("发送邮箱失败!请联系管理员进行排查");
        }
    }

邮箱验证规则:

需要满足的验证逻辑:

  1. @之前必须有内容且只能是字母(大小写)、数字、下划线(_)、减号(-)、点(.)
  2. @和最后一个点(.)之间必须有内容且只能是字母(大小写)、数字、点(.)、减号(-),且两个点不能挨着
  3. 最后一个点(.)之后必须有内容且内容只能是字母(大小写)、数字且长度为大于等于2个字节,小于等于6个字节

邮箱验证的正则表达式:

^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$