SMTP协议与JavaMail相关类SMTPTransport的学习

来源:互联网 发布:淘宝信用贷款额度降低 编辑:程序博客网 时间:2024/06/15 12:47

工作中碰到邮件发送失败的问题,跟踪到了底层代码。在找问题的同时,浏览了JavaMail的实现,并且重点学习了SMTPTransport类,顺便研究了下SMTP协议,整体做个记录。

一、SMTP协议

SMTP为Simple Mail Transfer Protocal的简称,即简单邮件传输协议。是一种提供有效可靠传送电子邮件的协议,用于在两台邮件服务器间交换邮件。负责发送邮件的服务器称为SMTP客户,负责接收邮件的服务器称为SMTP服务器。附上协议全文:RFC 821

二、SMTP连接与发送过程

1、建立TCP连接

2、客户端发送HELO命令,标识发件人身份,然后发送MAIL命令

3、服务端以OK作为相应,准备接收

4、客户端发送RCPT命令,标识收件人,可以有多个收件人

5、服务端返回是否同意为收件人接收邮件

6、协商接束,客户端用DATA命令发送邮件内容。邮件内容以<CRLF>.<CRLF>结束

7、发送接束,客户端用QUIT命令退出

三、JavaMail

JavaMail是Sun公司为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如:SMTP、POP3、IMAP和MIME等。JavaMail API封装在mail.jar的文件中。

JavaMail API按功能可分为三大类:

1)创建与解析邮件内容的API

2)发送邮件的API

3)接收邮件的API

核心API类包括Message、Session、Transport、Store等类。

Message类

javax.mail.Message 类是创建和解析邮件的核心API,它的实例对象代表一封电子邮件。客户端程序发送邮件时,首先使用创建邮件的API,将要创建邮件的数据封装到Message对象中,然后把该对象传递给邮件发送API发送出去。客户端程序接收邮件时,邮件接收API把接收到的邮件数据封装在Message类的实例对象中,客户端程序再使用邮件解析API,从Message对象中解析出接收到的邮件数据。

Session类

javax.mail.Session 类用于定义整个应用程序所需的环境信息,以及收集客户端与邮件服务器建立网络连接的会话信息,如邮件服务器的主机名、端口号、采用的邮件发送和接收协议等。Session对象根据这些会话信息构建邮件收发的Store和Transport对象,以及为客户端创建Message对象提供信息支持。

Transport类

javax.mail.Transport 类是发送邮件的核心API类,它的实例对象,代表实现了某个邮件发送协议的邮件发送对象,例如SMTP 协议。客户端程序创建好Message对象后,只需要使用邮件发送API得到 Transport 对象,然后把 Message 对象传递给 Transport 对象,并调用它的发送方法,就可以把邮件发送给指定的SMTP服务器。

Store类

javax.mail.Store 类是接收邮件的核心API类,它的实例对象代表实现某个邮件接收协议的邮件接收对象,例如POP3和IMAP协议。客户端程序接收邮件时,只需要使用邮件接收API得到Store对象,然后调用Store对象的接收方法,就可以从指定的 POP3服务器中获得邮件数据,并把这些邮件数据封装到表示邮件的Message对象中。

四、SMTPTransport类

因为排查问题的原因,重点看了SMTPTransport类的内容。这里先总结下SMTPTransport类。

SMTPTransport类实现了SMTP协议的邮件提交与发送过程,主要包括网络传输相关方法、sendMessage()方法以及其他的辅助方法。SMTPTransport类的重点即在sendMessage()方法。

sendMessage()方法按照  验证连接->验证发送方->验证接收方->发送->结束  的顺序来实现SMTP邮件的发送。

sendMessage()方法中的rcptTo()方法实现了接收方的验证,也即引起本次排查的问题所在。

rcptTo()方法通过循环发送RCPT TO命令来进行服务端接收验证,并通过服务器返回状态值进行判断与操作。

for (int i = 0; i < addresses.length; i++) {    sfex = null;    InternetAddress ia = (InternetAddress)addresses[i];    String cmd = "RCPT TO:" + normalizeAddress(ia.getAddress());    if (dsn)cmd += " NOTIFY=" + notify;    // send the addresses to the SMTP server    sendCommand(cmd);    // check the server's response for address validity    retCode = readServerResponse();    switch (retCode) {    case 250: case 251:                ...        }}

本次的问题即在服务端返回的状态值上。

五、结论

多看底层的代码是很有好处的。学无止境。

(SMPTTransport类的其他方法后续补上)

注:

1、关于SMPT协议,可参考:SMTP协议解析及工作过程  与  理解邮件传输协议

2、关于JavaMail API,可参考:JavaMail API简介

3、本次学习的JavaMail源码为mail-1.4.2-sources.jar,下载地址:mail-1.4.2-sources.jar

阅读全文
0 0
原创粉丝点击