|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
在性能方面,在windows平台下,.net可能是占强项,要是把.net放在sun开发的操作系统上去运行呢?根本就运行不了,.net对其它操作系统的支持也很弱,性能也可能比不上java。发送邮件冯睿
本文先容了怎样使用Java的收集API来完成一个电子邮件工具程序。一般Email工具都是利用SMTP(复杂邮件传输协定,SimpleMailTransferProtocol)来发送邮件,利用POP3协定来承受电子邮件。在本文中只对这两个协定作复杂先容。假如有乐趣的读者能够参考以下站点:
POP3:ftp://ftp.isi.edu/in-notes/rfc1939.txt
SMTP:ftp://ftp.isi.edu/in-notes/rfc2821.txt
Java中固然供应了JavaMailAPI,可是因为在这篇文章中我将从底层来切磋电子邮件软件是怎样事情的,因而不会利用JavaMailAPI。本文中的例子是在J2SE1.4下开辟的。
电子邮件的格局
在开辟Email软件之前,你必要懂得电子邮件的格局。依据RFC2882(http://www.faqs.org/rfcs/rfc2822.html)的划定,电子邮件由良多行构成,每行由〈CRLF〉(ASCII代码13和ASCII代码10)停止。每行的最年夜长度为998个字符。个中有些行供应了收发电子邮件所必须的信息,这些行被称为头(Header),一切的头组成了头域(HeaderField)。其他的行用于保留邮件的详细内容。
头域供应了良多信息,个中包含邮件的来历;邮件的目标地和邮件的主题等。每一个头由称号和冒号加上响应的值组成。比方From:、Send:和Reply-To:中纪录了邮件的来历。在From:中纪录的是邮件的作者;在Sender:中指定了发送邮件的代办署理(能够是邮件地点,也能够是呆板称号);Reply-To:中指定了承受复书的邮箱地点。
一封邮件大概有多个作者,因而From:中能够指定一个或多个邮箱地点。上面给出了一个个From:的例子:
From:RayFeng〈rayfeng@yahoo.com.cn〉,bogus@yahoo.com.cn
在一封电子邮件中只能有一个Sender。因而Sender:的值只能包括一个邮箱地点。假如在From:中只要一个作者,并且Sender:的值和From:的值不异,则Sender:就不会呈现在电子邮件中,不然会呈现信息冗余;反之Sender:则应当呈现在邮件中。上面是一个Sender:的例子:
Sender:RayFengrayfeng@yahoo.com.cn
在电子邮件中能够指定将复书发送到多个邮箱地点中。因而Reply-To:中能够包括一个或多个邮箱地点,每一个地点之间用逗号离隔。假如邮件中有Reply-To:,复书会被发送到排列在Reply-To:中的一切地点;假如邮件中没有Reply-To:,则复书会被发送到排列在From:中的地点。那末谁会收到邮件呢?To:和Cc:中保留了承受邮件的邮箱地点。二者的值都能够包括多个邮箱地点。
除邮件的来历和承受者,RFC2882中还界说了其他一些头,比方Subject:中包括了电子邮件的主题。上面是一个电子邮件头域的例子:
From:RayFeng〈rayfeng@yahoo.com.cn〉
To:bogus〈bogus@yahoo.com.cn〉
Cc:John〈John@yahoo.com.cn〉
Subject:TestEmail
附件
在MIME中同意在电子邮件中增加二进制文件,被增加的文件叫做附件。附件的内容能够作为邮件的一部分举行传输。MIME是假如完成这个功效的呢?在MIME中引进了良多头,个中和附件相干的最主要的就是Content-Type:和Content-Tracnsfer-Encoding:。为了在一封电子邮件中辨别分歧的部分,MIME请求在Content-Type:multipart/mixed头中包括一个界限参数。界限参数的值是一个在双引号中的字符串。经由过程这个字符串,程序就能够辨别电子邮件的分歧部分。在传输电子邮件的内容前,程序先传输一个〈CRLF〉,两个连字符和界限参数。当完成Email内容的传输后,程序会在最初传输界限参数和两个连字符。
上面的电子邮件中包括了两个部分,一个部分是由iso-8859-1字符构成的文本,一部分是名为file.txt的附件。这里没有包括Content-Transfer-Encoding:头,标明利用缺省的7位ASCII字符。
Content-Type:multipart/mixed;boundary="***"
--***
Content-Type:text/plain;charset="iso-8859-1"
Thismessagehasanattachment.
--***
Content-Type:text/plain;name="file.txt"
Attachmenttext.
--***--
发送电子邮件
screen.width-333)this.width=screen.width-333;">
基于互联网的电子邮件一般是使用SMTP收集协定举行传输的。依据SMTP,当电子邮件程序必要发送电子邮件时,该程序起首统一个SMTP服务程序创建起双向的通信通道(一般是经由过程套接字创建这类通道的)。这个基础的SMTP服务程序也许是这份电子邮件的终极目标地,也大概只是通向另外一个SMTP服务程序的跳板。总而言之,当电子邮件程序同SMTP服务程序创建起双相的传输通道后,电子邮件程序会向SMTP服务程序发送一系列基于ASCII字符的命令,而SMTP服务程序会对这些命令发生响应的回应来标明响应的操纵是乐成仍是失利了。
让我们假定一切的操纵都乐成了,那末电子邮件程序将把邮件发送到SMTP服务程序,假如电子邮件的吸收地点恰好是该SMTP服务程序运转的服务器,那末SMTP服务程序就会将邮件到场邮件数据库中,不然SMTP服务程序将把邮件转发到在其他SMTP服务器上的SMTP服务程序,直到抵达目标地为止。图二经由过程图示申明了这一点。
SMTP能够辨认良多电子邮件用来与SMTP服务程序通信的命令。某些命令必要参数,某些命令则不必要。可是每一个命令后必需跟一个〈CRLF〉。最经常使用的六个命令是HELO,MAIL,RCPT,DATA,RSET和QUIT。
依照下面的按次给出这六个命令并不是偶尔。除RSET外,其他的命令必需依照特定的按次发送,这是由于SMTP服务程序是基于形态的。关于每个创建了双向通信通道的电子邮件程序,SMTP服务程序城市保留以后的通信形态。
当一个电子邮件程序和SMTP服务程序创建接洽后,SMTP服务程序将向电子邮件程序发送初始化动静。该动静包括了一个三位回应码,这个回应码是用来标识SMTP服务程序的。除此以外,在SMTP服务程序发送给电子邮件程序的动静的头部也带有回应码,它们被用来暗示操纵乐成大概失利。电子邮件程序吸收到这些回应码后,能够依据个中包括的信息完成响应的事情。而动静的文本部分是给人看的,电子邮件程序能够疏忽文本部分。
在收到初始化动静后,电子邮件程序经由过程发送HELO命令来入手下手传输邮件。HELO命令有一个参数,该参数标记了SMTP服务程序地点服务器的域名。它将在SMTP服务程序中标识出SMTP服务程序。作为回应,SMTP服务程序举行一些初始化事情,将本人设定到初始形态以吸收电子邮件。当这些事情乐成完成后,它发送回一条乐成的回应动静给电子邮件程序,该回应动静以回应码250开首。
在HELO命令以后,电子邮件程序会发送MAIL命令。MAIL命令将在SMTP服务程序中标识动身送者,它有两个参数:FROM:和一个电子邮件地点。假如SMTP服务程序可以乐成地剖析电子邮件地点的话,一般它将前往以250开首的回应动静;否者将发送回暗示操纵失利的回应动静。
在MAIL以后是RCPT命令。RCPT命令在SMTP服务程序中标识出一个邮件的吸收者,它也有两个参数:TO:和一个电子邮件地点。假如邮件由多个吸收者,则程序必要屡次发送RCPT命令。
RCPT命令以后,程序必要发送电子邮件自己了。程序先发送一个DATA命令,当吸收到暗示乐成的回应动静后,将电子邮件逐行发送给SMTP服务程序,当一切的行都发送终了后,程序发送一行由句号构成的行。在此以后,电子邮件程序守候SMTP服务程序的回应动静,以断定邮件被SMTP服务程序一般吸收了。这统统都乐成后,程序能够发送RSET命令来加入邮件传输历程。最初,当要断开和SMPT服务程序创建的毗连时,程序发送QUIT命令。次要提示的一点是,固然下面的命令都是年夜写的,可是在实践的协定对巨细写不敏感。
如今大概你体贴的成绩是回应码的格局是如何的。最右边的一名数字代表操纵是不是乐成,1代表收到命令,2代表操纵乐成完成,3代表守候后续命令,4代表操纵一时未能完成(电子邮件程序能够在以后的邮件传输过程当中从头发送死令),5代表操纵不克不及完成(电子邮件程序不克不及在以后的邮件传输过程当中从头发送死令)。第二位数字代表回应的范畴,0代表语法毛病,1代表动静哀求,2代表传输通道,3和4没有指定,5代表与邮件体系相干。最有一名数字对第二位数字做增补申明,这里就不再胪陈。依据下面的信息,我们能够看出250代表哀求的命令已乐成完成;220代表SMTP服务程序正在守候HELO命令;而503代表命令按次毛病。有乐趣的伴侣能够拜见RFC2821。
上面供应了一个基于命令行的例子SMTPDemo,这个例子能够匡助你了解基于SMTP的邮件传输机制。这个程序将使用尺度端口25毗连到一个SMTP服务程序上。为了使程序可以运转,你必要将home变动为你利用的邮件服务器的地点。
//SMTPDemo.java
importjava.io.*;
importjava.net.*;
classSMTPDemo
{
publicstaticvoidmain(String[]args)
{
StringSMTPServer="home
intSMTPPort=25;
Socketclient=null;
try
{
//向SMTP服务程序创建一个套接字毗连。
client=newSocket(SMTPServer,SMTPPort);
//创立一个BufferedReader对象,以便从命令行读取用户输出。
BufferedReaderstdin;
stdin=newBufferedReader(newInputStreamReader(System.in));
//创立一个BufferedReader对象,以便从套接字读取输入。
InputStreamis=client.getInputStream();
BufferedReadersockin;
sockin=newBufferedReader(newInputStreamReader(is));
//创立一个PrintWriter对象,以便向套接字写进内容。
OutputStreamos=client.getOutputStream();
PrintWritersockout;
sockout=newPrintWriter(os,true);
//显现同SMTP服务程序的握手历程。
System.out.println("S:"+sockin.readLine());
while(true)
{
System.out.print("C:");
//读取用户输出。
Stringcmd=stdin.readLine();
//将用户输出的命令发送到SMTP服务程序。
sockout.println(cmd);
//从套接字读取SMTP服务程序的回应动静并显现在屏幕上。
Stringreply=sockin.readLine();
System.out.println("S:"+reply);
//假如发送了DATA命令而且取得乐成的回应动静,从输出设备读取行,
//直到读取到完整由句号构成的行时中断,这些行组成了电子邮件。
if(cmd.toLowerCase().startsWith("data")&&
reply.substring(0,3).equals("354"))
{
do
{
cmd=stdin.readLine();
if(cmd!=null&&cmd.length()〉1&&
cmd.charAt(0)== |
|