关于超想
本站导航
邮件列表
  首页 | 本站产品 | Delphi资料 | 免费资源 | 程序人生 | 软件工程 | 网站设计 | 推荐网站
你所在的位置 -> 主页 -> 超想软件 -> 编程资料 -> delphi -> 开发技巧 -> 网络通讯 ->详细
相关内容  
 
 
在程序运行期设置QUERY控件的PARAMS
 
【新品推荐】

  详细内容
 

Email 服务器的简单实现
作者: 评价: 上站日期: 2001-05-09
内容说明:
来源:

  一. 设计思路 

Email 系统采用C/S 结构。当用户想发送邮件时或收取邮件时在客户机上运行任意一个客户端程序,如Foxmail。在菜单’工具-> 选项’的邮件服务器里填上运行我们服务器程序的主机名。服务器主机24小时一直运行我们的服务器端程序,SMTP和POP3服务器程序分别在25端口和110端口侦听连接请求。当用户发信时,首先客户端会与服务器端建立Socket连接。然后开始一应一答的Client/Server间的通信。发信和收信时建立连接后服务器端分别要发送一个’250 OK’ 和’+OK pop3 server is ready ’的应答。客户端收到此应答后开始发送SMTP或POP3命令。POP3通信时一般最开始的命令是’user ‘和’pass’或’ apop’用以进行身份验证。注意由于POP3会话有3个状态,某些命令只在某特定状态下有效。当用户进行完所有的操作后发送一个’quit’命令。服务器端收到此命令即终止此次socket连接并继续侦听其他的连接请求。注意:POP3通信时客户端在Transaction状态下’quit’则进入update状态。如果从Authorization状态下’quit’则终止通信,而不进入Update状态。如果客户端不通过’quit’命令终止连接,POP3会话不会进入Update状态。而只有在Update状态下收到’quit’命令后服务器才会在断连前把标志为已删的邮件进行物理删除。 

二. 代码实现(以POP3为例) 

自定义TPOP类的描述: 

SessionState = ( Init,Authorization, Transaction,Update);
TPop=class (TComponent)
 public
   UserName:string;//Email帐户名
   PassWord:string; //Email口令
   ReceText:Pchar; //server端收到的字符串
   PopState:SessionState; 
//pop状态:
init or authorization or transaction or update
   MsgCount:integer; //邮件总数
   SizeCount:integer; //邮件总大小
   ReplyString:string;//服务器端发送的应答信息
   DeleIndex:byte;//用户要删的邮件序号
   ListIndex:byte;//list方法 的参数:
用户要列出的序号为listindex的邮件信息
   RetrIndex:byte;//retr方法的参数:
用户要取序号为retrindex的邮件
   TopIndex:byte; //top方法的参数
   QuitFlag:boolean;//用户如果通过quit命断连则此变量为true;
反之(此时要把f_dele都置回0)
   OldMsgCount:integer;//旧邮件数:Last 命令返回
   //邮件头的各个域 
   HMsgId:string;
   HReplyTo:string;
   HDate:string;
   HFrom:string;
   HTo:string;
   HSubject:string;
   HMIME_Ver:real;
   HContent_Type:string;
   HContent_Transfer_Encoding:string;
   HText:string;
  //所有POP3服务器必须支持的命令
  procedure user;
  function pass:boolean;
  procedure stat;
  procedure dele;
  procedure list;
  procedure retr;
  procedure noop;
  procedure rset;
  procedure aquit;
  procedure tquit;
  //扩展的可选择实现的POP3 命令
  procedure top;
  procedure last;
  procedure apop;
  procedure uidl;
  end;
1. 建立连接 

我们可以看到利用了Tclientsocket后客户端请求建立连接只需下面的代码。 

with ClientSocket do
   begin
    Host := Server;
    Active := True;
   end;
服务器端利用TserverSocket,一直在侦听110端口,若客户端有连接请求,则ServerSocketAccept事件会被激活,建立起连接。 

