Fastnet页中NMPOP3(收)和NMSMTP(发)

解决方案 »

  1.   

    另外,你可以从delphi安装目录的demos中找到很多实际的相关例子
      

  2.   

    你可以到 www.ntbar.com 去下载一个邮件服务器, 地址是 www.ntbar.com/oa/setup.exe ,这是我写的,邮件用access数据库保存,当然,也可以采用文件形式保存,支持POP3,SMTP,多线程还有什么问题可以写信给我,[email protected]
      

  3.   

    基实我要的并不是一个单纯的邮件服务器,所以现成我对我并不太合适。除非哪位愿意提供原码给我:)。其实我要的功能很简单,只要可以把客户发过来的邮件收过来/把客户的邮件通过我的邮件服务器转发出去,在通过我的邮件服务器的时候,数据会经过一些处理:)。
    我想用delphi6-indyserver-TIDIMap4Server来做服务器不知是否可行?
    请高手关注一下,小弟万分感谢。
      

  4.   

    难道这里的人都跟我一样,不会用indy系列的控件吗?大家帮帮我吧,
      

  5.   

    use exchang2000 ,all question will resolved!
      

  6.   

    难道非要用indy系列的控件吗?
      

  7.   


                           Email 服务器的简单实现      贵刊1999年7月26日《编程技巧》栏目刊登的《监视POP3信箱》一文介绍了直接调用WinSock函数来进行POP3网络通信从而监视有无新邮件的方法。但我们知道从Delphi 3 开始,它自带的控件中有基于Internet开发的控件。如果我们充分利用这些控件开发Internet程序则可以简化编程工作,提高效率。鉴于目前POP3客户端的软件的种类繁多,(如Outlook Express,Foxmail 以及Web 方式下的各免费邮局),而服务器端(除Unix Email系统)很少公开原代码,下面我就向大家着重介绍一下利用 Delphi 4中Internet控件组的TClientSocket 和TServerSocket 控件来实现 Email POP3服务器端。如果您理解了Email POP3服务器的构造,相信也可以依葫芦画瓢写出Email SMTP服务器程序。在此基础上加入多线程技术使服务器能同时处理多个客户的连接请求,您就可以轻松地实现一个简单的Email服务器了。 一. 设计思路     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服务器吧!
      

  8.   

    to:zhangking(张庆)
      谢谢,这个文件我手头上也有,我阅读了RFC1939已经可以完成一部分功能了,但是在响应RETR N(收某一封邮件)的时候,数据不能正确传给邮件的各个部分。
    以下是我的响应命令,大家看看:
      ConSocket.SendText('+OK size '+inttostr(Mailsize)+' octets'+crlf);
      ConSocket.SendText(+Form1.pop3mail.HFrom+' '+CRLF);
      ConSocket.SendText(+Form1.pop3mail.HSubject+' '+CRLF);
      ConSocket.SendText(+Form1.pop3mail.HText+' '+CRLF);
      ConSocket.SendText('.'+CRLF);
    本来我的意思是分别传送邮件来源、邮件主题、邮件内容。但是在客户端看收到的信息(以上我响应的)全在内容域里,其它域为空。 我想知道要怎么响应,客户端的各个域才会有正确的信息呢??
      
      

  9.   

    Procedure TFileServerThread.ClientExecute;
    Var
        Data: Array[0..1023] Of char;
        RecText: String;
        SocketStream: TWinSocketStream;    pop:TPop3;
    Begin    pop:=TPop3.Create(nil);    While Not Terminated And ClientSocket.Connected Do
        Try
            SocketStream := TWinSocketStream.Create(ClientSocket, 30000);
            Try
                FillChar(Data, SizeOf(Data), 0);
                if SocketStream.WaitForData(60000) then
                begin
                      RecText:=ClientSocket.ReceiveText();
                      if (RecText) = '' then
                      begin
                        pop.Dotimeout();
                        sleep(1);
                        ClientSocket.Close;
                        Terminate;
                      end
                      else
                        pop.ParseCommand(RecText);
                end
                else
                begin
                        pop.Dotimeout();
                        sleep(1);
                        ClientSocket.Close;
                        Terminate;            end;          If ClientSocket.Connected Then
              Begin
                ClientSocket.SendText(RecText);
              End;
            Finally
                SocketStream.Free;
            End;
        Except
            HandleException;    End;
    End;这样做可以吗?
    做在TFileServerThread.ClientExecute里!