javaMail学习二 电子邮件的工作原理

来源:互联网 发布:有什么编程软件 编辑:程序博客网 时间:2024/06/06 05:12

1.1下面以sina和sohu这两个电子邮件为例子来讲解电子邮件的传输过程和工作原理.假设sina邮箱的电子邮件为lisi@sina.com,sohu的邮箱账户为wangwu@sohu.com,他们之间的邮件的收发过程为

下面

 

下面根据上图来讲解一下邮件收发过程:

1.lisa@sina.com的邮件客户端程序(这里假设为outlook)与是sina的smtp服务器建立网络连接,并以lisa的用户名和密码登录后,使用smtp协议把邮件发送给sina的smtp服务器

2.sina的smtp服务器收到lisa@sina.com提交的电子邮件后,首先根据收件人的地址后缀判断接收者的邮件是否属于该SMTP服务器的管辖范围,如果是的话就直接把邮件存储到收件人的邮箱中,否则  sina的SMTP服务器向DNS服务器查询收件人的邮件地址后缀(sohu.com)所表示的域名MX记录,从而得到sohu的SMTP服务器信息,然后与sohu的smtp服务器建立连接并采用smtp协议把邮件发送给sohu的SMTP服务器。

3.sohu的SMTP服务器收到sina的SMTP服务器发来的电子邮件后,也将根据收件人的地址判断该邮件是否属于该SMTP服务器的管辖范围,如果是的话就直接把邮件存储到收件人邮箱(一般不会出现这种情况),否则,sohu的SMTP服务器可能继续转发这封电子邮件,也可能丢弃这封邮件。

4.拥有wangwu@sohu.com账户的用户通过邮件客户端程序(这里假设也为outlook)与sohu的pop3/imap服务器建立网络连接,并以wangwu的用户名和密码进行登录后,就可以通过pop3/imap协议查看wangwu@sohu.com邮箱中是否有新邮件,如果有的话,则使用pp3/imap读取邮箱中的新邮件。

 

想一想邮件客户端和SMTP服务器分别如何发送程序?

     邮件客户端软件与SMTP服务器之间,以及两台SMTP服务器之间都采用了SMTP协议进行通信。邮件客户端软件只采用了SMTP协议发送邮件,即邮件客户端软件只作为SMTP服务器的发送方。SMTP服务器既要采用SMTP协议向其他SMTP服务器发送邮件,又要采用SMTP协议接收其他SMTP服务器或邮件客户端软件发送过来的邮件,即SMTP服务器既是邮件的发送方又是邮件的接收方。邮件客户端软件和SMTP服务器都可以使用SMTP协议来发送邮件,仅发送邮件这一功能而言,他们在技术实现上有何差异呢?

他们的只要差异在于:

1.SMTP服务器接收邮件客户端软件发送过来的邮件后,需要根据收件人地址的域名将邮件转发给目标SMTP服务器,而大量的收件人地址中肯定会出现各种可能的域名,因此,SMTP服务器涉及到要与其他多台不能事先确定的SMTP服务器进行通信,它需要具有根据收件人地址的域名查询出该域的SMTP服务器的功能,即需要具有查询域名的MX记录的功能。邮件客户端软件被设定与固定的SMTP服务器通信,它可以直接与指定的SMTP服务器建立网络连接,因此它不需要根据收件人地址的域名来查询该域的SMTP服务器的功能。

2.对于来自某个邮件客户端的软件的邮件传输请求,SMTP服务器可能需要对发件人的用户,账户信息进行校验,因此邮件客户端软件需要具有向SMTP服务器传送用户账号信息的功能。SMTP服务器能够直接接收来自其他SMTP服务器的邮件传输请求,因此SMTP服务器在发送邮件是根本不需要传送用户账号信息的功能。

 

2.邮件传输协议

SMTP协议:该协议定义了邮件客户端软件和SMTP服务器,以及SMTP服务器之间的通信规则。

pop3/imap协议:该协议定义了邮件客户端软件和POP3/IMAP服务器之间的通信规则。

2.1  SMTP协议:

