NMpop3.pas
上传用户:szzdds
上传日期:2013-09-18
资源大小:293k
文件大小:28k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit NMpop3;
  2. {$X+}
  3. {$R-}
  4. {$IFDEF VER100}
  5. {$DEFINE NMF3}
  6. {$ENDIF}
  7. {$IFDEF VER110}
  8. {$DEFINE NMF3}
  9. {$ENDIF}
  10. {$IFDEF VER120}
  11. {$DEFINE NMF3}
  12. {$ENDIF}
  13. {$IFDEF VER125}
  14. {$DEFINE NMF3}
  15. {$ENDIF}
  16. interface
  17. uses
  18.   Classes, PSock, Sysutils, NMUUE, NMExtstr, NMConst;
  19. {$IFDEF VER110}
  20. {$OBJEXPORTALL On}
  21. {$ENDIF}
  22. {$IFDEF VER120}
  23. {$OBJEXPORTALL On}
  24. {$ENDIF}
  25. {$IFDEF VER125}
  26. {$OBJEXPORTALL On}
  27. {$ENDIF}
  28. const
  29.   POP3_PORT = 110;
  30.    //  CompName     ='NMPOP3';
  31.    //  Major_Version='4';
  32.    //  Minor_Version='02';
  33.    //  Date_Version ='012798';
  34. const {Protocol}
  35.   Cons_OK_Resp = '+OK';
  36.   Cons_Err_Resp = '-ERR';
  37.   Cons_Cmd_User = 'USER ';
  38.   Cons_Cmd_Pass = 'PASS ';
  39.   Cons_Cmd_Stat = 'STAT';
  40.   Cons_Cmd_Quit = 'QUIT';
  41.   Cons_Cmd_Top = 'TOP ';
  42.   Cons_Cmd_List = 'LIST ';
  43.   Cons_Cmd_Retr = 'RETR ';
  44.   Cons_Cmd_Dele = 'DELE ';
  45.   Cons_Cmd_Rset = 'RSET';
  46.   Cons_Cmd_Uidl = 'UIDL ';
  47.   Cons_Head_CSubj = 'SUBJECT:';
  48.   Cons_Head_CFrom = 'FROM:';
  49.   Cons_Head_CType = 'CONTENT-TYPE:';
  50.   Cons_Head_CMid = 'MESSAGE-ID:';
  51.   Cons_Head_CBoun = 'BOUNDARY=';
  52.   Cons_Head_CCTE = 'CONTENT-TRANSFER-ENCODING';
  53.   Cons_Head_FileN = 'FILENAME';
  54.   Cons_Head_Subj = 'Subject:';
  55.   Cons_Head_From = 'From:';
  56.   Cons_Head_MId = 'Message-ID:';
  57.   Cons_Head_Mult = 'multipart';
  58.   Cons_Head_UUEn = 'X-UUENCODE';
  59.   Cons_Head_B641 = 'base64';
  60.   Cons_Head_B642 = 'Base64';
  61. type
  62.   TListEvent = procedure(Msg, Size: integer) of object;
  63.       // Modification made by Edward T. Smith Sep 09 1998
  64.   TVarFileNameEvent = procedure(var FileName: string) of object;
  65.       // End
  66.   TMailMessage = class(TPersistent)
  67.   private
  68.     FHead: TexStringList;
  69.     FRawBody: TStringList;
  70.     FBody: TStringList;
  71.     Fcontenttypes, FAttachments: TStringList;
  72.     FPartHeaders: TList;
  73.     FContentType: string;
  74.     FFrom: string;
  75.     FSubject: string;
  76.     FMessageId: string;
  77.   public
  78.     FBoundary: string;
  79.     constructor Create;
  80.     destructor Destroy; override;
  81.     property Subject: string read FSubject;
  82.     property From: string read FFrom;
  83.     property RawBody: TStringList read FRawBody;
  84.     property Body: TStringList read FBody;
  85.     property Head: TExStringList read FHead;
  86.     property MessageId: string read FMessageId write FMessageId;
  87.     property ContentType: string read FContentType write FContentType;
  88.     property Attachments: TStringList read FAttachments;
  89.     property AttachContenttypes: TStringList read FContentTypes;
  90.     property PartHeaders: TList read FPartHeaders;
  91.   end; {_ TMailMessage      = class(TPersistent) _}
  92.   TSummary = class(TPersistent)
  93.   private
  94.     FSubject: string;
  95.     FFrom: string;
  96.     FBytes: integer;
  97.     FMessageId: string;
  98.     FHeader: TExStringList;
  99.   published
  100.     constructor Create;
  101.     destructor Destroy; override;
  102.     property Subject: string read FSubject write FSubject;
  103.     property From: string read FFrom write FFrom;
  104.     property MessageId: string read FMessageId write FMessageId;
  105.     property Bytes: integer read FBytes write FBytes;
  106.     property Header: TExStringList read FHeader write FHeader;
  107.   end; {_ TSummary          = class(TPersistent) _}
  108.   TNMPOP3 = class(TPowerSock)
  109.   private
  110.       // Modification made by Edward T. Smith Sep 09 1998
  111.     FOnDecodeStart: TVarFileNameEvent;
  112.     FOnDecodeEnd: TNotifyEvent;
  113.       // End
  114.     NMUUProcessor1: TNMUUProcessor;
  115.     FAttachFilePath, FFilename, FContent_type: string;
  116.     FSummary: TSummary;
  117.     FParse: boolean;
  118.     FMailMessage: TMailMessage;
  119.     FUserID, FPassword: string;
  120.     FAbort, FDeleteOnRead, FTransactionInProgress: boolean;
  121.     FMailCount, FFirstPart: integer;
  122.     FOnAuthenticationNeeded: THandlerEvent;
  123.     FOnAuthenticationFailed: THandlerEvent;
  124.     FOnReset: TNotifyEvent;
  125.     FOnList: TListEvent;
  126.     FOnRetrieveStart: TNotifyEvent;
  127.     FOnRetrieveEnd: TNotifyEvent;
  128.     FOnSuccess: TNotifyEvent;
  129.     FOnFailure: TNotifyEvent;
  130.     FOnConnect: TNotifyEvent;
  131.     WaitForReset: integer;
  132.     procedure ReadMailParts;
  133.     function ReadBody(var MailMessage: TMailMessage): boolean;
  134.     procedure ReadHeader(Readfile: boolean; var MailMessage: TMailMessage);
  135.     procedure AbortResume(Sender: TObject);
  136.     procedure SetAttachFilePath(Value: string);
  137.   protected
  138.   public
  139.     constructor Create(AOwner: TComponent); override;
  140.     destructor Destroy; override;
  141.     procedure Connect; override;
  142.     procedure Disconnect; override;
  143.     procedure GetMailMessage(MailNumber: integer);
  144.     procedure GetSummary(MailNumber: integer);
  145.     procedure DeleteMailMessage(MailNumber: integer);
  146.     procedure Extract(InString: string; var OutString: string);
  147.     function UniqueID(MailNumber: integer): string;
  148.     procedure Reset;
  149.     procedure List;
  150.     procedure Abort; override;
  151.     property MailCount: integer read FMailCount;
  152.     property Summary: TSummary read FSummary;
  153.     property MailMessage: TMailMessage read FMailMessage;
  154.     property OnRetriveStart: TNotifyEvent read FOnRetrieveStart write FOnRetrieveStart;
  155.     property OnRetriveEnd: TNotifyEvent read FOnRetrieveEnd write FOnRetrieveEnd;
  156.   published
  157.     property OnConnectionRequired;
  158.     property OnPacketRecvd;
  159.     property BytesRecvd;
  160.     property BytesTotal;
  161.     property UserID: string read FUserID write FUserID;
  162.     property Parse: boolean read FParse write FParse;
  163.     property Password: string read FPassword write FPassword;
  164.     property DeleteOnRead: boolean read FDeleteOnRead write FDeleteOnRead;
  165.       // Modification made by Edward T. Smith Sep 09 1998
  166.     property AttachFilePath: string read FAttachFilePath write SetAttachFilePath;
  167.       // End
  168.     property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
  169.     property OnAuthenticationNeeded: THandlerEvent read FOnAuthenticationNeeded write FOnAuthenticationNeeded;
  170.     property OnAuthenticationFailed: THandlerEvent read FOnAuthenticationFailed write FOnAuthenticationFailed;
  171.     property OnReset: TNotifyEvent read FOnReset write FOnReset;
  172.     property OnList: TListEvent read FOnList write FOnList;
  173.     property OnRetrieveStart: TNotifyEvent read FOnRetrieveStart write FOnRetrieveStart;
  174.     property OnRetrieveEnd: TNotifyEvent read FOnRetrieveEnd write FOnRetrieveEnd;
  175.     property OnSuccess: TNotifyEvent read FOnSuccess write FOnSuccess;
  176.     property OnFailure: TNotifyEvent read FOnFailure write FOnFailure;
  177.       // Modification made by Edward T. Smith Sep 09 1998
  178.     property OnDecodeStart: TVarFileNameEvent read FOnDecodeStart write FOnDecodeStart;
  179.     property OnDecodeEnd: TNotifyEvent read FOnDecodeEnd write FOnDecodeEnd;
  180.       // End
  181.   end; {_ TNMPOP3           = class(TPowerSock) _}
  182. implementation
  183. var Readindex, TFileIndex: integer;
  184. constructor TSummary.Create;
  185. begin
  186.   inherited Create;
  187.   FHeader := TExStringList.Create;
  188. end;
  189. destructor TSummary.Destroy;
  190. begin
  191.   FHeader.Free;
  192.   inherited Destroy;
  193. end;
  194. procedure TNMPOP3.SetAttachFilePath(Value: string);
  195. begin
  196.   if Value[Length(Value)] <> '' then
  197.     Value := Value + '';
  198.   FAttachFilePath := Value;
  199. end;
  200. // End
  201. constructor TNMPOP3.Create(AOwner: TComponent);
  202.  begin
  203.   inherited Create(AOwner);
  204.   Port := POP3_Port;
  205.   FMailMessage := TMailMessage.create;
  206.   FSummary := TSummary.create;
  207.   FDeleteOnRead := FALSE;
  208.   FTransactionInProgress := FALSE;
  209.   FAttachFilePath := '';
  210.   OnAbortRestart := AbortResume;
  211.   WaitForReset := 2;
  212.   NMUUProcessor1 := TNMUUProcessor.create(self);
  213. end; {_ constructor TNMPOP3.Create(AOwner: TComponent); _}
  214. destructor TNMPOP3.Destroy;
  215. begin
  216.   FSummary.free;
  217.   FMailMessage.free;
  218.   NMUUProcessor1.free;
  219.   inherited Destroy;
  220. end; {_ destructor TNMPOP3.Destroy; _}
  221. procedure TNMPOP3.Connect;
  222. var
  223.   ReplyMess: string;
  224.   Check: boolean;
  225.   TryCt: integer;
  226.   Done, ConnCalled, Handled: boolean;
  227.   function CheckAuth(FromHost: string): boolean;
  228.   begin
  229.     if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) > 0 then Result := TRUE
  230.     else {_ NOT if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) > 0 then Result := TRUE _}
  231.       begin
  232.         Result := FALSE;
  233.         if TryCt > 0 then raise Exception.create(Cons_Msg_Auth_Fail)
  234.         else {_ NOT if TryCt > 0 then raise Exception.create(Cons_Msg_Auth_Fail) _}
  235.           if not assigned(FOnAuthenticationFailed) then
  236.             raise Exception.create(Cons_Msg_Auth_Fail)
  237.           else {_ NOT if not assigned(FOnAuthenticationFailed) then raise Exception.create(Cons_Msg_Auth_Fail) _}
  238.             begin
  239.               Handled := FALSE;
  240.               FOnAuthenticationFailed(Handled);
  241.               if not Handled then raise Exception.create(Cons_Msg_Auth_Fail);
  242.               TryCt := TryCt + 1;
  243.             end; {_ NOT if not assigned(FOnAuthenticationFailed) then raise Exception.create(Cons_Msg_Auth_Fail) _}
  244.       end; {_ NOT if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) > 0 then Result := TRUE _}
  245.   end; {_ function CheckAuth(FromHost: string): boolean; _}
  246. begin
  247.   Done := FALSE;
  248.   TryCt := 0;
  249.   while (Password = '') or (UserID = '') do
  250.     if not assigned(FOnAuthenticationNeeded) then raise Exception.create(Cons_Msg_Auth_Fail)
  251.     else {_ NOT if not assigned(FOnAuthenticationNeeded) then raise Exception.create(Cons_Msg_Auth_Fail) _}
  252.       begin
  253.         if TryCt > 0 then break;
  254.         handled := FALSE;
  255.         FOnAuthenticationNeeded(Handled);
  256.         if not handled then raise Exception.create(Cons_Msg_Auth_Fail);
  257.         inc(TryCt);
  258.       end; {_ NOT if not assigned(FOnAuthenticationNeeded) then raise Exception.create(Cons_Msg_Auth_Fail) _}
  259.   ConnCalled := FALSE;
  260.   if FTransactionInProgress then ConnCalled := TRUE else FTransactionInProgress := TRUE;
  261.   try
  262.     inherited Connect;
  263.     try
  264.       ReplyMess := ReadLn;
  265.       if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) = 0 then raise Exception.create(ReplyMess);
  266.       Check := FALSE; TryCt := 0;
  267.       while not check do
  268.         begin
  269.           ReplyMess := Transaction(Cons_Cmd_User + FUserID);
  270.           if CheckAuth(ReplyMess) then
  271.             begin
  272.               ReplyMess := Transaction(Cons_Cmd_Pass + FPassword);
  273.               Check := CheckAuth(ReplyMess)
  274.             end; {_ if CheckAuth(ReplyMess) then _}
  275.           TryCt := TryCt + 1;
  276.         end; {_ while not check do _}
  277.       Done := TRUE;
  278.       ReplyMess := Transaction(Cons_Cmd_Stat);
  279.       if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) = 0 then raise Exception.create(ReplyMess);
  280.       FMailCount := StrToIntDef(NthWord(ReplyMess, ' ', 2), 0);
  281.     except
  282.       Disconnect;
  283.       raise
  284.     end; {_ try _}
  285.   finally
  286.     if not ConnCalled then FTransactionInProgress := FALSE;
  287.     if Done then
  288.       if assigned(FOnConnect) then
  289.         FOnConnect(self);
  290.   end; {_ try _}
  291. end; {_ procedure TNMPOP3.Connect; _}
  292. procedure TNMPOP3.Disconnect;
  293. var ReplyMess: string;
  294. begin
  295.   if Connected then
  296.     try
  297.       ReplyMess := Transaction(Cons_Cmd_Quit);
  298.       if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) = 0 then raise Exception.create(ReplyMess);
  299.     finally
  300.       inherited Disconnect;
  301.     end; {_ try _}
  302. end; {_ procedure TNMPOP3.Disconnect; _}
  303. procedure TNMPOP3.GetSummary(MailNumber: integer);
  304. var ReplyMess: string;
  305. begin
  306.   if not FTransactionInProgress then
  307.     begin
  308.       FTransactionInProgress := TRUE;
  309.       try
  310.         CertifyConnect;
  311.         if assigned(FOnRetrieveStart) then FOnRetrieveStart(self);
  312.         FAbort := FALSE;
  313.         ReplyMess := Transaction(Cons_Cmd_Top + IntToStr(MailNumber) + ' 0');
  314.         if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) = 0 then raise Exception.create(ReplyMess);
  315.         FSummary.FHeader.clear;
  316.         FSummary.FSubject := '';
  317.         FSummary.FFrom := '';
  318.         FSummary.FMessageID := '';
  319.         if not FAbort then
  320.           repeat
  321.             ReplyMess := readln;
  322.             if Pos(Cons_Head_Subj, ReplyMess) = 1 then FSummary.FSubject := Copy(ReplyMess, 9, length(ReplyMess) - 10);
  323.             if Pos(Cons_Head_From, ReplyMess) = 1 then FSummary.FFrom := Copy(ReplyMess, 6, length(ReplyMess) - 7);
  324.             if Pos(Cons_Head_MId, ReplyMess) = 1 then FSummary.FMessageID := Copy(ReplyMess, 13, 256);
  325.             if Replymess[Length(Replymess) - 1] = #13 then
  326.               SetLength(Replymess, Length(Replymess) - 2)
  327.             else {_ NOT if Replymess[Length(Replymess) - 1] = #13 then _}  SetLength(Replymess, Length(Replymess) - 1);
  328.             FSummary.FHeader.add(ReplyMess);
  329.           until ReplyMess = '.';
  330.         ReplyMess := Transaction(Cons_Cmd_List + IntToStr(MailNumber));
  331.         FSummary.FBytes := StrToInt(Trim(NthWord(ReplyMess, ' ', 3)));
  332.         StatusMessage(Status_Informational, sPOP_Cons_Summ_Retr);
  333.         if assigned(FOnRetrieveEnd) then FOnRetrieveEnd(self);
  334.       finally
  335.         FTransactionInProgress := FALSE;
  336.       end; {_ try _}
  337.     end; {_ if not FTransactionInProgress then _}
  338. end; {_ procedure TNMPOP3.GetSummary(MailNumber: integer); _}
  339. procedure TNMPOP3.GetMailMessage(MailNumber: integer);
  340. var ReplyMess: string;
  341. begin
  342.   if not FTransactionInProgress then
  343.     begin
  344.       FTransactionInProgress := TRUE;
  345.       CertifyConnect;
  346.       if assigned(FOnRetrieveStart) then FOnRetrieveStart(self);
  347.       try
  348.         FContent_type := '';
  349.         FMailMessage.FBoundary := '';
  350.         FFilename := '';
  351.         FAbort := FALSE;
  352.         FFirstPart := 2;
  353.         if assigned(OnPacketRecvd) then
  354.           begin
  355.             ReplyMess := Transaction(Cons_Cmd_List + IntToStr(MailNumber));
  356.             FBytesTotal := StrToInt(Trim(NthWord(ReplyMess, ' ', 3)));
  357.           end;
  358.         ReplyMess := Transaction(Cons_Cmd_Retr + IntToStr(MailNumber));
  359.         if Pos(Cons_OK_Resp, NthWord(ReplyMess, ' ', 1)) = 0 then raise Exception.create(ReplyMess);
  360.         Readindex := 0;
  361.         FMailMessage.FHead.clear;
  362.         FMailMessage.FBody.clear;
  363.         FMailMessage.FRawBody.clear;
  364.         FMailMessage.FAttachments.clear;
  365.         FMailMessage.Fcontenttypes.clear;
  366.         FMailMessage.FSubject := '';
  367.         FMailMessage.FContenttype := '';
  368.         FBytesRecvd := 0;
  369.         if not FAbort then ReadHeader(false, FMailMessage);
  370.         ReplyMess := Readln;
  371.         FBytesRecvd := FBytesRecvd + length(ReplyMess);
  372.         if assigned(OnPacketRecvd) then OnPacketRecvd(Self);
  373.         while ReplyMess <> '.' + #13#10 do
  374.           begin
  375.             ReplyMess := Copy(ReplyMess, 0, Length(ReplyMess) - 2);
  376.             FMailMessage.FRawBody.add(ReplyMess);
  377.             ReplyMess := Readln;
  378.             FBytesRecvd := FBytesRecvd + length(ReplyMess);
  379.             if assigned(OnPacketRecvd) then OnPacketRecvd(Self);
  380.           end;
  381.         if not FAbort then
  382.           if pos(Lowercase(Cons_Head_Mult), LowerCase(FMailMessage.FContentType)) > 0 then ReadMailParts
  383.           else if not FParse then FMailMessage.FBody.Assign(FMailMessage.FRawBody)
  384.           else
  385.             if (pos('BASE64', Uppercase(FContent_type)) > 0) then
  386.               begin
  387.                 FFirstPart := 0;
  388.                 ReadBody(FMailMessage);
  389.                 FMailMessage.FBody.loadfromfile(FAttachFilePath + FMailMessage.FAttachments[0]);
  390.               end
  391.             else {_ NOT if pos(Cons_Head_Mult, FContentType) > 0 then ReadMailParts _}  ReadBody(FMailMessage);
  392.         if FDeleteOnRead and not FAbort then
  393.           begin
  394.             ReplyMess := Transaction(Cons_Cmd_Dele + IntToStr(MailNumber));
  395.             if NthWord(ReplyMess, ' ', 1) = Cons_Err_Resp then raise Exception.create(ReplyMess);
  396.           end; {_ if FDeleteOnRead and not FAbort then _}
  397.         if FAbort then Transaction(Cons_Cmd_Rset)
  398.         else {_ NOT if FAbort then Transaction(Cons_Cmd_Rset) _}  StatusMessage(Status_Informational, sPOP_Cons_Msg_Retr);
  399.       finally
  400.         if assigned(FOnRetrieveEnd) then FOnRetrieveEnd(self);
  401.         FTransactionInProgress := FALSE;
  402.       end; {_ try _}
  403.     end; {_ if not FTransactionInProgress then _}
  404. end; {_ procedure TNMPOP3.GetMailMessage(MailNumber: integer); _}
  405. procedure TNMPOP3.Extract(InString: string; var OutString: string);
  406. var i: integer;
  407.   found: boolean;
  408. begin
  409.   CertifyConnect;
  410.   i := -1;
  411.   found := FALSE;
  412.   repeat
  413.     i := i + 1;
  414.     if (Pos(InString, FMailMessage.FHead[i]) > 0) then found := TRUE;
  415.   until found or (i = (FMailMessage.FHead.count - 1));
  416.   if found then OutString := Trim(Copy(FMailMessage.FHead[i], Pos(':', FMailMessage.FHead[i]) + 1, 255))
  417.   else {_ NOT if found then OutString := Trim(Copy(FMailMessage.FHead[i], Pos(':', FMailMessage.FHead[i]) + 1, 255)) _}  OutString := '';
  418. end; {_ procedure TNMPOP3.Extract(InString: string; var OutString: string); _}
  419. procedure TNMPOP3.Reset;
  420. var ReplyMess: string;
  421. begin
  422.   CertifyConnect;
  423.   ReplyMess := Transaction(Cons_Cmd_Rset);
  424.   if assigned(FOnReset) then FOnReset(self);
  425. end; {_ procedure TNMPOP3.Reset; _}
  426. procedure TNMPOP3.List;
  427. var ReplyMess: string;
  428. begin
  429.   if not FTransactionInProgress then
  430.     begin
  431.       FTransactionInProgress := TRUE;
  432.       try
  433.         CertifyConnect;
  434.         ReplyMess := Transaction(Cons_Cmd_List);
  435.         ReplyMess := Readln;
  436.         SetLength(ReplyMess, length(ReplyMess) - 2);
  437.         while (ReplyMess <> '.') do
  438.           begin
  439.             if assigned(FOnList) then FOnList(StrToInt(NthWord(ReplyMess, ' ', 1)), StrToInt(NthWord(ReplyMess, ' ', 2)));
  440.             ReplyMess := Readln;
  441.             SetLength(ReplyMess, length(ReplyMess) - 2);
  442.           end; {_ while (ReplyMess <> '.') do _}
  443.       finally
  444.         FTransactionInProgress := FALSE;
  445.       end; {_ try _}
  446.     end; {_ if not FTransactionInProgress then _}
  447. end; {_ procedure TNMPOP3.List; _}
  448. procedure TNMPOP3.ReadMailParts;
  449. var ReplyMess: string;
  450.   LastPart: boolean;
  451.   TemMessage: TMailMessage;
  452. begin
  453.    {Extract Boundary Information}
  454.   LastPart := FALSE;
  455.    {Read Till First Boundary}
  456.   TemMessage := TMailMessage.Create;
  457.   repeat
  458.     ReplyMess := FMailMessage.FRawBody[Readindex];
  459.     inc(Readindex);
  460.   until Pos(FMailMessage.FBoundary, ReplyMess) > 0;
  461.   repeat
  462.     if not FAbort then ReadHeader(true, TemMessage);
  463.     if not FAbort then LastPart := ReadBody(FMailMessage);
  464.   until (ReadIndex = FMailMessage.FRawBody.count) or (LastPart) or (FAbort) or (ReplyMess = '.' + #13#10);
  465.   TemMessage.Free;
  466.    {repeat
  467.       ReplyMess := readln;
  468.    until ReplyMess = '.' + #13#10; }
  469. end; {_ procedure TNMPOP3.ReadMailParts; _}
  470. procedure TNMPOP3.ReadHeader(Readfile: boolean; var MailMessage: TMailMessage);
  471. var ReplyMess: string;
  472. begin
  473.   repeat
  474.     if not FAbort then
  475.       begin
  476.         if ReadFile then
  477.           begin
  478.             if ReadIndex = FMailMessage.FRawBody.count then exit;
  479.             ReplyMess := FMailMessage.FRawBody[Readindex];
  480.             inc(Readindex);
  481.           end
  482.         else
  483.           begin
  484.             ReplyMess := ReadLn;
  485.             FBytesRecvd := FBytesRecvd + length(ReplyMess);
  486.             if assigned(OnPacketRecvd) then OnPacketRecvd(Self);
  487.             SetLength(ReplyMess, length(ReplyMess) - 2);
  488.           end;
  489.         if FFirstPart = 2 then FMailMessage.FHead.add(ReplyMess);
  490.         if (ReplyMess <> '') then
  491.           begin
  492.             if UpperCase(NthWord(ReplyMess, ' ', 1)) = Cons_Head_CSubj then
  493.               FMailMessage.Fsubject := Copy(ReplyMess, 9, 256);
  494.             if UpperCase(NthWord(ReplyMess, ' ', 1)) = Cons_Head_CFrom then
  495.               FMailMessage.FFrom := Copy(ReplyMess, 7, 256);
  496.             if UpperCase(NthWord(ReplyMess, ' ', 1)) = Cons_Head_CType then
  497.               FMailMessage.FContentType := Copy(ReplyMess, 15, 256);
  498.             if UpperCase(NthWord(ReplyMess, ' ', 1)) = Cons_Head_CMid then
  499.               FMailMessage.FMessageID := Copy(ReplyMess, 13, 256);
  500.             if Pos(Cons_Head_CBoun, UpperCase(ReplyMess)) > 0 then
  501.               begin
  502.                 MailMessage.FBoundary := Copy(ReplyMess, Pos(Cons_Head_CBoun, UpperCase(ReplyMess)) + 9, 256);
  503.                 if (MailMessage.FBoundary[1] = #22) then
  504.                   SetLength(MailMessage.FBoundary, Length(MailMessage.FBoundary) - 2)
  505.                 else {_ NOT if Boundary[1] = #22 then _}
  506.                   begin
  507.                     SetLength(MailMessage.FBoundary, Length(MailMessage.FBoundary) - 3);
  508.                     MailMessage.FBoundary := Copy(MailMessage.FBoundary, 2, 255);
  509.                   end; {_ NOT if Boundary[1] = #22 then _}
  510.               end;
  511.             if Pos(Cons_Head_CCTE, UpperCase(ReplyMess)) > 0 then
  512.               FContent_type := Copy(ReplyMess, 28, 256);
  513.             if (Pos(Cons_Head_FileN, UpperCase(ReplyMess)) > 0) or (Pos('NAME', UpperCase(ReplyMess)) > 0) then
  514.               FFilename := NthWord(ReplyMess, '"', 2);
  515.           end; {_ if (ReplyMess <> '') then _}
  516.       end; {_ if not FAbort then _}
  517.   until (ReplyMess = '') or FAbort;
  518.   if FFirstPart = 2 then FFirstPart := 1;
  519. end; {_ procedure TNMPOP3.ReadHeader; _}
  520. //BD 1-7-99 To support files with multiple .s
  521. function LastPos(StringSought, TheString: string): Integer;
  522. var
  523.   CurrentPos: Integer;
  524. begin
  525.   Result := 0;
  526.   while Pos(StringSought, TheString) > 0 do
  527.     begin
  528.       CurrentPos := Pos(StringSought, TheString) + Length(StringSought) - 1;
  529.       Result := Result + CurrentPos;
  530.       TheString := Copy(TheString, CurrentPos + 1, Length(TheString));
  531.     end;
  532.   if Result > 0 then
  533.     Result := Result - (Length(StringSought) - 1);
  534. end;
  535. //BD 1-7-99 To support files with multiple .s
  536. function TNMPOP3.ReadBody(var MailMessage: TMailMessage): boolean;
  537. var OutStream: TFileStream;
  538.   ReplyMess, TFname1, TFName2: string;
  539.   i: integer;
  540.   Ins, Ous: TFileStream;
  541. begin
  542.   try
  543.     result := FALSE;
  544.     OutStream := nil;
  545.    {if FFirstPart=1 then if (FContenttype<>'') and (pos('ascii',FContenttype)=0) then FFirstPart:=0;  }
  546.     if FFirstPart = 0 then
  547.       begin
  548.         inc(TFileIndex);
  549.         OutStream := TFileStream.create(FAttachFilePath + 'Temp' + IntToStr(TFileIndex) + '.mme', fmCreate);
  550.       end; {_ if FFirstPart = 0 then _}
  551.     StatusMessage(Status_Informational, sPOP_Cons_Msg_ExtrF);
  552.     if ReadIndex = FMailMessage.FRawBody.count then exit;
  553.     ReplyMess := FMailMessage.FRawBody[Readindex];
  554.     inc(Readindex);
  555.     while (Readindex <> FMailMessage.FRawBody.count) and (Pos(MailMessage.FBoundary, ReplyMess) = 0) and (ReplyMess <> '.' + #13#10) and (not FAbort) do
  556.       begin
  557.         if FFirstPart > 0 then
  558.           begin
  559.          //SetLength(ReplyMess, length(ReplyMess) - 2);
  560.             FMailMessage.FBody.add(ReplyMess);
  561.           end {_ if FFirstPart > 0 then _}
  562.         else {_ NOT if FFirstPart > 0 then _} {FMailMessage.FBody.add(ReplyMess);}
  563.           begin
  564.             ReplyMess := ReplyMess + CRLF;
  565.             OutStream.WriteBuffer(ReplyMess[1], length(ReplyMess));
  566.           end;
  567.         ReplyMess := FMailMessage.FRawBody[Readindex];
  568.         inc(Readindex);
  569.       end;
  570.     if not Fabort and (FFirstPart = 0) and (OutStream.size > 0) then
  571.       begin
  572.         OutStream.Free;
  573.         if FFileName = '' then FFileName := 'text.tmp';
  574.         TFName1 := Copy(FFileName, 1, LastPos('.', FFileName) - 1);
  575.         TFName2 := Copy(FFileName, Length(TFName1) + 2, Length(FFileName));
  576.         i := 1;
  577.         while FileExists(FAttachFilePath + FFileName) do
  578.           begin
  579.             FFileName := TFName1 + '_' + IntToStr(i) + '.' + TFName2;
  580.             i := i + 1;
  581.           end; {_ while FileExists(FAttachFilePath + FFileName) do _}
  582.       // Modification made by Edward T. Smith Sep 09 1998
  583.         if assigned(FOnDecodeStart) then
  584.           FOnDecodeStart(FFileName);
  585.       // End
  586.         FMailMessage.FBody.add(#13#10 + sPOP_Cons_Msg_File + FFileName + sPOP_Cons_Msg_Extr);
  587.         FMailMessage.FAttachments.Add(FFileName);
  588.         FMailMessage.FContentTypes.Add(FMailMessage.Contenttype);
  589.         if (Pos(Cons_Head_B641, Lowercase(FContent_type)) > 0) or (Pos(Cons_Head_UUEn, FContent_type) > 0) then
  590.           begin
  591.             Ins := TFileStream.create(FAttachFilePath + 'Temp' + IntToStr(TFileIndex) + '.mme', fmOpenRead);
  592.             Ous := TFileStream.create(FAttachFilePath + FFilename, fmCreate);
  593.             try
  594.               NMUUProcessor1.InputStream := Ins;
  595.               NMUUProcessor1.OutputStream := Ous;
  596.               if (Pos(Cons_Head_UUEn, FContent_type) > 0) then NMUUProcessor1.method := UUCode else NMUUProcessor1.method := UUMime;
  597.               StatusMessage(Status_Informational, sPOP_Cons_Msg_Deco);
  598.               if ins.size <> 0 then NMUUProcessor1.Decode;
  599.             finally
  600.               Ins.free;
  601.               Ous.free;
  602.             end; {_ try _}
  603.           end {_ if (Pos(Cons_Head_B641, FContent_type) > 0) or (Pos(Cons_Head_B642, FContent_type) > 0) or (Pos(Cons_Head_UUEn, FContent_type) > 0) then _}
  604.         else {_ NOT if (Pos(Cons_Head_B641, FContent_type) > 0) or (Pos(Cons_Head_B642, FContent_type) > 0) or (Pos(Cons_Head_UUEn, FContent_type) > 0) then _}
  605.           begin
  606.             if FileExists(FAttachFilePath + FFilename) then DeleteFile(FAttachFilePath + FFilename);
  607.             RenameFile(FAttachFilePath + 'Temp' + IntToStr(TFileIndex) + '.mme', FAttachFilePath + FFilename);
  608.           end;
  609.       end; {_ if not Fabort and (FFirstPart = 0) then _}
  610.     if (Pos(MailMessage.FBoundary, ReplyMess) > 0) then
  611.       begin
  612.         ReplyMess := Copy(ReplyMess, Length(ReplyMess) - 3, 256);
  613.         if Pos('--', ReplyMess) > 0 then result := true;
  614.       end; {_ if (Pos(FBoundary, ReplyMess) > 0) then _}
  615.     FFirstPart := 0;
  616.   finally
  617.     if FileExists(FAttachFilePath + 'Temp' + IntToStr(TFileIndex) + '.mme') then Deletefile(FAttachFilePath + 'Temp' + IntToStr(TFileIndex) + '.mme');
  618.   end;
  619. end; {_ function TNMPOP3.ReadBody: boolean; _}
  620. procedure TNMPOP3.DeleteMailMessage(MailNumber: integer);
  621. var ReplyMess: string;
  622.   Done: boolean;
  623. begin
  624.   if not FTransactionInProgress then
  625.     begin
  626.       Done := FALSE;
  627.       FTransactionInProgress := TRUE;
  628.       try
  629.         CertifyConnect;
  630.         ReplyMess := Transaction(Cons_Cmd_Dele + IntToStr(MailNumber));
  631.         if NthWord(ReplyMess, ' ', 1) = Cons_Err_Resp then
  632.           begin
  633.             if assigned(FOnFailure) then FOnFailure(self);
  634.             raise Exception.create(ReplyMess);
  635.           end {_ if NthWord(ReplyMess, ' ', 1) <> Cons_OK_Resp then _}
  636.         else {_ NOT if NthWord(ReplyMess, ' ', 1) <> Cons_OK_Resp then _}  Done := TRUE;
  637.       finally
  638.         FTransactionInProgress := FALSE;
  639.         if Done then
  640.           if assigned(FOnSuccess) then
  641.             FOnSuccess(self);
  642.       end; {_ try _}
  643.     end; {_ if not FTransactionInProgress then _}
  644. end; {_ procedure TNMPOP3.DeleteMailMessage(MailNumber: integer); _}
  645. function TNMPOP3.UniqueID(MailNumber: integer): string;
  646. var ReplyMess: string;
  647. begin
  648.   if not FTransactionInProgress then
  649.     begin
  650.       Result := '';
  651.       FTransactionInProgress := TRUE;
  652.       try
  653.         CertifyConnect;
  654.         ReplyMess := Transaction(Cons_Cmd_Uidl + IntToStr(MailNumber));
  655.         if NthWord(ReplyMess, ' ', 1) <> Cons_OK_Resp then
  656.           begin
  657.             if assigned(FOnFailure) then FOnFailure(self);
  658.             raise Exception.create(ReplyMess);
  659.           end {_ if NthWord(ReplyMess, ' ', 1) <> Cons_OK_Resp then _}
  660.         else {_ NOT if NthWord(ReplyMess, ' ', 1) <> Cons_OK_Resp then _}
  661.           Result := NthWord(ReplyMess, ' ', 3);
  662.       finally
  663.         FTransactionInProgress := FALSE;
  664.       end; {_ try _}
  665.     end; {_ if not FTransactionInProgress then _}
  666. end;
  667. procedure TNMPOP3.Abort;
  668. begin
  669.   Cancel;
  670.   if Connected then
  671.     begin
  672.       //if FTransactionInProgress then
  673.       //begin
  674.       //   Cancel;
  675.       //end {_ if FTransactionInProgress then _}
  676.       //else {_ NOT if FTransactionInProgress then _}
  677.       //begin
  678.       inherited Disconnect;
  679.       ClearInput;
  680.       //end; {_ NOT if FTransactionInProgress then _}
  681.     end; {_ if (not BeenCanceled) and Connected then _}
  682. end; {_ procedure TNMPOP3.Abort; _}
  683. procedure TNMPOP3.AbortResume(Sender: TObject);
  684. begin
  685.    //inherited Disconnect;
  686.    //TMemoryStream(FIstream).clear;
  687. end; {_ procedure TNMPOP3.AbortResume(Sender: TObject); _}
  688. constructor TMailMessage.create;
  689. begin
  690.   FHead := TExStringList.create;
  691.   FBody := TStringList.create;
  692.   FAttachments := TStringList.create;
  693.   FContentTypes := TStringList.create;
  694.   FRawBody := TStringList.create;
  695.   FPartHeaders := Tlist.Create;
  696. end; {_ constructor TMailMessage.create; _}
  697. destructor TMailMessage.destroy;
  698. begin
  699.   FHead.free;
  700.   FBody.free;
  701.   FAttachments.free;
  702.   FContentTypes.free;
  703.   FRawBody.free;
  704.   FPartHeaders.free;
  705. end; {_ destructor TMailMessage.destroy; _}
  706. end.