使用过JavaMail的api发送邮件的人可能会有这样一个疑惑:我如何知道我调用该api发送的邮件是否成功呢?一般的开放的api给我们调用都会有个返回值或者状态码,来告诉我们执行成功与否。但是JavaMail却没有提供这样一个返回值。

所以在调用JavaMail发送邮件的时候,我们只能通过catch异常的方式来判断邮件是否发送成功。我们认为只要没有异常发生,那么邮件就能发送成功。那么我们就来分析一下JavaMail为什么没有提供返回值,和通过异常判断邮件发送成功状态是否靠谱。

JavaMail发送邮件原理

在使用JavaMail进行发送邮件时,我们必须提供一个邮件会话。创建邮件会话的过程如下:

Properties props = new Properties();
        // 发送邮件的服务器的IP和端口
        props.put("mail.smtp.host", MAIL_SMTP_HOST);
        props.put("mail.smtp.port", MAIL_SMTP_PORT);
        // 是否需要身份验证
        props.put("mail.smtp.auth", "true");

        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        Session session = Session.getDefaultInstance(props, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
            // 登陆邮件发送服务器的用户名和密码
                return new PasswordAuthentication(MAIL_SENDER_MAIL, MAIL_SENDER_PASS);
            }
        });

  分析一下代码。在创建Session之前我们先创建一个Properties,这个Properties设置了这样几个参数:mail.smtp.host、mail.smtp.port、mail.smtp.auth和mail.smtp.socketFactory.class。在创建Session的时候还要传入发送邮件使用的用户名及密码。

发送邮件代码如下:

//使用JavaMail发送邮件的5个步骤
        //1、创建session
         Session session = Session.getInstance(prop);
         //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
         session.setDebug(true);
         //2、通过session得到transport对象
         Transport ts = session.getTransport();
         //3、使用邮箱的用户名和密码连上邮件服务器,发送邮件时,发件人需要提交邮箱的用户名和密码给smtp服务器,用户名和密码都通过验证之后才能够正常发送邮件给收件人。
         ts.connect("smtp.sohu.com", "gacl", "邮箱密码");
         //4、创建邮件
         Message message = createSimpleMail(session);
         //5、发送邮件
         ts.sendMessage(message, message.getAllRecipients());
         //关闭连接
         ts.close();

总结发送邮件过程主要有以下几个步骤:

1.创建包含邮件服务器的网络链接的Session对象
2.创建代表邮件内容的Message对象
3.创建Transport对象
4.链接服务器
5.发送Message
6.关闭链接

由于Transport只是一个抽象类,所以这里在发送Message的时候用调用的方法ts.sendMessage实际上是调用的Transport的实现类SMTPTransport的sendMessage方法。
而SMTPTransport的sendMessage方法则依赖SMTP协议进行邮件的发送。

所以,当javamail使用smtp服务发送邮件时,当你把邮件发送到smtp服务器的时候,你只能得到已经发送到smtp的队列中的状态,但是邮件服务器是否能发送成功,你是得不到的。就是说,你不能保证邮件发送一定成功。 这就取决于SMTP协议的内容传输了。

但是SMTP协议如果传输失败,是会报错的。SMTP由TCP提供的可靠的数据传输服务把邮件消息从发信人的邮件服务器传送到收信人的邮件服务器。
所以我们可以认为当我们调用JavaMail发送邮件时,如果程序没有报错则表示邮件发送成功。

SMTP工作机制

SMTP通常有两种工作模式:发送SMTP和接收SMTP。
具体工作方式为:发送SMTP在接到用户的邮件请求后,判断此邮件是否为本地邮件,若是直接投送到用户的邮箱,否则向dns查询远端邮件服务器的MX纪录,并建立与远端接收SMTP之间的一个双向传送通道,此后SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方面传送。一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此重复多次。当接收者收到全部邮件后会接收到特别的序列,如果接收者成功处理了邮件,则返回OK应答即可。

SMTP工作过程

简单邮件传输协议(SMTP)是一种基于文本的电子邮件传输协议,是在因特网中用于在邮件服务器之间交换邮件的协议。SMTP是应用层的服务,可以适应于各种网络系统。
SMTP的命令和响应都是基于文本,以命令行为单位,换行符为CR/LF。响应信息一般只有一行,由一个3位数的代码开始,后面可附上很简短的文字说明。
SMTP要经过建立连接、传送邮件和释放连接3个阶段。具体为:

(1)建立TCP连接。
(2)客户端向服务器发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令。
(3)服务器端以OK作为响应,表示准备接收。
(4)客户端发送RCPT命令。
(5)服务器端表示是否愿意为收件人接收邮件。
(6)协商结束,发送邮件,用命令DATA发送输入内容。
(7)结束此次发送,用QUIT命令退出。

SMTP服务器基于DNS中的邮件交换(MX)记录路由电子邮件。电子邮件系统发邮件时是根据收信人的地址后缀来定位邮件服务器的。SMTP通过用户代理程序(UA)完成邮件的编辑、收取和阅读等功能;通过邮件传输代理程序(MTA)将邮件传送到目的地。

