大聪明教你学Java | 实现邮件发送(以163邮箱向QQ邮箱发送邮件为例)

6,769 阅读5分钟

前言

电子邮件的应用非常广泛,常见的如在某网站注册了一个账户,自动发送一封激活邮件;通过邮件找回密码;发送活动信息等等。很显然,这些过程不能通过人工来操作(打开浏览器、打开邮箱、创建邮件、发送邮件),就只能通过勤劳的程序猿去实现发送邮件的功能了~

或许有些小伙伴还不知道怎么实现发送邮件的功能,下面就说说怎么用代码实现邮件的发送。

邮件发送

发送邮件需要遵从特定的协议,常用的电子邮件协议包括 SMTP,POP3,IMAP,其中邮件的创建和发送只需要用到SMTP协议(Simple Mail Transfer Protocol,简单邮件传输协议),下面就以163邮箱为例,具体的说一说。

开启SMTP服务

需要发送邮件的话,需要有个前期准备工作,就是开启邮箱的SMTP服务。

首先登录163邮箱,点击上方的设置按钮,再点击“POP3/SMTP/IMAP”,进入到设置页面开启SMTP服务 在这里插入图片描述

开启SMTP服务后,会生成授权码,授权码千万别忘了哦,后面会用到~ 在这里插入图片描述 在这里插入图片描述

翠花!上代码

邮箱的SMTP服务已经开启了,接下来就是代码了。

首先引入Maven依赖

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

在发送邮件之前,我们先创建一封简单的邮件文件,看看里面是什么样子的🧐

import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Properties;

/**
 * 创建简单邮件
 * @description: MailTest
 * @author: 庄霸.liziye
 * @create: 2021-11-23 14:44
 **/
public class CreatMail {
    public static void main(String[] args) throws Exception {
        //创建邮件
        Properties props = new Properties();                // 用于连接邮件服务器的参数配置
        Session session= Session.getInstance(props);        // 根据参数配置,创建会话对象
        MimeMessage message = new MimeMessage(session);     // 创建邮件对象

        /*
         * 也可以读取本地的eml 创建MimeMessage对象
         * new MimeMessage(session, new FileInputStream("D://email//test.eml"));
         */

        // From: 发件人
        // 其中 InternetAddress 的三个参数分别为: 发件人邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码
        message.setFrom(new InternetAddress("XXXXXX", "不肯过江东", "UTF-8"));

        // To: 收件人
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("XXXXXX", "USER_CC", "UTF-8"));
        // To: 增加收件人(可选)
        //message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress("xxxx@xxxx.com", "USER_DD", "UTF-8"));
        // Cc: 抄送(可选)
        //message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress("xxxx@xxxx.com", "USER_EE", "UTF-8"));
        // Bcc: 密送(可选)
        //message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress("xxxx@xxxx.com", "USER_FF", "UTF-8"));

        // Subject: 邮件主题
        message.setSubject("测试邮件发送", "UTF-8");

        // Content: 邮件正文(可以使用html标签)
        message.setContent("我在人民广场吃着炸鸡", "text/html;charset=UTF-8");

        // 设置显示的发件时间
        message.setSentDate(new Date());

        // 保存前面的设置
        message.saveChanges();

        // 将该邮件保存到本地
        OutputStream out = new FileOutputStream("D:\\email\\test.eml");
        message.writeTo(out);
        out.flush();
        out.close();
    }
}

我们可以看一下创建好的test.eml文件,里面的内容就是SMTP协议格式的文本(使用了base64进行了编码),其中 From: USER_AA 后面的内容是发件人邮箱,To: USER_CC 后面的内容是收件人邮箱。 在这里插入图片描述 接下来我们进入正题,看看怎么用代码发送邮件呢(●'◡'●)

import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

/**
 * @program: 发送邮件
 * @description: SendMail
 * @author: 庄霸.liziye
 * @create: 2021-11-23 14:57
 **/
public class SendMail {

    public static String myEmailAccount = "xxxxxx@163.com";    //发件人邮箱
    public static String myEmailPassword = "XXXXXX";      //SMTP服务授权码(刚刚上面提到了呦~ 千万别忘了哦~ )

    // 发件人邮箱的 SMTP 服务器地址,
    public static String myEmailSMTPHost = "smtp.163.com";

    // 收件人邮箱
    public static String receiveMailAccount = "xxxxx@qq.com";


    public static void main(String[] args) throws Exception {
        // 参数配置
        Properties props = new Properties();                    // 参数配置
        props.setProperty("mail.transport.protocol", "smtp");   // 使用的协议(JavaMail规范要求)
        props.setProperty("mail.smtp.host", myEmailSMTPHost);   // 发件人的邮箱的 SMTP 服务器地址
        props.setProperty("mail.smtp.auth", "true");            // 需要请求认证

        // 根据配置创建会话对象, 用于和邮件服务器交互
        Session session = Session.getInstance(props);
        // 设置为debug模式, 可以查看详细的发送 log
        session.setDebug(true);

        // 创建一封邮件
        MimeMessage message = createMimeMessage(session, myEmailAccount, receiveMailAccount);

        // 根据 Session 获取邮件传输对象
        Transport transport = session.getTransport();

        // 发件人邮箱以及开启SMTP服务后的授权码
        transport.connect(myEmailAccount, myEmailPassword);

        // 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的收件人, 抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());

        // 关闭连接
        transport.close();
    }

    /**
     * 创建简单邮件
     *
     * @param session     和服务器交互的会话
     * @param sendMailAddress    发件人邮箱地址
     * @param receiveMailAddress 收件人邮箱地址
     * @return
     * @throws Exception
     */
    public static MimeMessage createMimeMessage(Session session, String sendMailAddress, String receiveMailAddress) throws Exception {
        // 创建一封邮件
        MimeMessage message = new MimeMessage(session);

        // From: 发件人
        message.setFrom(new InternetAddress(sendMailAddress, "不肯过江东", "UTF-8"));

        // To: 收件人(可以增加多个收件人、抄送、密送)
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMailAddress, "测试人", "UTF-8"));

        // Subject: 邮件主题
        message.setSubject("吃炸鸡", "UTF-8");

        // Content: 邮件正文(可以使用html标签)
        message.setContent("我在人民广场吃着炸鸡", "text/html;charset=UTF-8");
        // 设置发件时间
        message.setSentDate(new Date());

        // 保存设置
        message.saveChanges();

        return message;
    }
}

这里需要注意的是:

某些邮箱服务器要求SMTP连接需要使用SSL安全认证(如QQ邮箱),那么就需要在参数配置中增加几个参数,如👇所示(关于smtpPort,不同的邮箱端口是不一样的,具体端口号就需要自行查询了;如果没有用到SSL安全认证,那么连接端口是不需要指定的,一般默认都是25)

final String smtpPort = "xxx";
props.setProperty("mail.smtp.port", smtpPort);
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.port", smtpPort);

==P.S. myEmailPassword 指的是SMTP服务的授权码,千万别写成邮箱的密码了哦~==

执行一下上面的代码,看看是什么效果呢~ 在这里插入图片描述 在这里插入图片描述 执行代码后控制台会输出日志,其中有一句DEBUG SMTP: connected to host "smtp.163.com", port: 25 ,这就证明了上面所说的那句话:如果没有用到SSL安全认证,那么连接端口是不需要指定的,一般默认都是25 O(∩_∩)O

小结

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西