SMTP协议通信的双方采用一问一答的命令/响应形式进行对话,SMTP协议定义了对话的规则和所有命令/响应的语法格式。SMTP协议分为标准的SMTP协议和扩展的SMTP协议。扩展的SMTP协议在标准的SMTP协议基础上增加了邮件安全方面的认证,人们现在所说的SMTP协议都是扩展的SMTP协议。

SMTP一共定义了18条命令,发送一封邮件的命令通常只需要用到6个命令。下面介绍一下发送命令的先后顺序,并描述了其语法格式和功能,其中<sp>代表空格,<crlf>代表回车和换行。

ehlo<sp><domain><crlf>

该命令是SMTP邮件发送程序与SMTP邮件接收程序建立连接后必须发送的第一条SMTP命令,参数<domain>表示SMTP邮件发送者的主机名。ehlo命令用于替代传统的SMTP协议中的helo命令。

auth<sp><para><crlf>

如果SMTP邮件接受程序需要SMTP邮件发送程序进行认证时,它会向SMTP邮件发送程序提示它所采用的认证方式,SMTP邮件发送程序接着应该使用这个命令回应SMTP邮件接收程序,参数<para>表示回应的认证方式,通常是SMTP邮件接收程序先前提示的认证方式。

mail<sp>From:<reverse-path><crlf>

此命令用于指定邮件发送者的邮箱地址,参数<reverse-path>表示发件人的邮箱地址。

rcpt<sp>To:<forward-patn><crlf>

此命令用于指定邮件接受者的邮箱地址,参数<forward-patn>表示接收者的地址,如果邮件要发送给多个邮件接受者,那么应该使用 多条rcpt<sp>To命令来分别指定每一个邮件接受者的地址。

data<crlf>

该命令用于表示SMTP邮件发送程序准备开始传送邮件内容,在这个命令后面发送的所有数据都将被单做邮件内容,直至遇到“<crlf>.<crlf>”标识符,则表示邮件内容结束。

quit<crlf>

此命令表示要结束邮件发送过程,SMTP邮件接收程序接收此命令后,将关闭与SMTP邮件发送服务器的网络连接。

   虽然SMTP协议之定义了18条SMTP命令,但是对一般的用户来说,只需要掌握上述的6条命令就差不多了。

对于SMTP邮件发送程序发送的每一条命令,SMTP邮件接收程序都将回应一条响应信息。每条响应信息都以一个响应状态码开头,如下

250 ok

   响应状态码由于表示SMTP服务器对请求命令的处理结果和状态,它是一个三位的十进制数。响应状态的最高位数字代表了不同的分类,单其为2时表示命令执行成功;为5时表示命令执行失败,为3时表示命令没有完成。各种响应码的代表意义请查阅RFC821文档

SMTP协议是一个基于TCP/IP的应用层协议,SMTP服务器的默认网络监听端口为25,因此可以使用windows自带的Telnet程序连接到某个SMTP服务器并与之对话。使用Telnet程序连接到某个SMTP服务器后,只需要按照SMTP协议的通信规则向该SMTP服务器手工发送上述的命令,就可以将一封电子邮件发送给SMTP服务器。SMTP服务器接收到Telnet程序发送来的电子邮件后,将根据“rcpt  to”命令中指定的收件人的地址是否属于自己的管辖范围,将电子邮件存储到本地收件人的邮箱中,或者将邮件转发给其他SMTP服务器。

   可以使用Telnet来模拟一个邮件客户端软件访问SMTP服务器,为了遏制垃圾邮件的蔓延,internet上的SMTP服务器通常采用了各种防垃圾邮件的手段,其中最基本的一条措施就是:只有某台计算机具有真实的internet主机名且该主机名没有被列入到被访问的SMTP服务器的黑名单列表中时,这台计算机才能以SMTP服务器的身份将邮件发送给被访问的SMTP服务器,否则,这台计算机就只能邮件客户端软件的身份将邮件发送给被访问的SMTP服务器,这时,被访问的SMTP服务器将对邮件客户端软件进行用户身份验证。显然,对于绝大多数读者的计算机来说,都只能以邮件客户端软件的身份来访问internet上的SMTP服务器。

  下面将通过在Telnet程序中手工发送SMTP命令来将一封邮件发送给Sina的SMTP服务器,来体验一下。

