Java-Web 邮件发送原理及实现示例

邮件概述

  1. 电子邮件:

在网络上传送邮件,需要有专门的邮件服务器.

邮件服务器相当于生活中的邮局,主要负责接收用户投递过来的邮件,再把邮件投递向邮件接收者的电子邮箱中。

  1. 邮件相关常用协议及相应的邮件服务器:
  • Pop3(Post of Office)协议: 对应的Pop3邮件服务器,主要负责邮件的接收即邮件在用户客户端到POP3服务器间传递。

  • SMTP(Simple Mail transfer Protocol):对应的SMTP服务器,主要负责邮件的发送,即邮件在各个SMTP邮件服务器之间传递。SMTP服务器的地址一般是:smtp.xx.com,如网易邮箱是:smtp.163.com,QQ邮箱是:smtp.qq.com.

  • 工作架构示意图:

在这里插入图片描述

其它相关的邮件协议:

  • IMAP(Interter Mail Access Protocol):其作用跟POP3协议类似,其与Pop3协议的差别在于: pop3协议允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、标记已读等),不会反馈到服务器上,比如通过客户端收取了邮箱中的3封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的 。而IMAP提供webmail 与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,对邮件进行的操作,服务器上的邮件也会做相应的动作。同时,IMAP像POP3那样提供了方便的邮件下载服务,让用户能进行离线阅读。IMAP提供的摘要浏览功能可以让你在阅读完所有的邮件到达时间、主题、发件人、大小等信息后才作出是否下载的决定
  • MIME((Multipurpose Internet Mail Extensions):多用途邮件扩展类型,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。协议详情可参考链接->>: MIME Type
  1. 在JAVA使用电子邮箱需要在邮箱中开通相关服务设置(以QQ邮箱为例:)

进入邮箱首页,进入设置:

在这里插入图片描述

​ 点击账户:

在这里插入图片描述

​ 开通相关服务 (获取相应的服务授权码信息):

在这里插入图片描述

在这里插入图片描述

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

准备工作

使用Java发送邮件十分简单,但首先应该准备JavaMail API和Java Activation Framework.

即准备两个jar包(附上maven仓库下载链接):

JavaMail是为方便java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持常用的邮件协议,如前面所讲的SMTP,POP3,IMAP以及MIME等。故在使用JavaMail API编写邮件时,只要调用JavaMail开发包中相应的API类就可以了。


其主要有四个核心类及对象:即 Session,Message,Transport,Store.

发送步骤

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

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

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

过程图示:

在这里插入图片描述

纯文本邮件示例:

导入相关jar包后,编写的一个纯文本邮件程序示例如下:

代码实现及注释:

package com.carson;

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 MailDemo1 {
    public static void main(String[] args) throws Exception {
        //创建一个Properties的持久的属性集.属性列表中每个键及其对应值都是一个字符串(Properties使用键值对的形式生成属性集)
        Properties prop = new Properties();//注:prop的get/put(接收Object对象),getProperty/setProperty方法(只能接收String)要对应使用,否则结果可能异常
        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() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人的邮件用户名,授权码
                return new PasswordAuthentication("carson.mail@qq.com","xbcvdjxuieiohgfb");
            }
        });
        //开启Session的debug模式,这样可以看到程序发送Email时的运行状态和输出信息
        session.setDebug(true);

        //2: 通过Session得到transport邮件连接发送对象
        Transport transport = session.getTransport();

        //3: 使用邮箱的用户名及授权码 连接上邮件服务器(需要抛出异常)
        transport.connect("smtp.qq.com","carson.mail@qq.com","xbcvdjxuieiohgfb");

        //4: 创建邮件(注意需要传递上面的session对象)
        MimeMessage message = new MimeMessage(session);
           //指明邮件的发件人
        message.setFrom(new InternetAddress("carson.mail@qq.com"));
           //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("2429070946@qq.com"));
           //邮件的标题
        message.setSubject("Carson的JavaMail测试邮件!");
           //邮件的文本内容(注意设置文本类型)
        message.setContent("<h1 style='color:blue'> 你好阿!</h1>","text/html;charset=UTF-8");

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

        // 关闭网络资源连接
        transport.close();
        System.out.println("邮件已发送!");
    }
}

效果:

在这里插入图片描述

文本带图片的邮件示例:

需先认识两个类及名词;

MimeBodyPart类

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

MimeMultipart类

javax.mail.internet.MimeMultipart类是抽象类Multipart的实现子类,它用来组合多个MIME消息。

一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。

在这里插入图片描述

如图,其中

  • 标明alternative类型的内容只能是纯文本正文

  • 标明related类型的内容是纯文本内容和内嵌的图片资源等,是向下兼容的。

  • 标明mixed类型的内容是纯文本内容和图片资源和文件附件等资源,其也是向下兼容的。

    文本带图片的邮件示例代码及注释如下:

