uSendMail.~pas
上传用户:yjb1804
上传日期:2021-01-30
资源大小:3105k
文件大小:18k
源码类别:

Email服务器

开发平台:

Delphi

  1. unit uSendMail;
  2. interface
  3. uses Classes,SysUtils,Dialogs, windows,IdMessage, IdEmailAddress,IdSMTP,
  4.      IdAttachmentFile, IdText, IdSASL_CRAM_MD5,IdUserPassProvider,Contnrs,objs,
  5.      Messages,syncobjs;
  6. type
  7.   TOnError=procedure (Sender:TObject;ErrMsg:string) of object;
  8.   TDestinationPart = class(TPersistent)
  9.   public
  10.     SendTo : ShortString;
  11.     CCSendTo : ShortString; //抄送
  12.     BccSendTo : ShortString;//暗送
  13.     ReturnAddy: ShortString; //收地址
  14.     Subject : ShortString;
  15.     Body : string;
  16.     Files : TStringList;
  17.     procedure AssignTo(Dest: TPersistent);override;
  18.     constructor Create(aSndTo, aCCSndTo, aBCCSndTo, aRtrnRcptAddy, aSubject, aBody:string; aFiles:TStringList=nil);overload;
  19.     constructor Create; overload;
  20.     destructor destroy; override;
  21.   end;
  22.   TOriginPart = class(TPersistent)
  23.   public
  24.     AuthType : TIdSMTPAuthenticationType;
  25.     FromAddy : string;
  26.     UserName : string;
  27.     Password : string;
  28.     Server : string;
  29.     Port : integer;
  30.     Debug : boolean;
  31.     procedure AssignTo(OriginPart: TPersistent);override;
  32.     constructor Create(aAuthType:TIdSMTPAuthenticationType; aFromAddy, aUserName, aPassword, aServer: string; aPort:integer);overload;
  33.     constructor Create(aUserName, aPassword:string);overload;
  34.     constructor CreateFromFile(fn:string); procedure SaveToFile(fn:string);
  35.   end;
  36.   TMailMessage = class
  37.   public
  38.   private
  39.     Destination : TDestinationPart;
  40.     Origin : TOriginPart;
  41.     SentOk : boolean;
  42.     SentMsg : string;
  43.   public
  44.     constructor Create(Dest:TDestinationPart; Orig:TOriginPart);
  45.     procedure SendNow;
  46.     destructor destroy;override;
  47.   published
  48.     property Success:boolean read SentOk ;
  49.     property ErrorMSG:String  read SentMsg;
  50.   end;
  51.   TBaseThreadMailMessage = class(TThread)
  52.   protected
  53.     FOnSendComplete:TNotifyEvent;
  54.     FOnSendError:TOnError;
  55.     FErrMsg:string;
  56.     
  57.     procedure DoOnComplete; virtual;
  58.     procedure DoOnError; virtual;
  59.   public
  60.     property OnSendComplete:TNotifyEvent read FOnSendComplete write FOnSendComplete;
  61.     property OnSendError:TOnError read FOnSendError write FOnSendError;
  62.   end;
  63.    TThreadMailMessage = class(TBaseThreadMailMessage)
  64.    protected
  65.      MailMsg : TMailMessage;
  66.      procedure Execute; override;
  67.    public
  68.      constructor Create(aDestinationPart:TDestinationPart;aOriginPart:TOriginPart);
  69.    end;
  70.   TMultiThreadMailMessage=class(TBaseThreadMailMessage)
  71.    protected
  72.      FDest:array of  TDestinationPart ;
  73.      FOrig:array of TOriginPart;
  74.      procedure Execute; override;
  75.    public
  76.      constructor Create(const aDestinationPart: array of TDestinationPart;const aOriginPart:array of TOriginPart);
  77.      destructor Destroy;override; 
  78.    end;
  79.    TEmailInfo=Class(TPersistent)
  80.    private
  81.      FSend:TOriginPart;
  82.      FRecv:TDestinationPart;
  83.      FUniqueID:String;
  84.      FIsError:Boolean;
  85.     procedure SetFRecv(const Value: TDestinationPart);
  86.     procedure SetSend(const Value: TOriginPart);
  87.    public
  88.      Constructor Create;
  89.      destructor Destroy; override;
  90.      procedure AssignTo(Dest: TPersistent);override;
  91.      property Send:TOriginPart read FSend write SetSend;
  92.      property Recv:TDestinationPart read FRecv write SetFRecv;
  93.      property Id:string read FUniqueID write FUniqueID;
  94.      property IsError:Boolean read FIsError write FIsError;
  95.    end;
  96.    TEmailInfoList=class(TList)
  97.    protected
  98.      procedure Notify(Ptr: Pointer; Action: TListNotification); Override;
  99.    end;
  100.    TEmailQueue=class(TCustomQueue)
  101.    private
  102.     function GetCount: integer;
  103.    public
  104.      Constructor Create;
  105.      Destructor Destroy; override;
  106.      Procedure Push(Email:TEmailInfo);
  107.      Function Pop:TEmailInfo;
  108.      Function Peek:TEmailInfo;
  109.     property Count:integer Read GetCount ;
  110.    end;
  111.    
  112.    { 使用方法
  113.     1,TEmailSenderMgr.Create;
  114.     2,设置  OnError,OnComplete事件
  115.     3,push一封email
  116.     4,Send
  117.     5,发送完毕释放
  118.    }
  119. Const
  120.    WM_Begin=WM_USER+555;
  121.    WM_OneSendBegin =WM_USER+556;
  122.    WM_OneSendEnd=WM_USER+557;
  123.    WM_Complete=WM_USER+558;
  124. type
  125.   TOnOneSendEnd=procedure(Sender:TObject;Email:TEmailInfo)of object;
  126.   TSendError=procedure (Sender:TObject;Email:TEmailInfo;Msg:String) of Object;
  127.    TEmailSenderMgr=class
  128.    private
  129.      FQueue:TEmailQueue;
  130.      FCS:TCriticalSection;
  131.      FThreadMailMessage:TThreadMailMessage;
  132.      FOnComplete:TNotifyEvent;
  133.      FOnOneSend:TOnOneSendEnd;
  134.      FOneSendEnd:TOnOneSendEnd;
  135.      FIsSending:Boolean;
  136.      FOnError: TSendError;
  137.    protected
  138.      FWindowHandle:THandle;
  139.     procedure MyOnComplete(Sender:TObject);
  140.     procedure WndProc(var Msg: TMessage);
  141.     procedure DoOnError(Sender:TObject;Msg:String);
  142.    public
  143.      Constructor Create;
  144.      Destructor Destroy; override;
  145.      Procedure Push(Email:TEmailInfo);
  146.      Function Pop:TEmailInfo;
  147.      Function Peek:TEmailInfo;
  148.      function HasEmail:Boolean;
  149.      procedure Send;
  150.      property OnComplete:TNotifyEvent read FOnComplete write FOnComplete;
  151.      property OnOneSend:TOnOneSendEnd read FOnOneSend write FOnOneSend;
  152.      property OnOneSendEnd:TOnOneSendEnd read FOneSendEnd write FOneSendEnd;
  153.      property OnSendError:TSendError read FOnError write FOnError;
  154.    end;
  155.  function ActiveMailThreadCount:integer;
  156. implementation
  157. uses uCommon;
  158. var
  159.   ActiveMailThreads:Integer;
  160.   
  161. {TMailMessage}
  162. constructor TMailMessage.Create(Dest:TDestinationPart; Orig:TOriginPart);
  163. begin
  164.   Destination:=TDestinationPart.Create('','','','','','',TStringList.Create);
  165.   if Dest<>nil then
  166.     Destination.Assign(Dest);
  167.   Origin:=TOriginPart.Create(atNone,'','','','',0);
  168.   if Orig<>nil then
  169.     Origin.Assign(Orig);
  170. end;
  171. procedure TMailMessage.SendNow;
  172. var
  173.   MsgSend:TIdMessage;
  174.   SMTP:TIdSMTP;
  175.   ix:integer;
  176.   SASLLogin:TIdSASLCramMd5;
  177.   UserPassProv:TIdUserPassProvider;
  178.   textPart:TIdText;
  179.   //AEmail: TIdEmailAddressItem;
  180. begin
  181.   SentOk:=False;
  182.   SentMsg:='';
  183.   
  184.   MsgSend:=TIdMessage.Create(nil);
  185.   with MsgSend do
  186.   begin
  187.       if (Destination.Files<>nil) AND (Destination.Files.Count>0) then
  188.         contentType:='multipart/alternative';
  189.       From.Text := Origin.FromAddy;
  190.       From.Name:=Origin.UserName;
  191.       Recipients.EMailAddresses := Destination.SendTo;
  192.       Subject := Destination.Subject;
  193.       Priority := mpNormal;
  194.       CCList.EMailAddresses := Destination.CCSendTo;
  195.       BccList.EMailAddresses := Destination.BCCSendTo;
  196.       ReceiptRecipient.Text := Destination.ReturnAddy;
  197.       textPart:=TIdText.Create(MsgSend.MessageParts,nil);
  198.       textPart.ContentType:='text/plain';
  199.       textPart.Body.Add(Destination.Body);
  200.       {textPart:=TIdText.Create(MsgSend.MessageParts,nil);
  201.       textPart.ContentType:='text/plain';
  202.       textPart.Body.Add(Destination.Body); }
  203.       for ix:=0 to Destination.Files.Count-1 do
  204.         TIdAttachmentFile.Create(MsgSend.MessageParts, Destination.Files.Strings[ix]);
  205.       
  206.     try
  207.       SMTP:=TIdSMTP.Create;
  208.       {try
  209.         TIdSSLContext.Create.Free;
  210.         smtp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(smtp);
  211.         smtp.UseTLS := utUseExplicitTLS;
  212.       except
  213.         smtp.IOHandler := TIdIOHandler.MakeDefaultIOHandler(smtp);
  214.         smtp.UseTLS := utNoTLSSupport;
  215.       end;  }
  216.       smtp.ManagedIOHandler := True;
  217.       try
  218.         SMTP.AuthType := Origin.AuthType;
  219.         SMTP.UserName := Origin.UserName; //setup the user name
  220.         SMTP.Password := Origin.Password; //setup the password
  221.         if SMTP.AuthType=atSASL then
  222.         begin
  223.           userPassProv:=TIdUserPassProvider.Create;
  224.           userPassProv.UserName:=SMTP.UserName;
  225.           userPassProv.Password:=SMTP.Password;
  226.           SASLLogin:=TIdSASLCramMd5.Create;
  227.           SASLLogin.UserPassProvider:=userPassProv; // assign the user pass provider to it
  228.           SMTP.SASLMechanisms.Add.SASL:=SASLLogin; // add the SASL login back to the SMTP object
  229.         end;
  230.         SMTP.Host := Origin.Server;
  231.         SMTP.Port := Origin.Port;
  232.         SMTP.Connect;
  233.         if not SMTP.Authenticate then
  234.           raise Exception.Create('发送邮件时发生了错误. 错误原因 : 无法通过认证.');
  235.         try
  236.           try
  237.             SMTP.Send(MsgSend); //send the message
  238.             SentOk:=true;
  239.           finally
  240.             SMTP.Disconnect; //disconnect from the server
  241.           end;
  242.         except
  243.           on E :Exception do
  244.           begin
  245.             SentOk:=false;
  246.             SentMsg:=E.Message;
  247.             raise Exception.Create('发送邮件时发生了错误. 错误原因 : '+E.Message);
  248.           end;
  249.         end;
  250.       finally
  251.         SMTP.Free; //free the memory end;
  252.       end;
  253.     finally
  254.         MsgSend.Free; //free the message
  255.     end;
  256.   end;
  257. end;
  258. destructor TMailMessage.destroy;
  259. begin
  260.   Destination.Free; 
  261.   Origin.Free;
  262. end;
  263. {TDestinationPart}
  264. procedure TDestinationPart.AssignTo(Dest: TPersistent);
  265. begin
  266.   if Dest is TDestinationPart then
  267.   begin
  268.     TDestinationPart(Dest).SendTo:=SendTo;
  269.     TDestinationPart(Dest).CCSendTo:=CCSendTo; //抄送
  270.     TDestinationPart(Dest).BccSendTo:=BccSendTo;//暗送
  271.     TDestinationPart(Dest).ReturnAddy:=ReturnAddy;
  272.     TDestinationPart(Dest).Subject:=Subject;
  273.     TDestinationPart(Dest).Body:=Body;
  274.     TDestinationPart(Dest).Files.Assign(Files);
  275.   end
  276.   else raise Exception.Create('类型不同不能克隆');
  277. end;
  278. constructor TDestinationPart.Create(aSndTo, aCCSndTo, aBCCSndTo, aRtrnRcptAddy, aSubject, aBody:string; aFiles:TStringList);
  279. begin
  280.   SendTo := aSndTo; //send message to, comma separate list for multiple adddesses
  281.   CCSendTo := aCCSndTo; //CC message to
  282.   BccSendTo := aBCCSndTo; //BCC message to
  283.   ReturnAddy:= aRtrnRcptAddy;
  284.   Subject := aSubject; //what's it about
  285.   Body := aBody; //the text, supports HTML or TEXT
  286.   Files:=TStringList.Create; //we must have a list, create if not provided
  287.   if aFiles<>nil then Files.assign(aFiles);
  288. end;
  289. constructor TDestinationPart.Create;
  290. begin
  291.   inherited;
  292.    Files:=TStringList.Create;
  293. end;
  294. destructor TDestinationPart.destroy;
  295. begin
  296.   Files.Free;
  297. end;
  298. {TOriginPart}
  299. procedure TOriginPart.AssignTo(OriginPart: TPersistent);
  300. begin
  301.   if OriginPart is  TOriginPart then
  302.   begin
  303.     TOriginPart(OriginPart).AuthType:=AuthType;
  304.     TOriginPart(OriginPart).FromAddy:=FromAddy ;
  305.     TOriginPart(OriginPart).UserName:=UserName;
  306.     TOriginPart(OriginPart).Password:=Password;
  307.     TOriginPart(OriginPart).Server:=Server ;
  308.     TOriginPart(OriginPart).Port:=Port;
  309.     TOriginPart(OriginPart).Debug:=Debug ;
  310.   end
  311.   else raise Exception.Create('类型不同不能克隆');
  312. end;
  313. constructor TOriginPart.Create(aAuthType:TIdSMTPAuthenticationType; aFromAddy, aUserName, aPassword, aServer: string; aPort:integer);
  314. begin
  315.   AuthType := aAuthType; //options are : 0=satNONE, 1=satDEFAULT, 2=sat
  316.   FromAddy := aFromAddy; //me@mydomain.com
  317.   UserName := aUserName; //me
  318.   Password := aPassword; //mypassword
  319.   Server := aServer; //smtp.mydomain.com
  320.   Port := aPort; //SMTP connection port (25 is default)
  321.   Debug := false; //debugging off/onend;
  322. end;
  323. constructor TOriginPart.Create(aUserName, aPassword: string);
  324. begin
  325.   Create(atDefault,aUserName,aUserName,aPassword,TEMailAddress.SMTPEmailSever(aUserName),25);
  326. end;
  327. constructor TOriginPart.CreateFromFile(fn:string);
  328. begin
  329. end;
  330. procedure TOriginPart.SaveToFile(fn:string);
  331. begin
  332. end;
  333. procedure IncMailThreadCount;
  334. begin
  335.   InterlockedIncrement(ActiveMailThreads);
  336. end;
  337. procedure DecMailThreadCount;
  338. begin
  339.   InterlockedDecrement(ActiveMailThreads);
  340. end;
  341. function ActiveMailThreadCount:integer;
  342. begin
  343.   result:=ActiveMailThreads;
  344. end;
  345. function MailThreadsDone:boolean;
  346. begin
  347.   result:=ActiveMailThreadCount=0;
  348. end;
  349. {TBaseThreadMailMessage}
  350. procedure TBaseThreadMailMessage.DoOnComplete;
  351. begin
  352.   if Assigned(FOnSendComplete) then FOnSendComplete(Self);
  353. end;
  354. procedure TBaseThreadMailMessage.DoOnError;
  355. begin
  356.   if Assigned(FOnSendError) then FOnSendError(Self,FErrMsg);
  357. end;
  358. { TThreadMailMessage }
  359. constructor TThreadMailMessage.Create(aDestinationPart: TDestinationPart;
  360.   aOriginPart: TOriginPart);
  361. begin
  362.   inherited Create(True);
  363.   IncMailThreadCount;
  364.   if aDestinationPart=nil then raise Exception.Create('You must supply a destination');
  365.   if aOriginPart=nil then raise Exception.Create('You must supply an origin');
  366.   FreeOnTerminate:=true;
  367.   MailMsg:=TMailMessage.Create(aDestinationPart, aOriginPart);
  368. end;
  369. procedure TThreadMailMessage.Execute;
  370. begin
  371.   try
  372.     try
  373.       MailMsg.SendNow;
  374.       Synchronize(DoOnComplete);
  375.     finally
  376.       DecMailThreadCount;
  377.     end;
  378.   except
  379.     on E:Exception do
  380.     begin
  381.       FErrMsg:=trim(e.Message);
  382.       Synchronize(DoOnError);
  383.     end;
  384.   end;
  385. end;
  386. { TMultiThreadMailMessage }
  387. constructor TMultiThreadMailMessage.Create(
  388.   const aDestinationPart: array of TDestinationPart;
  389.   const aOriginPart: array of TOriginPart);
  390. var
  391.   I:integer;
  392. begin
  393.   inherited Create(True);
  394.   SetLength(FDest,Length(aDestinationPart));
  395.   //CopyMemory(@FDest[0],@aDestinationPart[0],sizeof(TDestinationPart)*Length(aDestinationPart));
  396.   for I:=0 to Length(aDestinationPart)-1 do
  397.   begin
  398.    FDest[I]:=TDestinationPart.Create;
  399.    FDest[I].Assign(aDestinationPart[I]);
  400.   end;
  401.   SetLength(FOrig,Length(aOriginPart));
  402.   //CopyMemory(@FOrig[0],@aOriginPart[0],sizeof(TOriginPart)*Length(aOriginPart));
  403.   for I:=0 to Length(aOriginPart)-1 do
  404.   begin
  405.    FOrig[I]:=TOriginPart.Create;
  406.    FOrig[I].Assign(aOriginPart[I]);
  407.   end;
  408. end;
  409. destructor TMultiThreadMailMessage.Destroy;
  410. var
  411.   I:integer;
  412. begin
  413.   for I:=0 to Length(FOrig)-1 do
  414.   begin
  415.     FDest[I].Free;
  416.     FOrig[I].Free;
  417.   end;
  418.   inherited;
  419. end;
  420. procedure TMultiThreadMailMessage.Execute;
  421. var
  422.   MailMsg : TMailMessage;
  423.   I:integer;
  424. begin
  425.   try
  426.     for I:=0 to Length(FDest)-1 do
  427.     begin
  428.       MailMsg :=TMailMessage.Create(FDest[I],FOrig[I]);
  429.       try
  430.         try
  431.           MailMsg.SendNow;
  432.         except
  433.           on E:Exception do
  434.           begin
  435.             FErrMsg:=e.Message+#$D#$A'系统忽略该邮件,尝试发送下一封邮件.';
  436.             Synchronize(DoOnError);
  437.             Continue;
  438.           end;
  439.         end;
  440.       finally
  441.         MailMsg.Free;
  442.       end;
  443.     end;
  444.     Synchronize(DoOnComplete);
  445.   except
  446.     on E:Exception do
  447.     begin
  448.       FErrMsg:=e.Message;
  449.       Synchronize(DoOnError);
  450.     end;
  451.   end;
  452. end;
  453. { TEmailQueue }
  454. constructor TEmailQueue.Create;
  455. begin
  456.   Inherited;
  457.   List:=TEmailInfoList.Create;
  458. end;
  459. destructor TEmailQueue.Destroy;
  460. begin
  461.   List.free;
  462.   inherited;
  463. end;
  464. function TEmailQueue.GetCount: integer;
  465. begin
  466.   result:=List.Count;
  467. end;
  468. function TEmailQueue.Peek: TEmailInfo;
  469. begin
  470.   Result := TEmailInfo(inherited Peek);
  471. end;
  472. function TEmailQueue.Pop: TEmailInfo;
  473. begin
  474.   Result := TEmailInfo(inherited Pop);
  475. end;
  476. procedure TEmailQueue.Push(Email: TEmailInfo);
  477. var
  478.   AEmail: TEmailInfo;
  479. begin
  480.   AEmail:=TEmailInfo.Create;   //不用在这里释放
  481.   AEmail.Assign(Email);
  482.   inherited Push(Pointer(AEmail));
  483. end;
  484. { TEmailInfoList }
  485. procedure TEmailInfoList.Notify(Ptr: Pointer; Action: TListNotification);
  486. begin
  487.   case Action of
  488.     lnAdded:;
  489.     lnExtracted:;
  490.     lnDeleted:
  491.       if Ptr<>nil then TEmailInfo(Ptr).Free;
  492.   end;
  493. end;
  494. { TEmailSenderMgr }
  495. constructor TEmailSenderMgr.Create;
  496. begin
  497.   FQueue:=TEmailQueue.Create;
  498.   FCS:=TCriticalSection.Create;
  499.   FThreadMailMessage:=nil;
  500.   FIsSending:=False;
  501.   FWindowHandle := AllocateHWnd(WndProc);
  502. end;
  503. destructor TEmailSenderMgr.Destroy;
  504. begin
  505.   FCS.Leave;
  506.   FCS.Free;
  507.   FQueue.Free;
  508.   CloseHandle(FWindowHandle);
  509.   inherited;
  510. end;
  511. procedure TEmailSenderMgr.DoOnError(Sender: TObject; Msg: String);
  512. begin
  513.   if Assigned(FOnError) then FOnError(self,FQueue.Peek,Msg)
  514. end;
  515. function TEmailSenderMgr.HasEmail: Boolean;
  516. begin
  517.   Result:=FQueue.AtLeast(1);
  518. end;
  519. procedure TEmailSenderMgr.MyOnComplete(Sender: TObject);
  520. begin
  521.   if FQueue.Count=1 then
  522.     SendMessage(FWindowHandle,WM_Complete,0,0)
  523.   else
  524.   begin
  525.     SendMessage(FWindowHandle,WM_OneSendEnd,0,0);
  526.     if Assigned(FOneSendEnd) then FOneSendEnd(Self,FQueue.Peek);
  527.   end;
  528.   FQueue.Pop; //对象释放
  529. end;
  530. function TEmailSenderMgr.Peek: TEmailInfo;
  531. begin
  532.   FCS.Enter;
  533.   Result:=FQueue.Peek;
  534.   FCS.Leave;
  535. end;
  536. function TEmailSenderMgr.Pop: TEmailInfo;
  537. begin
  538.   FCS.Enter;
  539.   Result:=FQueue.Pop;
  540.   FCS.Leave;
  541. end;
  542. procedure TEmailSenderMgr.Push(Email: TEmailInfo);
  543. begin
  544.   FCS.Enter;
  545.   FQueue.Push(Email);
  546.   FCS.Leave;
  547. end;
  548. procedure TEmailSenderMgr.Send;
  549. begin
  550.   SendMessage(FWindowHandle,WM_Begin,0,0);
  551. end;
  552. procedure TEmailSenderMgr.WndProc(var Msg: TMessage);
  553. begin
  554.   case Msg.Msg of
  555.     WM_Begin:
  556.       if HasEmail then
  557.       begin
  558.         if FIsSending=true then exit;
  559.         FIsSending:=true;
  560.         //为什么用peek,因为pop时对象就被释放了
  561.         FThreadMailMessage:=TThreadMailMessage.Create(FQueue.Peek.Recv,FQueue.Peek.Send);
  562.         SendMessage(FWindowHandle,WM_OneSendBegin,0,0);
  563.         FThreadMailMessage.OnSendComplete:=MyOnComplete;
  564.         FThreadMailMessage.OnSendError:=DoOnError;
  565.         FThreadMailMessage.Resume;
  566.       end;
  567.       
  568.     WM_OneSendBegin:
  569.       if Assigned(FOnOneSend)  then FOnOneSend(self,FQueue.Peek);
  570.     WM_OneSendEnd:
  571.     begin
  572.      //为什么用peek,因为pop时对象就被释放了
  573.       FThreadMailMessage:=TThreadMailMessage.Create(FQueue.Peek.Recv,FQueue.Peek.Send);
  574.       FThreadMailMessage.OnSendComplete:=MyOnComplete;
  575.       FThreadMailMessage.OnSendError:=DoOnError;
  576.       FThreadMailMessage.Resume;
  577.     end;
  578.     WM_Complete:
  579.     begin
  580.       FIsSending:=false;
  581.       if Assigned(FOneSendEnd) then FOneSendEnd(Self,FQueue.Peek);
  582.       if Assigned(FOnComplete) then  FOnComplete(self);
  583.     end;
  584.   end;
  585. end;
  586. { TEmailInfo }
  587. procedure TEmailInfo.AssignTo(Dest: TPersistent);
  588. begin
  589.   if Dest is  TEmailInfo then
  590.   begin
  591.     Frecv.AssignTo(TEmailInfo(Dest).Recv);
  592.     FSend.AssignTo(TEmailInfo(Dest).Send);
  593.     TEmailInfo(Dest).IsError:=IsError;
  594.     TEmailInfo(Dest).Id:=id;
  595.   end
  596.   else
  597.   Inherited;
  598. end;
  599. constructor TEmailInfo.Create;
  600. begin
  601.   Frecv:=TDestinationPart.create('','','','','','',nil);
  602.   FSend:=TOriginPart.Create(atSASL,'','','','',25);
  603. end;
  604. destructor TEmailInfo.Destroy;
  605. begin
  606.   if Frecv<>nil then Frecv.Free;
  607.   if FSend<>nil then FSend.Free;
  608.   inherited;
  609. end;
  610. procedure TEmailInfo.SetFRecv(const Value: TDestinationPart);
  611. begin
  612.   FRecv.Assign(Value);
  613. end;
  614. procedure TEmailInfo.SetSend(const Value: TOriginPart);
  615. begin
  616.   FSend.Assign(Value);
  617. end;
  618. end.