邮箱自己自备,然后通过nslookup查询某个域的MX记录,就可以获得该域的SMTP服务器主机名,

注意:当SMTP服务器要对邮件客户端软件进行身份验证时,邮件客户端软件需要对用户名和密码进行BASE64编码后在传递给SMTP服务器,因此需要编写BASE64编码工具,对用户名和密码进行编码。下列代码就是BASE64编码工具程序

package com.jt.mail;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import sun.misc.BASE64Encoder;

/**
 * @author jt
 *2015-12-30 下午9:45:38
 *
 */
//BASE64编码工具
public class BASE64 {

 /**
  * @param args
  * @throws IOException
  */
 public static void main(String[] args) throws IOException {
  System.out.println("请输入用户名:");
  
  //将用户输入的字符存到缓冲池里
  //InputStreamReader类将字节流转化为字符流,是字节流通向字符流的桥梁(字符输入流类)
  BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
  //从缓冲池里面读取文本到程序里
  String username=in.readLine();
  System.out.println("请输入密码:");
  String password=in.readLine();
  
  BASE64Encoder encoder=new BASE64Encoder();
  System.out.println("编码后的用户名:"+encoder.encode(username.getBytes()));
  System.out.println("编码后的密码:"+encoder.encode(password.getBytes()));
  
 }

}

然后打开cmd窗口

输入:telnet smtp.sina.com.cn 25

连接到sina的smtp服务器

然后回车,该命令的正常执行结果为下图所示

上图显示的是sina的SMTP服务器返回给客户端的响应信息,其中包含3部分的内容,各部分的内容如下:

220:是邮件服务器返回给客户端的响应状态码,它表示邮件服务器准备就绪

smtp-5-121.smtpsmail.fmail.xd.sinanode.com:表示当前进行响应的邮件服务器的主机名

ESMTP:表示当前邮件服务器支持扩张SMTP协议

SMTP程序与SMTP服务器建立连接后,接着使用ehlo命令向SMTP服务器发送问候信息,由于当前运行的Telnet程序的计算机根本就没有在internet上注册主机名,所以这里随便使用一个名称jiangtao7913来表示ehlo命令中的主机名,发送ehlo命令后,邮件服务器返回如下图的信息

 

上图中返回了一系列以250开头的信息,响应状态码为250表示当前命令执行正常,其后的各种信息意义如下:

smtp-5-121.smtpsmail.fmail.xd.sinanode.com:表示当前进行响应的SMTP服务器主机名

AUTH  LOGIN  PLAIN:表示客户端输入认证命令的格式

AUTH =LOGIN PLAIN:表示SMTP服务器对客户端的认证方式为LOGIN。AUTH的认证方式主要有LOGIN,CRAM-MD5,PLAIN等几种,LOGIN认证方式要求客户端把用户名和密码经过BASE64编码后发送给SMTP服务器,CRAM-MD5认证方式要求客户端把用户名和密码经过MD5算法加密后发送给SMTP服务器,PLAIN认证方式要求客户端程序直接把用户名和密码发送给SMTP服务器。目前使用最多的也是LOGIN

8BITMIME:表示SMTP服务器支持8BIT编码的MIME邮件内容

      通常情况下,SMTP服务器接收到ehlo命令后,它将查询ehlo命令中指定的主机名是否是邮件发送程序所在计算机的主机名,如果不是的话,那么则认为邮件发送程序是一个客户端软件,要求客户端输入用户的账户信息并进行验证才能使用mail from命令,这时将返回上述图示的内容

  

 

 

b

如上图表示邮件发送成功了。接下你就可以到目标邮件去查看邮件了。

邮件的内容有两部分组成:

邮件头和邮件体

邮件阅读程序显示的发件人,收件人,和主题等信息就是从邮件头中提取出来的,其中的from字段用于指定发件人的地址,to字段用于指定收件人的地址,subject字段用于指定邮件的主题。由于邮件体头中from字段指定的收件人与mail from命令中指定的发件人可以不相同,一些恶意的人可能利用这个缺点发送一些伪造邮件,不过现在的邮件安全性高了,各大smtp服务器都在这方面做了加强。