package com.carson;

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 MailDemo2 {
    public static void main(String[] args) throws Exception {
        //创建一个Properties的持久的属性集.属性列表中每个键及其对应值都是一个字符串(Properties使用键值对的形式生成属性集)
        Properties prop = new Properties();//注:prop的get/put(接收Object对象),getProperty/setProperty方法(只能接收String)要对应使用,否则结果可能异常
        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() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人的邮件用户名,授权码
                return new PasswordAuthentication("carson.mail@qq.com","xbcvdjxuieiohgfb");
            }
        });
        //开启Session的debug模式,这样可以看到程序发送Email时的运行状态和输出信息
        session.setDebug(true);

        //2: 通过Session得到transport邮件连接发送对象
        Transport transport = session.getTransport();

        //3: 使用邮箱的用户名及授权码 连接上邮件服务器(需要抛出异常)
        transport.connect("smtp.qq.com","carson.mail@qq.com","xbcvdjxuieiohgfb");

        //4: 创建邮件(注意需要传递上面的session对象)
        MimeMessage message = new MimeMessage(session);
           //指明邮件的发件人
        message.setFrom(new InternetAddress("carson.mail@qq.com"));
           //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("2429070946@qq.com"));
           //邮件的标题
        message.setSubject("Carson的JavaMail测试邮件!");
           //准备图片数据
        MimeBodyPart image = new MimeBodyPart();
           //图片需经过数据处理  DataHandler即数据处理器
        DataHandler dh = new DataHandler(new FileDataSource("D:\\360downloads\\wpcache\\carson.jpg"));
        image.setDataHandler(dh);//在我们的body中放入这个处理的图片数据
        image.setContentID("1.jpg");//给图片设置一个ID,在下面可以使用
           //准备正文数据
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这是一封带图片<img src='cid:1.jpg'>的邮件","text/html;charset=UTF-8");
           //描述整合数据关系
        MimeMultipart mm = new MimeMultipart();
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("related");//默认设置为mixed表示邮件带图片带正文等情况(并且向下兼容多种情况),这里related表示邮件带图片
           //设置到消息中,保存修改
        message.setContent(mm);//把最后编辑好的邮件放到消息当中
        message.saveChanges();//保存修改

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

        // 关闭网络资源连接
        transport.close();
        System.out.println("邮件已发送!");
    }
}

效果:

在这里插入图片描述

复杂邮件(带图片带附件)示例:

复杂邮件示例代码及注释如下:

package com.carson;

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 MailDemo3 {
    public static void main(String[] args) throws Exception {
        //创建一个Properties的持久的属性集.属性列表中每个键及其对应值都是一个字符串(Properties使用键值对的形式生成属性集)
        Properties prop = new Properties();//注:prop的get/put(接收Object对象),getProperty/setProperty方法(只能接收String)要对应使用,否则结果可能异常
        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() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                //发件人的邮件用户名,授权码
                return new PasswordAuthentication("carson.mail@qq.com","xbcvdjxuieiohgfb");
            }
        });
        //开启Session的debug模式,这样可以看到程序发送Email时的运行状态和输出信息
        session.setDebug(true);

        //2: 通过Session得到transport邮件连接发送对象
        Transport transport = session.getTransport();

        //3: 使用邮箱的用户名及授权码 连接上邮件服务器(需要抛出异常)
        transport.connect("smtp.qq.com","carson.mail@qq.com","xbcvdjxuieiohgfb");

        //4: 创建邮件(注意需要传递上面的session对象)
        MimeMessage message = new MimeMessage(session);
           //指明邮件的发件人
        message.setFrom(new InternetAddress("carson.mail@qq.com"));
           //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("2429070946@qq.com"));
           //邮件的标题
        message.setSubject("Carson的JavaMail测试邮件!");
           //准备图片数据
        MimeBodyPart image = new MimeBodyPart();
           //图片需经过数据处理  DataHandler即数据处理器
        DataHandler dh = new DataHandler(new FileDataSource("D:\\360downloads\\wpcache\\carson.jpg"));
        image.setDataHandler(dh);//在我们的body中放入这个处理的图片数据
        image.setContentID("1.jpg");//给图片设置一个ID,在下面可以使用
           //准备正文数据
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这是一封带图片<img src='cid:1.jpg'>以及附件的邮件","text/html;charset=UTF-8");
           //附件
        MimeBodyPart attachment = new MimeBodyPart();
           //附件页需经过数据处理
        attachment.setDataHandler(new DataHandler(new FileDataSource("D:\\360downloads\\1.txt")));
        attachment.setFileName("1.txt");//附件设置名字

           //拼装邮件正文内容
        MimeMultipart multipart1 = new MimeMultipart();
        multipart1.addBodyPart(text);
        multipart1.addBodyPart(image);
        multipart1.setSubType("related");//默认设置为mixed表示邮件带图片带正文等情况(并且向下兼容多种情况),这里related表示邮件带图片
           //将拼装好的正文内容设置为主体
        MimeBodyPart contentText = new MimeBodyPart();
        contentText.setContent(multipart1);

           //拼接附件
        MimeMultipart allFile = new MimeMultipart();
        allFile.addBodyPart(attachment);
        allFile.addBodyPart(contentText);
        allFile.setSubType("mixed");//正文和附件都存在邮件中,所有类型设置为mixed
           //设置到消息中,保存修改
        message.setContent(allFile);//把最后编辑好的邮件放到消息当中
        message.saveChanges();//保存修改

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

        // 关闭网络资源连接
        transport.close();
        System.out.println("邮件已发送!");

    }
}

效果:

在这里插入图片描述


The End!!创作不易,欢迎点赞/评论!!欢迎关注个人公众号

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值