procedure TMyForm.ServerSocketAccept(Sender: TObject;
 Socket: TCustomWinSocket);
begin
  Statusbar1.Panels[0].Text :=
  '连接到 ' + Socket.RemoteAddress;
 //pop对象初始化
 pop:=TPop.Create(nil);
 pop.PopState:=init;
 pop.LoginResult:=false;
 pop.QuitFlag:=false;
 ServerSocket.Socket.Connections[0]
 .sendtext('+OK ibonc pop3 server is ready'+crlf);

end;
2. 通信 

服务器端收到客户端发来的信息,则会激活ServerSocketClientRead事件,通过ServerSocket的Socket.ReceiveText可以得到信息的内容。 

procedure TMyForm.ServerSocketClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var temp_command :string; 
//存放接收到的命令行,并做去crlf的处理
begin
temp_command:=Socket.ReceiveText;
//to remove the crlf in command line
temp_command:=trim(copy(temp_command,1,
pos(crlf,temp_command)-1));  
pop.ReceText:=pchar(temp_command);
if pop.popstate=init then
  if strLIComp(pop.ReceText,'user ',5)=0 then
    pop.user
  else
    ServerSocket.Socket.Connections[0]
.sendtext('-ERR user name please')
else if pop.popstate=authorization then
  begin
     if strLIComp(pop.ReceText,'pass ',5)=0 then
        pop.pass 
     else if strIComp(pop.ReceText,'quit')=0 then
        pop.aquit
       else
        ServerSocket.Socket.Connections[0]
.sendtext('-ERR pass word please');
  end
else if pop.popstate=transaction then
   begin
     if strIComp(pop.ReceText,'stat')=0 then
       pop.stat  
     else if strLIComp(pop.ReceText,'dele ',5)=0 then
       pop.dele
     else if strLIComp(pop.ReceText,'list',4)=0 then
       pop.list
     else if strLIComp(pop.ReceText,'retr ',5)=0 then
       pop.retr
     else if strIComp(pop.ReceText,'noop')=0 then
       pop.noop
     else if strIComp(pop.ReceText,'rset')=0 then
       pop.rset
     else if strIComp(pop.ReceText,'quit')=0 then
       pop.tquit
     else if strIComp(pop.ReceText,'last')=0 then
       pop.last
     else if strLIComp(pop.ReceText, 'apop ',5)=0 then
       pop.apop
     else if strLIComp(pop.ReceText, 'uidl ',5)=0 then
       pop.uidl
     else
       ServerSocket.socket.connections[0]
.sendtext('-ERR no such command yet'+crlf);
     end
end;
3. 关闭连接 

  procedure TMyForm.ServerSocket
ClientDisconnect(Sender: TObject;
    Socket: TCustomWinSocket);
  begin
   ServerSocket.Active := False;
   //如果client端没有通过quit 命令断连,
   则在断连时要把那些f_dele置为0
   if pop.QuitFlag=False then
    begin
     MyForm.query11.Close;
     MyForm.query11.Params[0].Asstring:=pop.UserName;
     MyForm.query11.prepare;
     MyForm.query11.execsql;
    end;
  end;
三. 结语 

由于Email系统与数据库表结构的紧密联系,笔者没有写出各POP3命令的具体实现。相信读者在认真阅读了RFC1939之后不难写出实现函数。现在就动手为你的公司写一个自己的Email服务器吧! 

 


 
你所在的位置 -> 主页 -> 超想软件 -> 编程资料 -> delphi -> 开发技巧 -> 网络通讯 ->详细
  首页 | 本站产品 | Delphi资料 | 免费资源 | 程序人生 | 软件工程 | 网站设计 | 推荐网站
声明:本站内容除注明原创以外均从网上摘抄,如有侵权请指明。
  如果您对我们的网站有什么意见或者建议,请与我们联系
powered by 建站易上手- V2.0