接着输入quit命令,结束整个邮件的传输命令,SMTP接收到客户端发送来的quit命令后,将断开与客户端的网络连接,telnet程序结束运行,windows命令窗口退回dos界面。

 

下面我们来利用pop3协议接收邮件,我们手工telnet来接收邮件。各种邮件发送软件发送邮件是就是利用这些SMTP命令的,他们的作用在于帮助用户把邮件发送的过程自动化。SMTP服务器可以接收邮件客户端发送过来的邮件,在电子邮件应用的早期,SMTP服务器都是非常开放的SMTP服务器不去识别发送方是邮件客户端程序还是其他SMTP服务器,人们可以使用邮件客户端程序连接上任意一台SMTP服务器,然后不需要任何验证就可以与这台SMTP服务器进行对话和通过该SMTP服务器转发电子邮件。后来一些人利用SMTP服务器的开放性,编写了专门用来自动发送大量广告信息的邮件群发程序,这种群发软件通常有两种技术实现方式。

1.采用邮件客户端软件发送邮件的方式。在这种情况下,邮件群发软件需要连接上internet上的某台SMTP服务器,然后将所有邮件逐一发给该SMTP服务器,在由该SMTP服务器将所有邮件转发给目标邮件。

2.采用SMTP服务器发送邮件的方式,这种情况下,邮件群发软件需要根据每个收件人地址的域名从DNS服务器上查询出该域的SMTP服务器,然后直接连上该SMTP服务器和将邮件发送给该SMTP服务器。

由于这个垃圾邮件带来的问题,各大邮件服务器都采取了措施:

1.SMTP服务器查询邮件发送程序在ehlo命令中指定的主机名是否是自己的真实的主机名,如果不是则认为邮件发送程序是一个邮件客户端软件,要求对发件人的账户信息进行校验,只有验证通过后,才接受发送程序所发送的邮件和进行邮件转发。由于一般的普通计算机不具有在internet上的DNS中注册主机名,通过这种方式就可以防止在普通计算机上运行的邮件群发软件采用SMTP服务器发送邮件的方式将垃圾邮件直接发送给SMTP服务器,这属于在邮件接收环节拒绝垃圾邮件的一种措施。

2.SMTP服务器限制其中的每个用户账户每天做多能发出的邮件数量,这样就可以控制邮件群发软件通过这SMTP服务器向外发送垃圾邮件的数量,这是在邮件发送环节拒绝垃圾邮件的一种措施。

3.如果邮件发送程序在ehlo命令中指定的主机名是它自己在internet上的DNS中注册的真实主机名,邮件接收SMTP服务器将认为邮件发送方也是一台SMTP服务器,不对发件人的用户账户信息进行验证,直接接收其所管辖的邮件地址的邮件,但不接受和转发其管辖范围之外的邮件地址的邮件,这也属于在邮件发送环节拒绝垃圾邮件的一种方式。

4.即使邮件发送程序在ehlo命令中指定的主机名是它在internet上的DNS中注册的真实主机名,但是如果运行邮件发送程序的计算机已经被列入了邮件接收SMTP服务器的黑名单中,邮件接收SMTP服务器也将拒收该计算机所发来的邮件。

 

pop3协议:邮件服务器提供商专门为每个用户申请的电子邮件提供了专门的邮件存储空间,SMTP服务器将接收到的电子邮件保存到相应用户的电子邮箱中。用户要从邮件服务提供商提供的电子邮箱中获取自己的电子邮件,需要邮件服务器提供商的POP3邮件服务器来帮助完成。

POP3协议定义了邮件客户端程序与POP3服务器进行通信的具体规则和细节。

pop3协议在RFC1939文档中定义,它采用的网络监听端口号默认为110,pop3协议共定义了12条pop3命令,邮件客户端程序通过这些命令来检索和获取用户电子邮箱中的邮件信息

下列分别列出了12条pop3命令及其说明,其中<sp>代表空格,<crlf>代表换行和回车

