说起Java有些人可能会想到一些用于修饰主页的Applet例如着名的水光倒影Lakeclass等其实这些Applet只是Java应用的很小一个方面作为一种新兴的网络语言Java用于编写基于TCP/IP的应用才算用到了点子上在编写TCP/IP的应用方面Java是我所用过的编程语言中最简洁最快速的本文将讨论如何用Java来编写可根据SMTP和POP协议来收发Email的Java Applet
一Java网络编程初步
建立TCP/IP连接
Socket类中的构造函数Socket(String hostint port)用于创建一个Socket并与指定的主机(host)及端口(port)连接由于受到Java Applet安全机制的限制主机名不可以任意指定而应和被调用的Applet所在主机的名字相同因此可先由GetCodeBase方法取得浏览器当前读取的CLASS文件所在的URL再通过GetHost方法从该URL返回用字符串表示的该主机的名称例如从~caveman/这个URL中可以返回用字符串表示的主机名
关于标准端口地址的值一般是SMTP为POP为FTP为等当然也有的主机用的是非标准的端口在使用之前最好先确定一下
数据的发送与接收
使用Socket类中的GetOutputStream方法可以取得与当前Socket对应的输出数据流用DataOutputStream类中的WriteBytes方法可以逐个字符地将数据写入到输出数据流中
使用Socket类中的GetInputStream方法可以取得与当前Socket对应的输入数据流用DataInputStream类中的ReadLine方法可以逐行地读取输入数据流中的数据
关闭TCP/IP连接
可以用Socket类中的close方法来关闭TCP/IP连接
二基于SMTP协议发送Email的Java Applet
SMTP协议和服务器
SMTP(Simple Mail Transfer Protocol)协议是目前网上流行的发送Email的协议SMTP协议共有条命令不过发一封Email只需用如下条命令就足够了(见表)
表
命 令 功 能
HELO <SP> <domain> <CRLF> 与SMTP服务器握手传送本机域名
MAIL <SP> FROM<reversepath> <CRLF>传送发信者的信箱名称
RCPT <SP> TO<forwardpath> <CRLF> 传送接收者的信箱名称
DATA <CRLF> 发送信件数据(包括信头和信体)
QUIT <CRLF> 退出与SMTP服务器的连接
除了ISP提供的SMTP服务器以外国内一些存放免费个人主页的服务器的SMTP端口也是打开的如果该服务器对外来的Email没有增加RELAY限制(例如网易就有此限制)那么也可以把它当作SMTP服务器来用如等在这些服务器上放一个下面要编的Java Applet和调用它的htm文件用户就可以实现在线发送Email了
SMTPtesterjava中的主要程序
该Java Applet用了三个文本条(TextField)部件tftf和tf它们分别用来供用户输入发信者的信箱名称接收者的信箱名称和信件的标题还用了两个文本区(TextArea)部件ta和tata供用户输入信体内容ta用来显示Smtp服务器的应答信息和出错信息等当然还用了一个按钮(Button)部件bu用户输入正确的信息后用鼠标点击一下它信件就可以被发出去了
事件捕获处理程序见程序
public boolean handleEvent(Event event)
{
if ((eventtarget != bu) || (eventid != ))
/*如果不是按钮bu被鼠标按下*/
{
return false
}
if (!((tfgetText()length() == ) || (tfgetText()length() == )))
/*如果发信者和收信人的信箱名称都填好了执行发信程序Burun*/
{ budisable()
burun()
return true
}
taappendText(Please give me enough information to send your email!\n)
return true
}
(程序)
发送Email程序burun见程序
public void burun()
{
try
{
Socket socket= new Socket(getCodeBase()getHost())
/*建立与smtp服务器的连接*/
DataOutputStream dataout= new DataOutputStream(socketgetOutputStream())
DataInputStream dataIn= new DataInputStream(socketgetInputStream())
GetReply(dataIn)
dataoutwriteBytes(HELO \r\n)
/*开始按SMTP协议发信*/
GetReply(dataIn)
dataoutwriteBytes(MAIL FROM + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(RCPT TO + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(DATA\r\n)
GetReply(dataIn)
dataoutwriteBytes(From + tfgetText() + \r\n)
dataoutwriteBytes(To + tfgetText() + \r\n)
dataoutwriteBytes(Subject+tfgetText()+\n\n+tagetText()+\r\n\r\n)
GetReply(dataIn)
dataoutwriteBytes(QUIT\r\n)
GetReply(dataIn)
socketclose()
/*退出连接*/
buenable()
return
}
catch (javaioIOException IOException) /*捕获IO错误*/
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
接收服务器应答程序GetReply见程序
void GetReply(DataInputStream dataIn)
{
String string
string=
try
{
string= dataInreadLine()
taappendText(string + \n)
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
实例运行
在~caveman上已经放了编译好的SMTPtesterclass和调用它的图是该Applet在运行时的画面这时这封信已被发往了!
图
三基于POP协议读取E_mail的Java Applet
POP协议和服务器
POP(Post Office Protocol version )是一种常用的网络协议用于从远程服务器的信箱里收取E_mail它的常用命令根据连接时的不同状态有
()授权状态(AUTHORIZATION state)
User<SP><name><CRLF> 用户名
Pass<SP><string><CRLF> 用户密码
Quit<CRLF> 退出
()执行状态(TRANSACTION state)
STAT<CRLF> 信箱状态即信箱内共有几封信总共大小(进制表示)等
LIST<SP><msg><CRLF> 不用msg参数时显示每封信的大小列表用msg参数时显示编号为msg的信件的长度(进制表示)
TOP<SP><msg><SP><n><CRLF> 取编号为msg的信件的信头(head)和部分信体(body)n=时只取信头n≠时取信头和信体的前n行该命令为可选命令有些POP服务器软件不支持它
RETR<SP><msg><CRLF> 读取编号为msg的信件
DELE<SP><msg><CRLF> 删编号为msg的信件其实只是作个标记真正删除要到更新状态
()更新状态(UPDATE state)
QUIT<CRLF> 退出并把做过DELE标记的邮件删掉
另外还有NOOPLASTRSETRPOP等命令用得较少
与SMTP服务器的情况相似除了ISP提供的POP服务器外国内的一些存放免费个人主页的服务器也提供POP服务(例如网易)用户在获得免费主页的同时也可以得到一个POP信箱例如我的信箱为在服务器上放一个下面要编写的Applet和调用它的htm文件在线运行它输入正确的用户名和密码后就可以读取Email了
POPtesterjava中的主要程序
该Java Applet共用了三个文本条(TextField)部件tftf和tf它们分别用来供用户输入用户名密码和要读取的Email的编号(为时只取信箱状态不读信)还用了一个文本区(TextArea)部件ta用来显示POP服务器的应答信息信件内容和出错信息等当然还用了一个按钮(Button)部件bu用户输入正确的信息后用鼠标点击一下它就可以读取指定的信件了
事件捕获处理程序与SMTPtester中的一样读取Email程序burun见程序
public void burun()
{
try
{
Socket socket= new Socket(getCodeBase()getHost() )
/*连接POP服务器*/
DataOutputStream dataout= new DataOutputStream(socketgetOutputStream())
DataInputStream dataIn= new DataInputStream(socketgetInputStream())
GetReply(dataIn)
dataoutwriteBytes(USER + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(PASS + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(STAT\r\n)
/*信箱状态*/
GetReply(dataIn)
dataoutwriteBytes(LIST\r\n)
/*信件长度列表*/
GetReply(dataIn)
taappendText(\n)
if (tfgetText()equals() == false)
{
dataoutwriteBytes(RETR + tfgetText() + \r\n)
/*读取指定信件*/
GetReply(dataIn)
taappendText(\n)
}
dataoutwriteBytes(QUIT\r\n)
GetReply(dataIn)
socketclose()
buenable()
return
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
接收服务器应答程序GetReply和GetReply见程序
void GetReply(DataInputStream dataIn)
{
String string
string=
try
{
for (string=dataInreadLine()
(stringequals()=false)
string=dataInreadLine())
/*List和Retr命令的应答虽然有多行但都用一句作为结束可据此取应答信息*/
{
taappendText(string + \n)
}
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
读取单句应答的程序GetReply和SMTPtester中的相同因为在与POP服务器对话时List和Retr的应答不只一句因此又编了一个GetReply程序来处理这个问题
实例运行
在~caveman上已经放了编译好的POPtesterclass和调用它的l图是该Applet运行时的画面刚才在上用SMTPtester发出的那封信已到了我网易的信箱里了
四程序的改进
以上两个Java Applet还很不完善在加强错误捕获对邮件附件的支持等方面需要改进的地方还很多另外根据上面提到的一些基本方法只需稍加变化还可以用Java来实现其他网络协议如FTPNEWS等