www.pudn.com > MailServer.rar > cMain.pas


unit cMain; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, Sockets, ScktComp, KsSkinEngine, se_controls, 
  KsSkinForms, ksskinstdcontrol, ActnList, KsSkinItems, Menus, KsSkinMenus, 
  ExtCtrls, KsSkinButtons, KsSkinLabels, KsSkinGroupBoxs, DataSet, ComCtrls, 
  ksskinmessages; 
type 
  SessionState = (stInit, stAuthorization, stTransaction, stUpdate ); 
  PMailList = ^AMailList; 
  AMailList = record 
    UserName, PassWord,Domain,Power,Size,MailBoxPath: string; //用户名和密码 
    SessionState: SessionState; //会话状态 
    MailFrom: string[65]; //发送者 
    RcptTo: Tstrings; //SMTP发送时为接收者表,限制由自己定 
                      //POP收信时为删除标记,-表示已作删除标记,+表示未作删除标记 
                      //index=0的项为总信件数(字符型数字) 
    Data: string; //邮件内容 
    SockHandle: integer; //会话使用的soket句柄,用于区分是那一个会话的标记 
    P: TextFile; //读写文件的指针 
    success: Boolean; //整个过程是否正常结束 
  end; 
  function CheckUser(UserName:string):boolean; 
  function CheckPass(UserName,UserPass:string;var MailRecord:PMailList):boolean; 