user<sp>username<crlf>user命令是pop3客户端程序与pop3邮件服务器建立连接后通常发送的第一条命令,参数username是表示收件人的账户名称

pass<sp>password<crlf>pass命令是在user命令成功通过后,pop3客户端程序接着发送的命令,它用于传递账户的密码,参数password表示账户的密码

apop<sp>name,digest<crlf>apop命令用于代替user和pass命令,它以MD5数字摘要的形式向pop3邮件服务器提交账户密码

stat<crlf>stat命令用于查询邮箱中的统计信息,例如,邮箱中有邮件数和邮件占用的字节大小等

uidl<sp>msg#<crlf>uidl命令用于查询某封邮件的唯一标识,参数msg#表示邮件的序号,是一个从1开始编号的数字

list<sp>[msg#]<crlf>list命令用于列出邮箱中的邮件信息,参数msg#是一个可选参数,表示邮件的序号。当不指定参数时,pop3服务器列出邮箱中所有的邮件信息;当指定参数msg#时,pop3服务器只返回该序列号对应的邮件信息。

retr<sp>msg#<crlf>list命令用于获取某封邮件的内容,参数msg#表示邮件的序号

dele<sp>msg#<crlf>dele命令用于在某封邮件上设置删除标记,参数msg#表示邮件的序号,pop3服务器执行dele命令时,只是为邮件设置了删除标记,并没有真正把邮件删除掉,只有pop3客户端程序发出quit命令后,pop3服务器才会真正删除所有设置了删除标记的邮件

reset<crlf>rset命令用于清除所有邮件的删除标记

top<sp>msg#<sp>n<crlf>top命令用于获取某封邮件的邮件头和邮件体中的前n行内容,参数msg#表示邮件的序号,参数n表示要返回邮件的前几行内容。使用这条命令以提高web mail系统(通过web站点上收发邮件)中的邮件列表显示处理效率,因为这种情况下不需要获取每封邮件的完整内容,而是仅仅需要获取每封邮件的邮件头信息。

noop<crlf>noop命令用于检测pop3客户端与pop3服务器的连接情况

quit<crlf>quit命令表示要结束邮件接收过程,pop3服务器接收到此命令后,将删除所有设置了删除标记的邮件,并关闭与pop3客户端程序的网络连接。

  对于pop3客户端程序发送的每一条pop3命令,pop3服务器都将回应一些响应信息。响应信息由一行或则多行文本信息组成,其中的第一行始终以“+ok”或“-err”开头,他们分别是当前命令执行成功或失败。

下面来实践一下:使用telnet来接收邮件并分析其过程。

 

 在cmd 输入如下命令:

telnet pop3.sina.com 110

如下是pop3服务器响应给客户端的信息,“+OK”表示客户端连接pop3服务器连接成功

 

接着输入 user lilisasamm 回车

输入pass  账号密码

stat  回车 如下图,表示该账号下有4封邮件,占用用直接大小为10106字节

 

 

 输入list 回车命令,如下图列出所有邮件以及邮件的大小

 

 

 

 接着用retr 命令查看邮件的内容,如下图

 

 接着使用dele 删除指定邮件   如下图第3封邮件被删除了

接着使用rset清除dele命令为邮件设置的删除标记,接着list邮件,发现删除的第三封邮件又出来了,因此可见dele并没有删除邮件,只是为邮件设置了删除标记,然后使用rset命令可以清除这个删除标记,pop3服务器只有接收到pop3客户端发送的quit命令后,才会真正的删除所有设置了删除标记的邮件。

 

 imap协议:imap协议是对pop3协议的一种扩展,定义了邮件客户端与邮件服务器的通信规则,它定义了更为强大的邮件接收功能。

主要体现在如下:

1.imap协议具有摘要浏览功能,可以让用户读完所有邮件的主题,发件人,大小等信息后,再由用户做出是否下载或直接在服务器上删除邮件的决定。

2.imap可以让用户有选择性的现在附件。

3.imap可以让用户在邮件服务器上创建自己的邮件夹,分类保存各个邮件。

 

 

 

 

 

0 0
原创粉丝点击