JavaMail如何保证邮件发送成功的更多相关文章

  1. ActiveMQ入门系列之应用:Springboot+ActiveMQ+JavaMail实现异步邮件发送

    现在邮件发送功能已经是几乎每个系统或网址必备的功能了,从用户注册的确认到找回密码再到消息提醒,这些功能普遍的会用到邮件发送功能.我们都买过火车票,买完后会有邮件提醒,有时候邮件并不是买完票立马就能收到 ...

  2. 使用javaMail实现简单邮件发送

    一.首先你要用来发送邮件的qq邮箱需要开通pop3/smtp服务,这个可以百度一下就知道了 二.导入所需要的jar包,我使用的是maven添加依赖 <dependency> <gro ...

  3. java-基于JavaMail的Java邮件发送

    1.基于JavaMail的Java邮件发送:简单邮件发送 2.基于JavaMail的Java邮件发送:复杂邮件发送

  4. 基于JavaMail的Java邮件发送:复杂邮件发送

    参考:http://blog.csdn.net/xietansheng/article/details/51722660package com.bfd.ftp.utils;import java.ut ...

  5. 【转】基于JavaMail的Java邮件发送

    http://blog.csdn.net/xietansheng/article/details/51673073 http://blog.csdn.net/xietansheng/article/d ...

  6. jenkins构建邮件自动发送,测试邮件发送成功,构建项目邮件发送不成功的问题

    提示问题: Connection error sending email,retrying once more in 10 seconds…… Connection error sending ema ...

  7. JavaMail技术实现邮件发送转【】

    1.导入2个jar包,mail.jar,activation.jar 2.导入的jar包与myeclipse中自带的javaee 中的javaee.jar中的javax.activation包及jav ...

  8. 基于JavaMail的Java邮件发送:简单邮件发送

    使用Java应用程序发送 E-mail 十分简单,但是首先你应该在你的机器上安装 JavaMail API 和Java Activation Framework (JAF) . 您可以从 Java 网 ...

  9. 在outlook中发邮件判断邮件发送成功的方法

    早上给企业发了求职邮件,但是发送的时候,自己发现附件比较大,因为之前比较少使用这个工具来发邮件,所以发送之后没有提醒成功与否,求职心切,内心变得比较紧张. 所以查了查方法,发现了以下解决方案,现备注下 ...

随机推荐

  1. Oracle RAC Failover

    Oracle  RAC 同时具备HA(High Availiablity) 和LB(LoadBalance). 而其高可用性的基础就是Failover(故障转移). 它指集群中任何一个节点的故障都不会 ...

  2. Linux驱动开发之开篇--HelloWorld

    Linux驱动的编写,大致分为两个过程,第一个过程为测试阶段,即为某一具体的设备,添加必要的驱动模块,为了节省编译时间,需要将代码单独放在一处,在编译时,只需要要调用内核的头文件即可:第二个过程为布置 ...

  3. WPF-控件-将ListBox条目水平排列

    <Grid Margin="6"> <ListBox> <!--ItemsPanel--> <ListBox.ItemsPanel> ...

  4. 第一章 Web MVC简介

    Web MVC简介 1.1.Web开发中的请求-响应模型: 在Web世界里,具体步骤如下: 1.  Web浏览器(如IE)发起请求,如访问hao123主页 2.  Web服务器(如Tomcat)接收请 ...

  5. Feature Stapling in SharePoint 2010

    http://msdn.microsoft.com/en-us/library/bb861862(v=office.12).aspx http://gallery.technet.microsoft. ...

  6. cocos2dx中的定时器及其分类

    cocos2dx中的定时器分三大类: 1.帧循环定时器 2.一次性定时器 3.自定义定时器 一.帧循环定时器,顾名思义,每一帧都会执行一次,用于实时性要求比较高的场合,如碰撞检测 void sched ...

  7. Unity3D 利用NGUI2.6.3做技能冷却的CD效果

    转自http://blog.csdn.net/qqmcy/article/details/9469021 NGUI非常强大我们今天来学习一下,如何利用NGUI做技能冷却的CD效果.先导入NGUI的插件 ...

  8. org.apache.commons.dbutils.QueryRunner 执行sqlserver的存储过程

    执行不带输出参数的存储过程与 执行普通update  sql没有什么区别,直接调用即可: 示例代码: public Boolean startResidentialInfoStatistics(Str ...

  9. Matlab中cell2mat的使用

    binIndices是1*50的cell,每个cell是的1*n(n不定),那么cell2mat(binIndices)得到的是1*sum(cellfun(@length,binIndices))的行 ...

  10. oracle中行转列函数

    一.问题描述 有时在“相关子查询中”需要查询某个实体类对应的某个字段有多个值,如果不做行专列查询,会提示返回多个列的错误.例如: 如上图所示,一个组合包,可能对应多个产品,需要你将所对应的多个产品都放 ...