请问邮件服务器间是如何进行邮件收发的,有什么协议没?
还有就是有免smtp服务器的发送软件那是如何做到的

解决方案 »

  1.   

    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服务器吧!
      

  2.   

    //窗体上有一个BUTTON控件,一个LABEL控件,一个NMSMTP控件
    //带密码险证的邮件发送程序需要BASE64编码,DecodeBase64和 EncodeBase64
    //为解码和编码函数
    //在263、163和SOHU上都能发送成功
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Psock, NMsmtp, ComCtrls;type
      TForm1 = class(TForm)
        NMSMTP1: TNMSMTP;
        Button1: TButton;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
        procedure NMSMTP1Connect(Sender: TObject);
        procedure NMSMTP1InvalidHost(var Handled: Boolean);
        procedure NMSMTP1ConnectionFailed(Sender: TObject);
        procedure NMSMTP1Status(Sender: TComponent; Status: String);
        procedure NMSMTP1SendStart(Sender: TObject);
        procedure NMSMTP1Success(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    //BaseTable为BASE64码表
    const BaseTable:string='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var
      Form1: TForm1;
      AuthSucc:boolean;// 是否需要密码验证
      function DecodeBase64(Source:string):string; //解码函数
      function FindInTable(CSource:char):integer;  //
      function EncodeBase64(Source:string):string; //编码函数
    implementation{$R *.DFM}
    //
    function FindInTable(CSource:char):integer;
    begin
      result:=Pos(string(CSource),BaseTable)-1;
    end;
    ////
    function DecodeBase64(Source:string):string;
    var
      SrcLen,Times,i:integer;
      x1,x2,x3,x4,xt:byte;
    begin
      result:='';
      SrcLen:=Length(Source);
      Times:=SrcLen div 4;
      for i:=0 to Times-1 do
      begin
        x1:=FindInTable(Source[1+i*4]);
        x2:=FindInTable(Source[2+i*4]);
        x3:=FindInTable(Source[3+i*4]);
        x4:=FindInTable(Source[4+i*4]);
        x1:=x1 shl 2;
        xt:=x2 shr 4;
        x1:=x1 or xt;
        x2:=x2 shl 4;
        result:=result+chr(x1);
        if x3= 64 then break;
        xt:=x3 shr 2;
        x2:=x2 or xt;
        x3:=x3 shl 6;
        result:=result+chr(x2);
        if x4=64 then break;
        x3:=x3 or x4;
        result:=result+chr(x3);
      end;
    end;
    /////
    function EncodeBase64(Source:string):string;
    var
      Times,LenSrc,i:integer;
      x1,x2,x3,x4:char;
      xt:byte;
    begin
      result:='';
      LenSrc:=length(Source);
      if LenSrc mod 3 =0 then Times:=LenSrc div 3
      else Times:=LenSrc div 3 + 1;
      for i:=0 to times-1 do
      begin
        if LenSrc >= (3+i*3) then
        begin
          x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
          xt:=(ord(Source[1+i*3]) shl 4) and 48;
          xt:=xt or (ord(Source[2+i*3]) shr 4);
          x2:=BaseTable[xt+1];
          xt:=(Ord(Source[2+i*3]) shl 2) and 60;
          xt:=xt or (ord(Source[3+i*3]) shr 6);
          x3:=BaseTable[xt+1];
          xt:=(ord(Source[3+i*3]) and 63);
          x4:=BaseTable[xt+1];
        end
        else if LenSrc>=(2+i*3) then
        begin
          x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
          xt:=(ord(Source[1+i*3]) shl 4) and 48;
          xt:=xt or (ord(Source[2+i*3]) shr 4);
          x2:=BaseTable[xt+1];
          xt:=(ord(Source[2+i*3]) shl 2) and 60;
          x3:=BaseTable[xt+1];
          x4:='=';
        end else
        begin
          x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
          xt:=(ord(Source[1+i*3]) shl 4) and 48;
          x2:=BaseTable[xt+1];
          x3:='=';
          x4:='=';
        end;
        result:=result+x1+x2+x3+x4;
      end;
    end;
    //////////
    procedure TForm1.Button1Click(Sender: TObject);
    var MailTo,MailBody:TStringList;
    begin
    Nmsmtp1.Host :='smtp.sohu.com';
    nmsmtp1.Port :=25;
    nmsmtp1.UserID :='linbch';//发信人的用户名,必须是真实的
    nmsmtp1.ReportLevel :=1;
    Nmsmtp1.TimeOut :=10000;
    nmsmtp1.Connect ;    ///连接
    if AuthSucc=true then ////验证成功
    begin
      MailTo:=TStringList.Create;
      MailTo.Add('[email protected]');
      MailBody.Add('Hello it is a test');
      nmsmtp1.PostMessage.FromAddress:='[email protected]'; //发信人的电子邮件地址
      nmsmtp1.PostMessage.ToAddress :=MailTo;
      nmsmtp1.PostMessage.Body:=MailBody;
      nmsmtp1.PostMessage.Subject :='My test';
      Mailto.Clear ;
      //Mailto.Add('c:\a.txt');
      //Mailto.Add('c:\b.txt');
      //nmsmtp1.PostMessage.Attachments:=MailTo; 附件
      MailTo.Free ;
      MailBody.Free;
      nmsmtp1.SendMail;
    end;
    end;
    procedure TForm1.NMSMTP1Connect(Sender: TObject);
    begin
    //////连接成功,下面用户认证过程
      label1.caption:=nmsmtp1.Status;
      if nmsmtp1.ReplyNumber = 250 then
        label1.caption:=nmsmtp1.Transaction('auth login'); //开始认证
      if nmsmtp1.ReplyNumber =334 then //返回值为334,让你输入用BASE64编码后的用户名
        label1.caption:=nmsmtp1.Transaction('YWFhYWE=');// 用户名aaaaa
      if nmsmtp1.ReplyNumber =334 then  // 返回值为334,让你输入用BASE64编码后的用户密码
        label1.caption:=nmsmtp1.Transaction('MTIzNDU2'); //密码为123456
      if nmsmtp1.ReplyNumber =235 then
      begin
        label1.caption:='successful';
        AuthSucc:=true;
      end;
      //showmessage(label1.caption);
    end;procedure TForm1.NMSMTP1InvalidHost(var Handled: Boolean);
    begin
      label1.caption :='Invalid Host';
    end;procedure TForm1.NMSMTP1ConnectionFailed(Sender: TObject);
    begin
    label1.caption :='connect failed';
    end;procedure TForm1.NMSMTP1Status(Sender: TComponent; Status: String);
    begin
      label1.caption :=nmsmtp1.Status ;
    end;procedure TForm1.NMSMTP1SendStart(Sender: TObject);
    begin
      label1.Caption :='start send';
    end;procedure TForm1.NMSMTP1Success(Sender: TObject);
    begin
      label1.Caption:='send success!';
    end;end. 
      

  3.   

    delphi自代tnmpop3和tnmsmtp控件
    unit mail;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Buttons, Menus, NMsmtp, Psock, NMpop3, StdCtrls, ExtCtrls;type
      TFrmMain = class(TForm)
        Label1: TLabel;
        Bevel1: TBevel;
        lb: TListBox;
        nmp: TNMPOP3;
        nms: TNMSMTP;
        PopupMenu1: TPopupMenu;
        ReadMail1: TMenuItem;
        SendMail1: TMenuItem;
        DeleteMail1: TMenuItem;
        ReplyMail1: TMenuItem;
        Forward1: TMenuItem;
        Bevel2: TBevel;
        SpeedButton5: TSpeedButton;
        SpeedButton1: TSpeedButton;
        SpeedButton3: TSpeedButton;
        SpeedButton4: TSpeedButton;
        SpeedButton2: TSpeedButton;
        procedure SpeedButton1Click(Sender: TObject);
        procedure SpeedButton2Click(Sender: TObject);
        procedure SpeedButton3Click(Sender: TObject);
        procedure SpeedButton4Click(Sender: TObject);
        procedure SpeedButton5Click(Sender: TObject);
        procedure DeleteMail1Click(Sender: TObject);
        procedure ReplyMail1Click(Sender: TObject);
        procedure Forward1Click(Sender: TObject);
        procedure nmpAuthenticationFailed(var Handled: Boolean);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure emailyaz;
        procedure listemail;
        procedure readmail(number:integer);
        procedure refreshmails;
      end;var
      FrmMain: TFrmMain;implementation{$R *.DFM}
    uses config, umread, usend;procedure TFrmMain.SpeedButton1Click(Sender: TObject);
    begin
      configure.showmodal;
    end;procedure TFrmMain.SpeedButton2Click(Sender: TObject);
    begin
      frmmain.nmp.connect;
      frmmain.listemail;
    end;procedure TFrmMain.SpeedButton3Click(Sender: TObject);
    begin
     readmail(lb.itemindex+1);
     frmread.showmodal;
    end;procedure TFrmMain.SpeedButton4Click(Sender: TObject);
    begin
     frmsend.eto.text:='';
     frmsend.ecc.text:='';
     frmsend.ebcc.text:='';
     frmsend.esubject.text:='';
     frmsend.Mmessage.text:='';
     frmsend.lattach.Items.clear;
     frmsend.showmodal;
    end;procedure TFrmMain.SpeedButton5Click(Sender: TObject);
    begin
      close;
    end;procedure tfrmmain.emailyaz;
    var
     i:integer;
     str:string;
    begin
     lb.items.clear;
       for i:=1 to nmp.mailcount do
     begin
      str:='';
      nmp.getsummary(i);
       str:=nmp.summary.from+'    '+nmp.summary.subject;
      lb.items.add(str);
     end;
    end;procedure tfrmmain.listemail;
    var
     y:string;
    begin
     screen.cursor:=crhourglass;
      label1.caption:='Please wait for listing emails';
      if nmp.Connected then
       begin
        emailyaz;
        label1.caption:=inttostr(nmp.mailcount)+' Email listed..'
       end
      else label1.caption:='Connection terminated.. Please try again.';
     screen.cursor:=crdefault;
    end;procedure tfrmmain.readmail(number:integer);
    begin
     screen.cursor:=crhourglass;
     nmp.GetMailMessage(number);
     frmread.efrom.Text := NMP.MailMessage.From;
     frmread.esubject.Text := NMP.MailMessage.Subject;
     frmread.mheader.Lines.Assign(NMP.MailMessage.Head);
     frmread.mbody.Lines.Assign(NMP.MailMessage.Body);
     If NMP.MailMessage.Attachments.Text <> '' then
        frmread.lattach.items.assign(nmp.MailMessage.Attachments);
     frmread.mno.caption:=inttostr(number);
     screen.cursor:=crdefault;
    end;procedure tfrmmain.refreshmails;
    VAR
     S:STRING;
     OLDC,NEWC:INTEGER;
    begin
      S:=Label1.CAPTION;
      delete(S,1,pos('-',S)+1);
      OLDC:=NMP.MAILCOUNT;
      nmp.disconnect;
      nmp.connect;
      NEWC:=NMP.MAILCOUNT;
      SHOWMESSAGE(INTTOSTR(NEWC));
    end;procedure TFrmMain.DeleteMail1Click(Sender: TObject);
    begin
    if  Messagedlg('Delete Mail? Are you sure?',mtconfirmation,[mbok,mbcancel],0)=mrok then
                           nmp.DeleteMailMessage(lb.itemindex+1);
    end;procedure TFrmMain.ReplyMail1Click(Sender: TObject);
    begin
      screen.cursor:=crhourglass;
      nmp.getsummary(lb.itemindex+1);
      frmsend.eto.Text:=copy(nmp.summary.from,
                        pos('<',nmp.summary.from)+1,
                        length(nmp.summary.from)-(pos('<',nmp.summary.from)+1));
      frmsend.ecc.text:='';
      frmsend.ebcc.text:='';
      frmsend.esubject.text:='';
      frmsend.Mmessage.text:='';
      frmsend.lattach.Items.clear;
      screen.Cursor:=crdefault;
      frmsend.showmodal;
    end;procedure TFrmMain.Forward1Click(Sender: TObject);
    var
     i:integer;
     k:string;
    begin
     screen.cursor:=crhourglass;
     nmp.GetMailMessage(lb.itemindex+1);
     frmsend.esubject.Text := NMP.MailMessage.Subject;
     frmsend.mmessage.Lines.Assign(NMP.MailMessage.Body);
     If NMP.MailMessage.Attachments.Text <> '' then
        for i:=0 to nmp.mailmessage.attachments.count-1 do
          frmsend.lattach.items.add(k+'\'+nmp.MailMessage.Attachments[i]);
      frmsend.eto.text:='';
      frmsend.ecc.text:='';
      frmsend.ebcc.text:='';
      screen.Cursor:=crdefault;
      frmsend.showmodal;
    end;procedure TFrmMain.nmpAuthenticationFailed(var Handled: Boolean);
    begin
     configure.showmodal;
    end;procedure TFrmMain.FormCreate(Sender: TObject);
    beginend;end.
      

  4.   

    unit config;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;type
      TConfigure = class(TForm)
        Label1: TLabel;
        Edit1: TEdit;
        Label2: TLabel;
        Edit2: TEdit;
        Label3: TLabel;
        Edit3: TEdit;
        Label4: TLabel;
        Edit4: TEdit;
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Configure: TConfigure;implementationuses mail;{$R *.DFM}procedure TConfigure.Button1Click(Sender: TObject);
    begin
     FrmMain.nmp.host:=Edit1.Text;
     FrmMain.nmp.Port:=strtoint(Edit2.text);
     FrmMain.nmp.UserID:=Edit3.text;
     FrmMain.nmp.Password:=Edit4.text;
     close;
    end;procedure TConfigure.Button2Click(Sender: TObject);
    begin
     close;
    end;end.
    ///////////////////////////////
    unit umread;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Grids, StdCtrls, Buttons, OleCtnrs, Menus,inifiles;type
      Tfrmread = class(TForm)
        efrom: TEdit;
        Label1: TLabel;
        Label2: TLabel;
        mheader: TMemo;
        esubject: TEdit;
        mbody: TMemo;
        Label3: TLabel;
        Label4: TLabel;
        SpeedButton1: TSpeedButton;
        SpeedButton2: TSpeedButton;
        SpeedButton3: TSpeedButton;
        Label5: TLabel;
        mno: TLabel;
        lattach: TListBox;
        oc: TOleContainer;
        MainMenu1: TMainMenu;
        Reply1: TMenuItem;
        Forward1: TMenuItem;
        Exit1: TMenuItem;
        Delete1: TMenuItem;
        procedure SpeedButton2Click(Sender: TObject);
        procedure SpeedButton1Click(Sender: TObject);
        procedure SpeedButton3Click(Sender: TObject);
        procedure lattachDblClick(Sender: TObject);
        procedure Exit1Click(Sender: TObject);
        procedure Reply1Click(Sender: TObject);
        procedure Forward1Click(Sender: TObject);
        procedure Delete1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
      procedure temizle;
        { Public declarations }
      end;var
      frmread: Tfrmread;implementationuses mail,usend;{$R *.DFM}procedure tfrmread.temizle;
    begin
     efrom.text:='';
     esubject.text:='';
     mheader.text:='';
     mbody.text:='';
     lattach.items.clear;
    end;
    procedure Tfrmread.SpeedButton2Click(Sender: TObject);
    begin
    if frmmain.nmp.mailcount > strtoint(mno.caption) then
     begin
       temizle;
       frmmain.readmail(strtoint(mno.caption)+1);
     end;
    end;procedure Tfrmread.SpeedButton1Click(Sender: TObject);
    begin
    if mno.caption<>'1' then
       begin
        temizle;
        frmmain.readmail(strtoint(mno.caption)-1);
       end;
    end;procedure Tfrmread.SpeedButton3Click(Sender: TObject);
    begin
     close;
    end;procedure Tfrmread.lattachDblClick(Sender: TObject);
    var
     pcr:Tinifile;
     e:string;
    begin
     pcr:=Tinifile.Create('mail.ini');
     e:=pcr.Readstring('General','Attachpath',e);
     oc.createlinktofile(e+'\'+lattach.Items.Strings[lattach.ItemIndex],false);
     oc.DoVerb(ovshow);
     pcr.free;
    end;procedure Tfrmread.Exit1Click(Sender: TObject);
    begin
     close;
    end;procedure Tfrmread.Reply1Click(Sender: TObject);
    begin
    screen.cursor:=crhourglass;
      frmsend.eto.Text:=copy(efrom.text,
                        pos('<',efrom.text)+1,
                        length(efrom.text)-(pos('<',efrom.text)+1));  frmsend.ecc.text:='';
      frmsend.ebcc.text:='';
      frmsend.esubject.text:='';
      frmsend.Mmessage.text:='';
      frmsend.lattach.Items.clear;
      screen.Cursor:=crdefault;
      frmsend.showmodal;
    end;procedure Tfrmread.Forward1Click(Sender: TObject);
    var
     i:integer;
     tk:tinifile;
     k:string;
    begin
     screen.cursor:=crhourglass;
     tk:=tinifile.create('HamitEmail.ini');
      k:=tk.readstring('General','Attachpath',k);
     tk.free;
     frmsend.esubject.Text := esubject.text;
     frmsend.mmessage.Lines.Assign(mbody.lines);
     If lattach.items.count<>0  then
        for i:=0 to lattach.items.count-1 do
          frmsend.lattach.items.add(k+'\'+lattach.items[i]);
      frmsend.eto.text:='';
      frmsend.ecc.text:='';
      frmsend.ebcc.text:='';
      screen.Cursor:=crdefault;
      frmsend.showmodal;
    end;procedure Tfrmread.Delete1Click(Sender: TObject);
    begin
     frmmain.nmp.DeleteMailMessage(strtoint(mno.caption));
    if frmmain.nmp.mailcount > strtoint(mno.caption) then
     begin
       temizle;
       frmmain.readmail(strtoint(mno.caption)+1);
     end
    else if mno.caption<>'1' then
       begin
        temizle;
        frmmain.readmail(strtoint(mno.caption)-1);
       end;
    end;
    end.
      

  5.   

    unit usend;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Buttons, ExtCtrls,inifiles, Menus;type
      Tfrmsend = class(TForm)
        Label1: TLabel;
        Label2: TLabel;
        Label3: TLabel;
        Label4: TLabel;
        Label5: TLabel;
        Mmessage: TMemo;
        eto: TEdit;
        ecc: TEdit;
        ebcc: TEdit;
        esubject: TEdit;
        SpeedButton5: TSpeedButton;
        SpeedButton1: TSpeedButton;
        lattach: TListBox;
        SpeedButton3: TSpeedButton;
        Bevel1: TBevel;
        Bevel2: TBevel;
        Bevel3: TBevel;
        op: TOpenDialog;
        PopupMenu1: TPopupMenu;
        Remove1: TMenuItem;
        procedure SpeedButton3Click(Sender: TObject);
        procedure SpeedButton1Click(Sender: TObject);
        procedure Remove1Click(Sender: TObject);
        procedure SpeedButton5Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      frmsend: Tfrmsend;implementationuses mail;{$R *.DFM}procedure Tfrmsend.SpeedButton3Click(Sender: TObject);
    begin
     if op.execute then
      lattach.items.add(op.filename);
    end;procedure Tfrmsend.SpeedButton1Click(Sender: TObject);
    var
     kp,tk:Tinifile;
     h,u,p:string;
    begin
    screen.cursor:=crhourglass;
    if not frmmain.nms.Connected then
      begin
         tk:=Tinifile.create('mail.ini');
         p:=tk.ReadString('General','DefaultConn',p);
         h:=tk.ReadString(p,'Host',h);
         u:=tk.ReadString(p,'Username',u);
         frmmain.nms.host:=h;
         frmmain.nms.UserID:=u;
         frmmain.nms.connect;
         tk.free;
         if not frmmain.nms.connected then
              showmessage('Connection Problem');
      end; kp:=Tinifile.create('mail.ini');
      frmmain.NMs.PostMessage.FromAddress :=kp.readstring(p,'Email','');
      frmmain.NMs.PostMessage.FromName := kp.readstring(p,'Name','');
      frmmain.NMs.PostMessage.Subject := Esubject.text;
      frmmain.NMs.PostMessage.ToAddress.Add(eto.Text);
      frmmain.NMs.PostMessage.ToBlindCarbonCopy.Add(Ebcc.Text);
      frmmain.NMs.PostMessage.ToCarbonCopy.Add(Ecc.Text);
      frmmain.NMs.PostMessage.Attachments.AddStrings(Lattach.Items);
      frmmain.NMs.PostMessage.Body.Assign(mMessage.Lines);
      kp.free;
      frmmain.NMs.SendMail;
     screen.cursor:=crdefault;
      close;
    end;procedure Tfrmsend.Remove1Click(Sender: TObject);
    begin
      lattach.Items.Delete(Lattach.ItemIndex);
    end;procedure Tfrmsend.SpeedButton5Click(Sender: TObject);
    begin
     close;
    end;end.
    不知道你的邮箱要不就发过去了。
    累死我了
    一个很完整的收发邮箱软件!