type 
  TfrmMain = class(TForm) 
    SeSkinForm1: TSeSkinForm; 
    SeSkinPopupMenu1: TSeSkinPopupMenu; 
    CustomItem1: TSeSkinItem; 
    CustomItem2: TSeSkinItem; 
    CustomItem3: TSeSkinItem; 
    CustomItem4: TSeSkinItem; 
    actList: TActionList; 
    actviewlog: TAction; 
    actsetup: TAction; 
    actclose: TAction; 
    Image1: TImage; 
    GroupBox1: TSeSkinGroupBox; 
    lbl_company: TSeSkinLabel; 
    Label2: TSeSkinLabel; 
    btnClose: TSeSkinButton; 
    mnuSkin: TSeSkinItem; 
    SeSkinEngine1: TSeSkinEngine; 
    actAbout: TAction; 
    CustomItem5: TSeSkinItem; 
    SeMsg: TSeSkinMessage; 
    sckSmtp: TServerSocket; 
    sckPop3: TServerSocket; 
    lbl_jcompany: TSeSkinLabel; 
    procedure sckSmtpListen(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckSmtpAccept(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckSmtpClientConnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckSmtpClientRead(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure sckSmtpClientDisconnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckPop3Accept(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckPop3ClientConnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckPop3ClientDisconnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckPop3Listen(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure sckPop3ClientRead(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure outmsg(instr:string); 
    procedure actcloseExecute(Sender: TObject); 
    procedure actviewlogExecute(Sender: TObject); 
    procedure btnCloseClick(Sender: TObject); 
    procedure sckSmtpClientError(Sender: TObject; 
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
      var ErrorCode: Integer); 
    procedure sckPop3ClientError(Sender: TObject; 
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
      var ErrorCode: Integer); 
    procedure AppException(Sender: TObject; E: Exception); 
    procedure SkinClick(Sender: TObject); 
    procedure actAboutExecute(Sender: TObject); 
    procedure actsetupExecute(Sender: TObject); 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  SkinFile:string; 
  end; 
//SMTP接收处理类 
type 
  TSMTPEngin = class(TThread) 
  private 
    socket: TCustomWinSocket; 
    text: string; 
  protected 
    procedure execute; override; 
    function SaveMail(Socket: TCustomWinSocket): boolean; 
    procedure SMTPMailEngin; 
  end; 
//POP3接收处理类 
type 
  TPOP3Engin = class(TThread) 
  private 
    socket: TCustomWinSocket; 
    text: string; 
  protected 
    procedure execute; override; 
    procedure POP3MailEngin; 
  end; 
 
var 
  frmMain: TfrmMain; 
  SMTPList: TList; 
  POP3List: TList; 
  root :string; 
implementation 
 
uses Functions, cLog, ADODB_TLB, Utility, cSet; 
 
{$R *.dfm} 
 
////////////////////////////////////////////邮件接收/处理线程类开始////////////////////////////////////// 
//SMTP类 
 
procedure TSMTPEngin.execute; 
begin 
  synchronize(SMTPMailEngin); 
end; 
 
procedure TSMTPEngin.SMTPMailEngin; 
var 
  i: integer; 
  MailRecord: PMailList; 
  sendecho:string; 
begin 
  Text := socket.ReceiveText; 
  //查找相应记录 
  MailRecord := nil; 
  for i := 0 to SMTPList.Count - 1 do 
  begin 
    MailRecord := SMTPList.Items[i]; 
    if MailRecord.SockHandle = socket.SocketHandle then 
      break; 
  end; 
 
  case MailRecord.SessionState of 
    stInit: 
      begin 
        text := trim(DeleteSubString(text, CRLF, -1, False)); 
        if (pos('HELO', uppercase(text)) = 1) or (pos('EHLO', uppercase(text)) = 1) then 
        begin 
          MailRecord.SessionState := stAuthorization; //状态改为验证会话状态 
          sendecho:='250-SMTP server ready' + CRLF; 
          sendecho:=sendecho+'250-AUTH LOGIN' + CRLF; 
          sendecho:=sendecho+'250 8BITMIME' + CRLF; 
        end 
        else 
          sendecho:='500 cmd line invalidate' + CRLF; 
      end; 
    stAuthorization: 
      begin 
        text := trim(DeleteSubString(text, CRLF, -1, False)); 
        if uppercase(text) = 'AUTH LOGIN' then 
          sendecho:='334 VXNlcm5hbWU6' + CRLF 
        else if MailRecord.UserName = '' then 
        begin 
          if CheckUser(DecodeBase64(text)) then 
          //if DirectoryExists(DecodeBase64(text)) then //检查是否有相应的邮箱路径,检查是否是合法用户 
          begin 
            MailRecord.UserName := DecodeBase64(text); //存入用户名 
            sendecho:='334 UGFzc3dvcmQ6'+ CRLF; 
          end 
          else 
            sendecho:='555 AUTH LOGIN failed,invalid User' + CRLF; //不是合法用户 
        end 
        else if (MailRecord.PassWord = '') and (text <> '') then 
        begin 
          if CheckPass(MailRecord.UserName,DecodeBase64(text),MailRecord) then 
          //if text = MailRecord.UserName then //根据用户名找到相应的密码并比较认证,这里让它等于用户名 
          begin 
            MailRecord.PassWord := DecodeBase64(text); 
            MailRecord.SessionState := stTransaction; //通过验证,会话进入stTransaction传输状态 
            sendecho:='235 ' + text + CRLF; 
          end 
          else 
            sendecho:='535 AUTH LOGIN failed,PassWord Error' + MailRecord.UserName + CRLF 
        end 
        else if text <> '' then 
          sendecho:='500 cmd line invalidate ' + CRLF; 
      end; 
    stTransaction: 
      begin 
        if pos('MAIL FROM:', uppercase(text)) = 1 then 
        begin 
          MailRecord.MailFrom := trim(copy(text, 11, length(text) - 10)); 
          sendecho:='250 RCPT TO to enter receiver(s)' + CRLF; 
        end 
        else if pos('RCPT TO:', uppercase(text)) = 1 then //接收者 
        begin 
          if MailRecord.RcptTo.Count < 10 then //最大一次可转发人数为9,共发给10人(这里可以自己定制) 
          begin 
            MailRecord.RcptTo.Add(trim(copy(text, 9, length(text) - 8))); 
            sendecho:='250 receiver(s) ' + trim(copy(text, 9, length(text) - 8)) + ' accepted' + CRLF; 
          end 
          else 
            sendecho:='502 receiver(s) overload, Max is 10' + CRLF; 
        end 
        else if UpperCase(text) = 'DATA' + CRLF then 
        begin 
          if MailRecord.RcptTo.Count > 0 then //检测接收者是否为空 
            sendecho:='354 Start mail input; end with .' + CRLF 
          else 
            sendecho:='502 receiver buffer empty' + CRLF; 
        end 
        else if pos(CRLF + '.' + CRLF, text) > 0 then //结束邮件内容 
        begin 
          MailRecord.Data := MailRecord.Data + copy(text, 0, Pos(CRLF + '.' + CRLF, text) - 1); 
          text:=''; 
          MailRecord.success := True; 
          if SaveMail(socket) then 
            sendecho:='250 message accepted' + CRLF 
          else 
            sendecho:='500 write message failed' + CRLF; 
        end 
        else if UpperCase(text) = 'QUIT' + CRLF then //结束会话,进入更新状态 
        begin 
          MailRecord.SessionState := stUpdate; 
          sendecho:='250 bye' + CRLF; 
        end 
        else if pos('RSET', uppercase(text)) = 1 then 
        begin 
          MailRecord.success := False; 
          sendecho:='250 SMTP server have reset OK' + CRLF; 
        end 
        else 
          begin 
          MailRecord.Data := MailRecord.Data + text; 
          text:=''; 
          end; 
      end; 
    stUpdate: 
      begin 
        sendecho:='250 Session Close' + CRLF; 
        socket.Close; 
      end; 
  else 
    sendecho:='500 cmd line invalidate' + CRLF; 
  end; //end of case; 
  if sendecho<>'' then 
    begin 
    socket.SendText(sendecho); 
    frmMain.outmsg(sendecho); 
    end; 
  if text<>'' then frmMain.outmsg(text+CRLF); 
  sleep(50); 
  if MailRecord.SessionState = stUpdate then socket.Close; 
 
end; 
 
procedure TfrmMain.outmsg(instr:string); 
begin 
  FrmLog.AddMsg(inStr); 
end; 
 
function TSMTPEngin.SaveMail(Socket: TCustomWinSocket): boolean; 
var 
  i, j: integer; 
  MailRecord: PMailList; 
  recever, filename: string; 
  root:string; 
begin 
  result := true; 
  root:=ExtractFilePath(Application.ExeName); 
  for i := 0 to SMTPList.Count - 1 do 
  begin 
    MailRecord := SMTPList.Items[i]; 
    if MailRecord.SockHandle = socket.SocketHandle then 
    begin 
      if MailRecord.success then //如果接收正常,就分发邮件 
      begin 
        try 
          for j := 0 to MailRecord.RcptTo.Count - 1 do 
          begin 
            recever := MailRecord.RcptTo.Strings[j]; 
            recever := copy(recever, pos('<', recever) + 1, pos('>', recever) - pos('<', recever) - 1); //得到<>内的邮件地址 
            recever := trim(copy(recever, 1, pos('@', recever) - 1)); //得到用户名 
 
            MailRecord.MailBoxPath := root + 'Domain\' + MailRecord.Domain + '\' + recever + '\'; //邮箱路径 
            ForceDirectories(MailRecord.MailBoxPath); 
            SetCurrentDir(MailRecord.MailBoxPath); 
            filename := getuserid; //产生一个20位数字文件名,也作为它的邮件独立-ID表 
            assignfile(MailRecord.P,filename+'.txt'); 
            rewrite(MailRecord.P); //建立邮件文件 
            write(MailRecord.P, 'S'+CRLF+MailRecord.Data);  
            closefile(MailRecord.P); 
            assignfile(MailRecord.P,'index.txt'); 
            if fileExists('index.txt') then 
              append(MailRecord.P) //如果存在索引,追加记录 
            else 
              rewrite(MailRecord.P); //建立索引文件 
            writeln(MailRecord.P, '+' + filename); //写内容,+号位是删除标记位,表示未删除 
            Flush(MailRecord.P); 
            closefile(MailRecord.P); 
            SetCurrentDir(root); 
          end; 
        except 
          result := false; 
        end; 
      end; 
      MailRecord.success := False; 
      MailRecord.UserName := ''; 
      MailRecord.PassWord := ''; 
      MailRecord.MailFrom := ''; 
      MailRecord.RcptTo.Clear; 
      break; 
    end; 
  end; 
end; 
 
function CheckPass(UserName,UserPass:string;var MailRecord:PMailList): boolean; 
var 
  tRs:TRecordSet; 
  lsql:string; 
  ErrText:string; 
begin 
  Result:=false; 
  lsql:='select * from MailUser where 1=1 ' 
    + ' and UserName='''+CorrectStr(UserName)+'''' 
    + ' and UserPass='''+CorrectStr(UserPass)+''''; 
  tRs:=MailDataSet.GetData(lsql,ErrText); 
  if not tRs.EOF then 
  begin 
    MailRecord.UserName:=UserName; 
    MailRecord.PassWord:=UserPass; 
    if SDomain then 
      MailRecord.Domain:='local' 
    else 
      MailRecord.Domain:=tRs.Fields['Domain'].Value; 
    MailRecord.Power:=tRs.Fields['Power'].Value; 
    MailRecord.Size:=tRs.Fields['Size'].Value; 
    Result:=true; 
  end; 
end; 
 
function CheckUser(UserName:string): boolean; 
var 
  tRs:TRecordSet; 
  lsql:string; 
  ErrText:string; 
begin 
  Result:=false; 
  lsql:='select * from MailUser where UserName='''+CorrectStr(UserName)+''''; 
  tRs:=MailDataSet.GetData(lsql,ErrText); 
  if not tRs.EOF then 
    Result:=true; 
end; 
 
//POP3类 
 
procedure TPOP3Engin.execute; 
begin 
  synchronize(POP3MailEngin); 
end; 
 
procedure TPOP3Engin.POP3MailEngin; 
var 
  i, totalmailbytes: integer; 
  MailRecord: PMailList; 
  sendecho: string; 
  readmailbody: Tstrings; 
  tUserName,tUserPass:string; 
  tmpFile:string; 
begin 
  totalmailbytes := 0; 
  if not socket.Connected then exit; 
  Text := socket.ReceiveText; 
  //查找相应记录 
  MailRecord := nil; 
  for i := 0 to POP3List.Count - 1 do 
  begin 
    MailRecord := POP3List.Items[i]; 
    if MailRecord.SockHandle = socket.SocketHandle then 
      break; 
  end; 
 
  case MailRecord.SessionState of 
    stInit: 
      begin //验证是否有此邮箱名 
text := trim(DeleteSubString(text, CRLF, -1, False)); 
if pos('USER', uppercase(text)) = 1 then 
begin 
  tUserName := trim(copy(text, 6, length(text) - 5)); 
  if CheckUser(tUserName) then //是否存在用户 
  begin 
    MailRecord.SessionState := stAuthorization; //状态改为验证会话状态 
    MailRecord.UserName := tUserName; //记录用户名 
    sendecho:='+OK ' + tUserName + ' mailbox accepted' + CRLF 
  end 
  else 
    sendecho:='-ERR sorry, no mailbox for ' + tUserName + ' here' + CRLF; 
end 
else 
  if UpperCase(text) = 'QUIT' then 
    sendecho:='+OK POP3 server signing off' + CRLF 
  else 
    sendecho:='-ERR cmd line invalidate' + CRLF; 
      end; 
    stAuthorization: //验证密码 
      begin 
        text := trim(DeleteSubString(text, CRLF, -1, False)); 
        if pos('PASS', uppercase(text)) = 1 then 
        begin 
          tUserPass := trim(copy(text, 6, length(text) - 5)); 
 
          if CheckPass(MailRecord.UserName,tUserPass,MailRecord) then //验证密码是否正确 
          begin 
            MailRecord.MailBoxPath := root + 'Domain\' + MailRecord.Domain + '\' + MailRecord.UserName + '\'; //邮箱路径 
            ForceDirectories(MailRecord.MailBoxPath); 
            if not fileExists(MailRecord.MailBoxPath+'index.txt') then 
              FileClose(FileCreate(MailRecord.MailBoxPath+'index.txt')); 
            SetCurrentDir(root); 
            MailRecord.SessionState := stTransaction; //状态改为传输会话状态 
            MailRecord.PassWord := tUserPass; 
            sendecho:='+OK you are welcome' + CRLF 
          end 
          else 
            sendecho:='-ERR sorry,LOGIN failed,PassWord Error' + CRLF; 
        end 
        else 
          if UpperCase(text) = 'QUIT' then 
            sendecho:='+OK POP3 server signing off' + CRLF 
          else 
            sendecho:='-ERR cmd line invalidate' + CRLF; 
      end; 
    stTransaction: 
      begin 
        text := trim(DeleteSubString(text, CRLF, -1, False)); 
        if uppercase(text) = 'STAT' then 
        begin 
          //处理邮件列表 
          MailRecord.RcptTo.LoadFromFile(MailRecord.MailBoxPath + 'index.txt'); 
          for i := 0 to MailRecord.RcptTo.Count - 1 do 
            totalmailbytes := totalmailbytes + getfilesize(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i], 2, length(MailRecord.RcptTo.Strings[i]) - 1) + '.txt'); 
          sendecho:='+OK ' + inttostr(MailRecord.RcptTo.Count) + ' ' + InttoStr(totalmailbytes) + CRLF; 
        end 
        else 
          if uppercase(text) = 'UIDL' then //列所有邮件独立-ID表(由0x21到0x7E字符组成,这个符号在给定的存储邮件中不会重复) 
          begin 
            sendecho:='+OK' + CRLF; 
            for i := 0 to MailRecord.RcptTo.Count - 1 do 
              sendecho:=sendecho+inttostr(i + 1) + ' ' + copy(MailRecord.RcptTo.Strings[i], 2, length(MailRecord.RcptTo.Strings[i]) - 1) + CRLF; 
            sendecho:=sendecho+'.' + CRLF; 
          end 
          else 
            if pos('UIDL', uppercase(text)) = 1 then //列指定邮件独立-ID表 
            begin 
              i := strtoint(copy(text, 5, length(text) - 4)); 
              if i <= MailRecord.RcptTo.Count then 
                sendecho:='+OK ' + inttostr(i) + ' ' + copy(MailRecord.RcptTo.Strings[i - 1], 2, length(MailRecord.RcptTo.Strings[i - 1]) - 1) + CRLF 
              else 
                sendecho:='-ERR no such message found' + CRLF; 
            end 
            else 
              if uppercase(text) = 'LIST' then //列所有邮件 
              begin 
                for i := 0 to MailRecord.RcptTo.Count - 1 do 
                  totalmailbytes := totalmailbytes + getfilesize(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i], 2, length(MailRecord.RcptTo.Strings[i]) - 1) + '.txt'); 
                sendecho:='+OK ' + inttostr(MailRecord.RcptTo.Count) + ' messages (' + InttoStr(totalmailbytes) + ' bytes)' + CRLF; 
                for i := 0 to MailRecord.RcptTo.Count - 1 do 
                  sendecho:=sendecho+inttostr(i + 1) + ' ' + Inttostr(getfilesize(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i], 2, length(MailRecord.RcptTo.Strings[i]) - 1) + '.txt')) + CRLF; 
                sendecho:=sendecho+'.' + CRLF; 
              end 
              else 
                if pos('LIST', uppercase(text)) = 1 then //列指定邮件 
                begin 
                  i := strtoint(copy(text, 5, length(text) - 4)); 
                  if i <= MailRecord.RcptTo.Count then 
                    sendecho:='+OK ' + inttostr(i) + ' ' + InttoStr(getfilesize(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i - 1], 2, length(MailRecord.RcptTo.Strings[i - 1]) - 1) + '.txt')) + CRLF 
                  else 
                    sendecho:='-ERR no such message found' + CRLF; 
                end 
                else 
                  if pos('RETR', uppercase(text)) = 1 then 
                  begin 
                    i := strtoint(copy(text, 5, length(text) - 4)); 
                    if i <= MailRecord.RcptTo.Count then 
                      begin 
                      sendecho:='+OK ' + Inttostr(getfilesize(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i - 1], 2, length(MailRecord.RcptTo.Strings[i - 1]) - 1) + '.txt')) + ' bytes' + CRLF; 
                      readmailbody:=TStringList.Create; 
                      tmpFile:=MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[i - 1], 2, length(MailRecord.RcptTo.Strings[i - 1]) - 1) + '.txt'; 
                      readmailbody.LoadFromFile(tmpFile); 
                      socket.SendText(sendecho+readmailbody.Text+CRLF+ '.' + CRLF); 
                      sendecho:=''; 
                      readmailbody.Free; 
                      end 
                    else 
                      sendecho:='-ERR no such message found' + CRLF; 
                  end 
                  else 
                    if pos('DELE', uppercase(text)) = 1 then 
                    begin 
                      i := strtoint(copy(text, 5, length(text) - 4)); 
                      if i <= MailRecord.RcptTo.Count then 
                      begin 
                        MailRecord.RcptTo.Strings[i - 1] := replacing(MailRecord.RcptTo.Strings[i - 1], '+', '-', 1); 
                        sendecho:='+OK message ' + copy(text, 5, length(text) - 4) + ' deleted' + CRLF; 
                      end 
                      else 
                        sendecho:='-ERR no such message found' + CRLF; 
                    end 
                    else 
                      if uppercase(text) = 'QUIT' then 
                      begin 
                        MailRecord.SessionState := stUpdate; //状态改为结束会话状态 
                        MailRecord.success := True; 
                        sendecho:='+OK POP3 server signing off (maildrop empty)' + CRLF; 
                      end 
                      else 
                        if uppercase(text) = 'NOOP' then 
                          sendecho:='+OK POP3 server ready' + CRLF 
                        else 
                          if uppercase(text) = 'RSET' then 
                          begin 
                            for i := 0 to MailRecord.RcptTo.Count - 1 do 
                              MailRecord.RcptTo.Strings[i] := replacing(MailRecord.RcptTo.Strings[i], '-', '+', 1); 
                            sendecho:='+OK maildrop has ' + inttostr(MailRecord.RcptTo.Count) + ' messages'; 
                          end; 
      end; 
    stUpdate: 
      begin 
        sendecho:='+OK POP3 server signing off' + CRLF; 
        socket.Close; 
      end; 
  else 
    sendecho:='500-cmd line invalidate' + CRLF; 
  end; //end of case; 
  if sendecho<>'' then 
    begin 
    socket.SendText(sendecho); 
    frmMain.outmsg(sendecho); 
    end; 
  frmMain.outmsg(text+CRLF); 
  sleep(50); 
  if MailRecord.SessionState = stUpdate then  socket.Close; 
end; 
 
////////////////////////////////////////////邮件接收/处理线程类结束////////////////////////////////////// 
 
 
procedure TfrmMain.sckSmtpListen(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  outmsg('SMTP Socket(' + inttostr(socket.SocketHandle)+') 开始侦听.......'); 
end; 
 
procedure TfrmMain.sckSmtpAccept(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  MailRecord: PMailList; 
begin 
  outmsg('SMTP Socket(' + inttostr(socket.SocketHandle)+ ') ' + '已接受'+Socket.RemoteHost+'连接'); 
  outmsg('220 SMTP server ready' + CRLF); 
  Socket.SendText('220 SMTP server ready' + CRLF); 
  MailRecord := New(PMailList); 
  MailRecord.SockHandle := Socket.SocketHandle; 
  MailRecord.SessionState := stInit; 
  MailRecord.success := False; 
  MailRecord.RcptTo := Tstringlist.Create; 
  MailRecord.UserName := ''; 
  MailRecord.PassWord := ''; 
  MailRecord.MailFrom := ''; 
  SMTPList.Add(MailRecord); 
end; 
 
procedure TfrmMain.sckSmtpClientConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  outmsg('SMTP Socket(' + inttostr(socket.SocketHandle)+ ') ' + '与' + Socket.RemoteHost + '连接成功!'); 
end; 
 
procedure TfrmMain.sckSmtpClientRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  th: TSMTPEngin; 
begin 
  th := TSMTPEngin.Create(True); 
  th.FreeOnTerminate := true; 
  th.socket := socket; 
  th.Resume; 
end; 
 
procedure TfrmMain.FormCreate(Sender: TObject); 
var 
  tCitem:TSeSkinItem; 
  tmpList:Tstrings; 
  tmpi,tmpj:integer; 
  tmpSkin:string; 
  connstr:string; 
begin 
  connstr:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source="' 
    + ExtractFilePath(Application.ExeName)+'database\MailDB.mdb";Persist Security Info=False'; 
  MailDataSet:=TdataSet.Create; 
  MailDataSet.OpenDb(connstr); 
  Company:=rGetValue('Company','奇易'); 
  LCompany:=rGetValue('LCompany','上海奇易科技'); 
  Application.Title:=Company+'邮件服务器'; 
  SDomain:=true; 
  lbl_company.Caption:=LCompany; 
  Jcompany:=CorrectStr(rGetValue('JCompany','(c)'+lCompany),'|'); 
  //mo_jcompany.text:=CorrectStr(jcompany,'|'); 
  lbl_jcompany.Caption:=Jcompany; 
   
  Self.Caption:=Application.Title; 
  SMTPList := TList.Create; 
  POP3List := TList.Create; 
  root := ExtractFilePath(Application.ExeName); 
  if not Assigned(FrmLog) then 
    FrmLog := TfrmLog.Create(Application); 
 
  Application.OnException := AppException; 
 
  tmpSkin:=rGetValue('SkinFile',''); 
  tmplist:=SearchFile; 
  for tmpj:=0 to SeSkinPopupMenu1.Items.count -1 do 
    if SeSkinPopupMenu1.Items[tmpj].Name='mnuSkin' then break; 
 
  if tmplist<>nil then 
    begin 
      for tmpi:=0 to tmplist.count-1 do 
      begin 
        tCitem:=TSeSkinItem.Create(SeSkinPopupMenu1.Items[tmpj]); 
        tCitem.OnClick:=SkinClick; 
        tCitem.Caption:=copy(tmplist[tmpi],1,length(tmplist[tmpi])-5); 
        SeSkinPopupMenu1.Items[tmpj].Add(tCitem); 
        if tmpSkin='' then tmpSkin:=tCitem.Caption; 
      end; 
 
      for tmpi:=0 to mnuSkin.Count-1 do 
        if lowercase(tmpSkin)=lowercase(mnuSkin.Items[tmpi].Caption) then 
           mnuSkin.Items[tmpi].Checked:=true; 
    end; 
  SkinFile:=ExtractFilePath(Application.ExeName)+'skins\' + tmpSkin +'.mskn'; 
 
  sckSmtp.Port:=25; 
  sckPop3.Port:=110; 
  sckSmtp.Open; 
  sckPop3.Open; 
end; 
 
procedure TfrmMain.FormDestroy(Sender: TObject); 
begin 
  SMTPList.Free; 
  POP3List.Free; 
end; 
 
procedure TfrmMain.sckSmtpClientDisconnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  i: integer; 
  MailRecord: PMailList; 
begin 
  for i := 0 to SMTPList.Count - 1 do 
  begin 
    MailRecord := SMTPList.Items[i]; 
    if MailRecord.SockHandle = socket.SocketHandle then 
    begin 
      MailRecord.RcptTo.Free; 
      Dispose(MailRecord); 
      SMTPList.Delete(i); 
      break; 
    end; 
  end; 
  outmsg('SMTP Socket(' + inttostr(socket.SocketHandle)+')与'+socket.RemoteHost + '断开连接'); 
end; 
 
procedure TfrmMain.sckPop3Accept(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  MailRecord: PMailList; 
begin 
  outmsg('SMTP Socket(' + inttostr(socket.SocketHandle)+ ') ' + '已接受'+Socket.RemoteHost+'连接'); 
  outmsg('+OK POP3 server ready' + CRLF); 
  Socket.SendText('+OK POP3 server ready' + CRLF); 
  MailRecord := New(PMailList); 
  MailRecord.SockHandle := Socket.SocketHandle; 
  MailRecord.SessionState := stInit; 
  MailRecord.success := False; 
  MailRecord.RcptTo := Tstringlist.Create; 
  MailRecord.UserName := ''; 
  MailRecord.PassWord := ''; 
  MailRecord.MailFrom := ''; 
  POP3List.Add(MailRecord); 
end; 
 
procedure TfrmMain.sckPop3ClientConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  outmsg('POP3 Socket(' + inttostr(socket.SocketHandle)+ ') ' + '与' + Socket.RemoteHost + '连接成功!'); 
end; 
 
procedure TfrmMain.sckPop3ClientDisconnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  i, j: integer; 
  MailRecord: PMailList; 
begin 
  for i := 0 to POP3List.Count - 1 do 
  begin 
    MailRecord := POP3List.Items[i]; 
    if MailRecord.SockHandle = socket.SocketHandle then 
    begin 
      if MailRecord.success then //如果接收正常,删除作了标记的邮件 
      begin 
        for j := MailRecord.RcptTo.Count - 1 downto 0 do 
          if pos('-', MailRecord.RcptTo.Strings[j]) = 1 then 
            begin 
            deletefile(MailRecord.MailBoxPath + copy(MailRecord.RcptTo.Strings[j], 2, length(MailRecord.RcptTo.Strings[j]) - 1) + '.txt'); 
            MailRecord.RcptTo.Delete(j); 
            end; 
        MailRecord.RcptTo.SaveToFile(MailRecord.MailBoxPath + 'index.txt'); //存未删除的索引 
      end; 
      MailRecord.RcptTo.Free; 
      Dispose(MailRecord); 
      POP3List.Delete(i); 
      break; 
    end; 
  end; 
  outmsg('POP3 Socket(' + inttostr(socket.SocketHandle)+')与'+socket.RemoteHost + '断开连接'); 
 
end; 
 
procedure TfrmMain.sckPop3Listen(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  outmsg('POP3 Socket(' + inttostr(socket.SocketHandle)+') 开始侦听.......'); 
end; 
 
procedure TfrmMain.sckPop3ClientRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  th: TPOP3Engin; 
begin 
  th := TPOP3Engin.Create(True); 
  th.FreeOnTerminate := true; 
  th.socket := socket; 
  th.Resume; 
end; 
 
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
 sckSmtp.Close; 
 sckPop3.Close; 
end; 
 
procedure TfrmMain.actcloseExecute(Sender: TObject); 
begin 
  close; 
end; 
 
procedure TfrmMain.actviewlogExecute(Sender: TObject); 
begin 
  actviewlog.Checked := not actviewlog.Checked; 
  if actviewlog.Checked then 
    frmlog.Show 
  else 
    frmlog.Hide ; 
 
end; 
 
procedure TfrmMain.btnCloseClick(Sender: TObject); 
begin 
 self.SeSkinForm1.MinToTray; 
end; 
 
procedure TfrmMain.sckSmtpClientError(Sender: TObject; 
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
  var ErrorCode: Integer); 
begin 
  showmessage(inttostr(errorcode)); 
end; 
 
procedure TfrmMain.sckPop3ClientError(Sender: TObject; 
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
  var ErrorCode: Integer); 
begin 
  showmessage(inttostr(errorcode)); 
end; 
 
procedure TfrmMain.AppException(Sender: TObject; E: Exception); 
begin 
  showmessage(e.Message); 
end; 
 
procedure TfrmMain.SkinClick(Sender: TObject); 
var 
  tmpi:integer; 
begin 
SkinFile:=ExtractFilePath(Application.ExeName)+'skins\' + lowercase(TSeSkinItem(Sender).Caption) +'.mskn'; 
  frmMain.SeSkinEngine1.SkinFile:=SkinFile; 
  for tmpi:=0 to mnuSkin.Count -1 do 
    mnuSkin.items[tmpi].checked:=false; 
 
  TSeSkinItem(Sender).Checked:=true; 
  rPutValue('SkinFile',TSeSkinItem(Sender).Caption); 
end; 
 
procedure TfrmMain.actAboutExecute(Sender: TObject); 
begin 
   frmMain.Show; 
   if frmMain.SeSkinForm1.WindowState = kwsTray then //kwsNormal 
     frmMain.SeSkinForm1.MinToTray; 
end; 
 
procedure TfrmMain.actsetupExecute(Sender: TObject); 
begin 
  frmSet.show; 
end; 
 
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
   CanClose:=false; 
   if self.SeMsg.MessageDlg('确认退出?     ',mtConfirmation,[mbYes, mbNo],0)=mrYes then CanClose:=True; 
end; 
 
end.