home *** CD-ROM | disk | FTP | other *** search
- unit Cciccpop;
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Menus, FileCtrl, CCWSock, CCICCInf,
- CCICCPrf, IniFiles, Gauges , CCUUCode, CCiccfrm;
-
- type
- { Component To Hold POP3/SMTP handling capabilities }
- TPOP3SMTPComponent = class( TWinControl )
- public
- POP3CommandInProgress ,
- Connection_Established : Boolean;
- Socket1 : TCCSocket;
- constructor Create( AOwner : TComponent ); override;
- destructor Destroy; override;
- function EstablishPOP3Connection( PCRPointer : PConnectionsRecord ) : Boolean;
- function POP3Disconnect : Boolean;
- function DoCStyleFormat( TheText : string;
- const TheArguments : array of const ) : String;
- procedure UpdateGauge( BytesFinished , TotalToHandle : longint );
- procedure AddProgressText( WhatText : String );
- procedure ShowProgressText( WhatText : String );
- procedure ShowProgressErrorText( WhatText : String );
- function GetPOP3ServerResponse( var ResponseString : String ) : integer;
- procedure POP3SMTPSocketsErrorOccurred( Sender : TObject;
- ErrorCode : Integer;
- TheMessage : String );
- function PerformPOP3Command(
- TheCommand : string;
- const TheArguments : array of const ) : Integer;
- function PerformPOP3ExtendedCommand(
- TheCommand : string;
- const TheArguments : array of const ) : Integer;
- function GetPOP3ServerExtendedResponse( ResponseString : PChar ) : integer;
- function GetNextSDItem( WorkingString : String;
- var TheIndex : Integer ) : String;
- procedure PurgeTrashedMessageListings( TheEMBRecord : PEMailMailBoxRecord );
- procedure TrashMessage( TheEMMRecord : PEMailMessageRecord );
- procedure TrashAllMarkedMessages( TheLB : TListBox;
- TheMBRecord : PEMailMailboxRecord );
- procedure ParseMailListing( TheListing : String;
- var TotalMessages : Longint;
- var MessageBytes : Longint);
- function CheckAllNewMail( var TotalBytes : Longint ) : Integer;
- function GetMessageHeader( TheReturnList : TStringList ) : Longint;
- function DownloadMessageListing( TheNumber : Integer;
- TheFileName : String;
- TheHeaderSL : TStringList ) : Longint;
- function DownloadAllMessageListings( TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
- function GetHeaderSubject( HList : TStringList ) : String;
- function GetHeaderSender( HList : TStringList ) : String;
- function GetHeaderRecipient( HList : TStringList ) : String;
- function GetHeaderCarbons( HList : TStringList ) : String;
- function GetHeaderBlindCarbons( HList : TStringList ) : String;
- function GetHeaderDateTime( HList : TStringList ) : String;
- procedure TransferMessage( SourceEMBRecord , TargetEMBRecord : PEMailMailBoxRecord;
- MessageNumber : Integer );
- function LoginUser( PCRPointer : PConnectionsRecord ) : Boolean;
- function SendPassword( PCRPointer : PConnectionsRecord ) : Boolean;
- function DeleteMailItem( TheNumber : Longint ) : Boolean;
- end;
-
- var
- ThePOP3SMTPComponent : TPOP3SMTPComponent; { Gee, which one is this? :) }
-
- implementation
-
- procedure TPOP3SMTPComponent.TrashMessage( TheEMMRecord : PEMailMessageRecord );
- begin
- TheEMMRecord^.MRMessageSender := 'DELETE ME';
- end;
-
- procedure TPOP3SMTPComponent.TrashAllMarkedMessages( TheLB : TListBox;
- TheMBRecord : PEMailMailboxRecord );
- var Counter_1 : Integer;
- WorkingList : TList;
- begin
- WorkingList := TList( TheMBRecord^.MBLTag );
- for Counter_1 := 0 to TheLB.Items.Count - 1 do
- begin
- if TheLB.Selected[ Counter_1 ] then
- begin
- TrashMessage( PEMailMessageRecord( WorkingList.Items[ Counter_1 ] ));
- end;
- end;
- end;
-
- { This function calls an extended response POP3SMTP command routine }
- function TPOP3SMTPComponent.PerformPOP3ExtendedCommand(
- TheCommand : string;
- const TheArguments : array of const ) : Integer;
- var TheBuffer : string; { Text buffer }
- begin
- { If command in progress send back -1 error }
- if POP3CommandInProgress then
- begin
- Result := -1;
- exit;
- end;
- { Set status variable }
- POP3CommandInProgress := True;
- { Set global error code }
- GlobalErrorCode := 0;
- { Format output string }
- TheBuffer := Format( TheCommand , TheArguments );
- { Preset failure code }
- Result := TCPIP_STATUS_FATAL_ERROR;
- { If invalid socket or no connection abort }
- if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
- exit;
- { Send the buffer plus EOL chars }
- Socket1.StringData := TheBuffer + #13#10;
- { if abort due to timeout or other error exit }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Otherwise return preliminary code }
- Result := TCPIP_STATUS_PRELIMINARY;
- end;
-
- { This function gets an extended period-ended multiline response from the server }
- function TPOP3SMTPComponent.GetPOP3ServerExtendedResponse( ResponseString : PChar ) : integer;
- var
- { Assume ResponseString already allocated as 0..513 }
- { Pointer to the response string }
- TheBuffer ,
- BufferPointer : array[0..255] of char;
- HolderBuffer : array[0..513] of char;
- { Character to check for response code }
- ResponseChar : char;
- { Pointers into returned string }
- TheIndex ,
- TheLength : integer;
- { Control variable }
- LeftoversInPan ,
- Finished : Boolean;
- BufferString : String;
- begin
- { Preset fatal error }
- Result := TCPIP_STATUS_FATAL_ERROR;
- { Start loop control }
- LeftoversInPan := false;
- Finished := false;
- StrCopy( HolderBuffer , '' );
- repeat
- { Do a peek }
- BufferString := Socket1.PeekData;
- { If timeout or other error exit }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Find end of line character }
- TheIndex := Pos( #10 , BufferString );
- if TheIndex = 0 then
- begin
- TheIndex := Pos( #13 , BufferString );
- if TheIndex = 0 then
- begin
- TheIndex := Pos( #0 , BufferString );
- if TheIndex = 0 then
- begin
- TheIndex := Length( BufferString );
- LeftoversInPan := True;
- StrPCopy( TheBuffer , BufferString );
- StrCat( HolderBuffer , TheBuffer );
- LeftoversOnTable := false;
- end;
- end;
- end;
- { If an end of line then process the line }
- if TheIndex > 0 then
- begin
- { Get length of string }
- TheLength := TheIndex;
- { Receive actual data }
- Socket1.CCSockReceive( Socket1.TheSocket ,
- @BufferPointer[ 0 ] ,
- TheLength );
- { Abort if timeout or error }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Put in the length byte }
- BufferPointer[ TheLength ] := Chr( 0 );
- if LeftOversOnTable then
- begin
- LeftOversOnTable := false;
- StrCopy( ResponseString , HolderBuffer );
- StrCat( ResponseString , BufferPointer );
- end
- else
- begin
- if not LeftoversInPan then StrCopy( ResponseString , BufferPointer );
- end;
- if LeftoversInPan then
- begin
- LeftoversInPan := false;
- LeftoversOnTable := true;
- end
- else
- begin
- ResponseChar := ResponseString[ 0 ];
- if (( ResponseChar = '.' ) and ( StrLen( ResponseString ) <= 3 )) then
- begin
- ResponseString[ 0 ] := ' ';
- Finished := true;
- Result := TCPIP_STATUS_COMPLETED;
- end
- else
- begin
- if ResponseChar = '.' then ResponseString[ 0 ] := ' ';
- Finished := true;
- Result := TCPIP_STATUS_PRELIMINARY;
- end;
- end;
- end;
- until ( Finished and ( not LeftoversOnTable ));
- StrLCopy( ResponseString , ResponseString , StrLen( ResponseString ) - 2 );
- end;
-
-
- { This function moves along a string from an index, getting the next }
- { string delimited item or last one on string. }
- function TPOP3SMTPComponent.GetNextSDItem( WorkingString : String;
- var TheIndex : Integer ) : String;
- var HoldingString : String;
- begin
- HoldingString := Copy( WorkingString , TheIndex + 1 , 255 );
- TheIndex := Pos( ' ' , HoldingString );
- if TheIndex = 0 then
- begin
- Result := HoldingString;
- end
- else
- begin
- HoldingString := Copy( HoldingString , 1 , TheIndex - 1 );
- Result := HoldingString;
- end;
- end;
-
- { This method assumes logged into server; gets data via STAT command }
- { returns total bytes in var'd param and total messages as result }
- function TPOP3SMTPComponent.CheckAllNewMail( var TotalBytes : Longint ) : Integer;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- TheLResult : Longint;
- begin
- TheReturnString :=
- DoCStyleFormat( 'STAT' , [ nil ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Begin login sequence with user name }
- TheResult := PerformPOP3Command( 'STAT', [ nil ] );
- if TheResult <> TCPIP_STATUS_PRELIMINARY then
- begin
- POP3CommandInProgress := false;
- Result := -1;
- exit;
- end;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'Mail Not Available!' , [ nil ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := -1;
- { leave }
- exit;
- end;
- ParseMailListing( TheReturnString , TheLResult , TotalBytes );
- Result := TheLResult;
- end;
-
- function TPOP3SMTPComponent.DeleteMailItem( TheNumber : Longint ) : Boolean;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- begin
- TheReturnString :=
- DoCStyleFormat( 'DELE %d' , [ TheNumber ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Begin login sequence with user name }
- TheResult := PerformPOP3Command( 'DELE %d', [ TheNumber ] );
- if TheResult <> TCPIP_STATUS_PRELIMINARY then
- begin
- POP3CommandInProgress := false;
- Result := false;
- exit;
- end;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'Mail Not Available!' , [ nil ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := false;
- { leave }
- exit;
- end;
- Result := True;
- end;
-
- { This method splits up a listing and pulls out its component data }
- procedure TPOP3SMTPComponent.ParseMailListing( TheListing : String;
- var TotalMessages : Longint;
- var MessageBytes : Longint);
- var HoldingString ,
- HoldingString2 : String;
- WorkingIndex : Integer;
- begin
- WorkingIndex := Pos( ' ' , TheListing );
- HoldingString := Copy( TheListing , WorkingIndex + 1 , 255 );
- WorkingIndex := Pos( ' ' , HoldingString );
- HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
- TotalMessages := StrToInt( HoldingString2 );
- HoldingString := Copy( HoldingString , WorkingIndex + 1 , 255 );
- WorkingIndex := Pos( ' ' , HoldingString );
- if WorkingIndex = 0 then WorkingIndex := 256;
- HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
- MessageBytes := StrToInt( HoldingString2 );
- end;
-
- { This method accumulates all the strings until '' as a messge header }
- function TPOP3SMTPComponent.GetMessageHeader( TheReturnList : TStringList ) : Longint;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- TheReturnPChar ,
- TheHoldingPChar : PChar;
- TotalGotten : Longint;
- begin
- GetMem( TheReturnPChar , 514 );
- TheReturnList.Clear;
- TotalGotten := 0;
- repeat
- TheResult := GetPOP3ServerExtendedResponse( TheReturnPChar );
- if StrLen( TheReturnPChar ) < 3 then
- begin
- TheResult := TCPIP_STATUS_COMPLETED;
- end;
- TotalGotten := TotalGotten + StrLen( TheReturnPChar ) + 2;
- if StrLen( TheReturnPChar ) > 255 then
- begin
- Getmem( TheHoldingPChar , 255 );
- while StrLen( TheReturnPChar ) > 255 do
- begin
- StrCopy( TheHoldingPChar , '' );
- StrMove( TheHoldingPChar , TheReturnPChar , 255 );
- TheReturnPChar := TheReturnPChar + 256;
- TheReturnString := StrPas( TheHoldingPChar );
- TheReturnList.Add( TheReturnString );
- end;
- StrCopy( TheHoldingPChar , '' );
- StrMove( TheHoldingPChar , TheReturnPChar , StrLen( TheReturnPChar ));
- TheReturnString := StrPas( TheHoldingPChar );
- TheReturnString := '\' + TheReturnString;
- TheReturnList.Add( TheReturnString );
- FreeMem( TheHoldingPChar , 255 );
- end
- else
- begin
- TheReturnString := StrPas( TheReturnPChar );
- TheReturnList.Add( TheReturnString );
- end;
- until (( GlobalAbortedFlag ) or ( TheResult = TCPIP_STATUS_COMPLETED ));
- FreeMem( TheReturnPChar , 514 );
- Result := TotalGotten;
- end;
-
- { This method parses a header stringlist and obtains the subject line }
- function TPOP3SMTPComponent.GetHeaderSubject( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '[No Subject]';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'SUBJECT:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 9 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method parses a header stringlist and obtains the sender's ID }
- function TPOP3SMTPComponent.GetHeaderSender( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'FROM:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 7 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method strips out the TO: field of a mail message header }
- function TPOP3SMTPComponent.GetHeaderRecipient( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'TO:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 5 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method strips out the CC: field of a mail message header }
- function TPOP3SMTPComponent.GetHeaderCarbons( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'CC:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 5 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method strips out the BCC: field of a mail message header }
- function TPOP3SMTPComponent.GetHeaderBlindCarbons( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'BCC:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 6 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method strips out the DATE: field of a mail message header }
- function TPOP3SMTPComponent.GetHeaderDateTime( HList : TStringList ) : String;
- var Counter_1 : Integer;
- Finished : Boolean;
- WorkingIndex : Integer;
- WorkingString : String;
- begin
- Counter_1 := 0;
- Finished := false;
- WorkingString := '';
- while (( not Finished ) and ( Counter_1 <= HList.Count - 1 )) do
- begin
- WorkingIndex := Pos( 'DATE:' , Uppercase( HList.Strings[ Counter_1 ] ));
- if WorkingIndex > 0 then
- begin
- WorkingString := Copy( HList.Strings[ Counter_1 ] , 7 , 255 );
- Finished := true;
- end
- else Inc( Counter_1 );
- end;
- Result := WorkingString;
- end;
-
- { This method transfers a message from one mailbox to another }
- procedure TPOP3SMTPComponent.TransferMessage( SourceEMBRecord ,
- TargetEMBRecord : PEMailMailBoxRecord;
- MessageNumber : Integer );
- var WorkingList1 , WorkingList2 : TList;
- TheEMMRecord : PEMailMessageRecord;
- begin
- WorkingList1 := TList( SourceEMBRecord^.MBLTag );
- WorkingList2 := TList( TargetEMBRecord^.MBLTag );
- TheEMMRecord := PEMailMessageRecord( WorkingList1.Items[ MessageNumber ] );
- WorkingList2.Add( TheEMMRecord );
- SourceEMBRecord^.MBLTag := Longint( WorkingList1 );
- TargetEMBRecord^.MBLTag := Longint( WorkingList2 );
- end;
-
- { This function deletes all read/sent articles and associated files }
- procedure TPOP3SMTPComponent.PurgeTrashedMessageListings( TheEMBRecord : PEMailMailBoxRecord );
- var TheEMMRecord : PEMailMessageRecord;
- Counter_1 : Integer;
- WorkingList : TList;
- Finished : Boolean;
- begin
- { Do this for ease of coding }
- with TheEMBRecord^ do
- begin
- { Get the current TList of article headers }
- WorkingList := TList( MBLTag );
- { Run up to total new articles }
- for Counter_1 := 0 to WorkingList.Count - 1 do
- begin
- TheEMMRecord := PEMailMessageRecord( WorkingList.Items[ Counter_1 ] );
- if ( TheEMMRecord^.MRMessageSender = 'DELETE ME' ) then
- begin
- Dec( MBTotal );
- if not TheEMMRecord^.MRRead then if MBUnReadTotal > 0 then Dec( MBUnReadTotal );
- if not TheEMMRecord^.MRSent then if MBUnSentTotal > 0 then Dec( MBUnSentTotal );
- if FileExists( MailPath + '\' + TheEMMRecord^.MRFilename ) then
- {DeleteFile( MailPath + '\' + TheEMMRecord^.MRFileName )};
- end;
- end;
- Counter_1 := 0;
- Finished := False;
- if WorkingList.Count = 0 then Finished := true;
- while Not Finished do
- begin
- TheEMMRecord := PEMailMessageRecord( WorkingList.Items[ Counter_1 ] );
- if ( TheEMMRecord^.MRMessageSender = 'DELETE ME' ) then
- begin
- WorkingList.Delete( Counter_1 );
- end
- else Counter_1 := Counter_1 + 1;
- if Counter_1 > WorkingList.Count - 1 then Finished := true;
- end;
- end;
- end;
-
- { This method uses the ARTICLE command to obtain an article and put it in a }
- { preset/supplied file. It is designed to work by itself or inside DAALs }
- function TPOP3SMTPComponent.DownloadMessageListing( TheNumber : Integer;
- TheFileName : String;
- TheHeaderSL : TStringList ) : Longint;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- TheReturnPChar ,
- TheHoldingPChar : PChar;
- TheMessageFile : TextFile;
- Counter_1 : Integer;
- TotalGotten : Longint;
- begin
- TheReturnString :=
- DoCStyleFormat( 'RETR %d' ,
- [ TheNumber ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Begin login sequence with user name }
- TheResult := PerformPOP3Command( 'RETR %d', [ TheNumber ] );
- if TheResult <> TCPIP_STATUS_PRELIMINARY then
- begin
- POP3CommandInProgress := false;
- Result := 0;
- exit;
- end;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'Retrieve Message %d Failed!' ,
- [ TheNumber ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := 0;
- { leave }
- exit;
- end;
- GetMem( TheReturnPChar , 514 );
- try
- AssignFile( TheMessageFile , TheFileName );
- Rewrite( TheMessageFile );
- except
- MessageDlg( 'Unable to open Mail Message file ' + TheFileName + '!' ,
- mtError , [mbok],0 );
- Socket1.OutOfBand := 'ABOR'+#13#10;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- result := 0;
- exit;
- end;
- TotalGotten := GetMessageHeader( TheHeaderSL );
- for Counter_1 := 0 to TheHeaderSL.Count - 1 do
- Writeln( TheMessageFile , TheHeaderSL.Strings[ Counter_1 ] );
- repeat
- TheResult := GetPOP3ServerExtendedResponse( TheReturnPChar );
- TotalGotten := TotalGotten + StrLen( TheReturnPChar ) + 2;
- if StrLen( TheReturnPChar ) > 255 then
- begin
- Getmem( TheHoldingPChar , 255 );
- while StrLen( TheReturnPChar ) > 255 do
- begin
- StrCopy( TheHoldingPChar , '' );
- StrMove( TheHoldingPChar , TheReturnPChar , 255 );
- TheReturnPChar := TheReturnPChar + 256;
- TheReturnString := StrPas( TheHoldingPChar );
- Writeln( TheMessageFile , TheReturnString );
- end;
- StrCopy( TheHoldingPChar , '' );
- StrMove( TheHoldingPChar , TheReturnPChar , StrLen( TheReturnPChar ));
- TheReturnString := StrPas( TheHoldingPChar );
- TheReturnString := '\' + TheReturnString;
- Writeln( TheMessageFile , TheReturnString );
- FreeMem( TheHoldingPChar , 255 );
- end
- else
- begin
- TheReturnString := StrPas( TheReturnPChar );
- Writeln( TheMessageFile , TheReturnString );
- end;
- until (( GlobalAbortedFlag ) or ( TheResult = TCPIP_STATUS_COMPLETED ));
- FreeMem( TheReturnPChar , 514 );
- CloseFile( TheMessageFile );
- Result := TotalGotten;
- end;
-
- { This method Gets all the Article Listings for a newsgroup which have not been }
- { Downloaded and gets them into text files. It displays Article count, # & bytes }
- { in the status line during the process. }
- function TPOP3SMTPComponent.DownloadAllMessageListings(
- TheEMBRecord : PEMailMailBoxRecord ) : Boolean;
- var WorkingList : TList;
- TheEMMRecord : PEMailMessageRecord;
- Counter_1 : Integer;
- WorkingID ,
- WorkingNumber : Integer;
- WorkingFileName : String;
- BytesToGet : Longint;
- TotalMessages : Integer;
- WorkingSL : TStringList;
- BytesGotten : Longint;
- begin
- Result := true;
- TotalMessages := CheckAllNewMail( BytesToGet );
- if TotalMessages < 0 then exit;
- if TotalMessages = 0 then
- begin
- MessageDlg( 'No New Mail!' , mtInformation, [mbOK],0);
- exit;
- end;
- with TheEMBRecord^ do
- begin
- WorkingID := MBIDNumber;
- WorkingNumber := MBMaxMsgNumber;
- WorkingList := TList( MBLTag );
- WorkingSL := TStringList.Create;
- for Counter_1 := 1 to TotalMessages do
- begin
- New( TheEMMRecord );
- WorkingNumber := WorkingNumber + 1;
- with TheEMMRecord^ do
- begin
- WorkingFileName := 'EM' + IntToStr( WorkingNumber );
- if Length( WorkingFileName ) > 8 then WorkingFileName :=
- Copy( WorkingFileName , 1 , 8 );
- WorkingFileName := WorkingFileName + '.' +
- IntToStr( WorkingID );
- MRFileName := WorkingFileName;
- WorkingFileName := MailPath + '\' + WorkingFileName;
- BytesGotten := DownloadMessageListing( Counter_1 , WorkingFileName , WorkingSL );
- if EMRemoteDeletionVector = 2 then DeleteMailItem( Counter_1 );
- UpdateGauge( BytesGotten , BytesToGet );
- MRMailBoxName := MBName;
- MRMessageSubject := GetHeaderSubject( WorkingSL );
- MRMessageRecipient := GetHeaderRecipient( WorkingSL );
- MRMessageSender := GetHeaderSender( WorkingSL );
- MRCarbonCopy := GetHeaderCarbons( WorkingSL );
- MRBlindCarbonCopy := GetHeaderBlindCarbons( WorkingSL );
- MRDateTime := GetHeaderDateTime( WorkingSL );
- MRRead := false;
- MRSent := false;
- MRFileName := ExtractFileName( WorkingFileName );
- WorkingList.Add( TheEMMRecord );
- end;
- end;
- UpdateGauge( BytesToGet , BytesToGet );
- MBLTag := Longint( WorkingList );
- MBMaxMsgNumber := WorkingNumber;
- MBTotal := MBTotal + TotalMessages;
- MBUnReadTotal := MBUnReadTotal + TotalMessages;
- Result := true;
- end;
- end;
-
- { This sends FTP progress text to the Inet form }
- procedure TPOP3SMTPComponent.ShowProgressErrorText( WhatText : String );
- begin
- CCInetCCForm.ShowProgressErrorText( WhatText );
- end;
-
- { This is a core function! It performs an FTP command and if no timeout }
- { return a preliminary ok. }
- function TPOP3SMTPComponent.PerformPOP3Command(
- TheCommand : string;
- const TheArguments : array of const ) : Integer;
- var TheBuffer : string; { Text buffer }
- begin
- { If command in progress send back -1 error }
- if POP3CommandInProgress then
- begin
- Result := -1;
- exit;
- end;
- { Set status variable }
- POP3CommandInProgress := True;
- { Set global error code }
- GlobalErrorCode := 0;
- { Format output string }
- TheBuffer := Format( TheCommand , TheArguments );
- { Preset failure code }
- Result := TCPIP_STATUS_FATAL_ERROR;
- { If invalid socket or no connection abort }
- if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
- exit;
- { Send the buffer plus EOL chars }
- Socket1.StringData := TheBuffer + #13#10;
- { if abort due to timeout or other error exit }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Otherwise return preliminary code }
- Result := TCPIP_STATUS_PRELIMINARY;
- end;
-
- { This function gets up to 255 chars of data plus a return code from FTP serv }
- function TPOP3SMTPComponent.GetPOP3ServerResponse(
- var ResponseString : String ) : integer;
- var
- { Buffer string for response line }
- TheBuffer : string;
- { Pointer to the response string }
- BufferPointer : array[0..255] of char absolute TheBuffer;
- { Character to check for response code }
- ResponseChar : char;
- { Pointers into returned string }
- TheIndex ,
- TheLength : integer;
- { Control variable }
- LeftoversInPan ,
- Finished : Boolean;
- begin
- { Preset fatal error }
- Result := TCPIP_STATUS_FATAL_ERROR;
- { Start loop control }
- LeftoversInPan := false;
- Finished := false;
- repeat
- { Do a peek }
- TheBuffer := Socket1.PeekData;
- { If timeout or other error exit }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Find end of line character }
- TheIndex := Pos( #10 , TheBuffer );
- if TheIndex = 0 then
- begin
- TheIndex := Pos( #13 , TheBuffer );
- if TheIndex = 0 then
- begin
- TheIndex := Pos( #0 , TheBuffer );
- if TheIndex = 0 then
- begin
- TheIndex := Length( TheBuffer );
- LeftoversInPan := True;
- LeftoverText := LeftoverText + TheBuffer;
- LeftoversOnTable := false;
- end;
- end;
- end;
- { If an end of line then process the line }
- if TheIndex > 0 then
- begin
- { Get length of string }
- TheLength := TheIndex;
- { Receive actual data }
- Socket1.CCSockReceive( Socket1.TheSocket ,
- @BufferPointer[ 1 ] ,
- TheLength );
- { Abort if timeout or error }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
- { Put in the length byte }
- BufferPointer[ 0 ] := Chr( TheLength );
- if LeftOversOnTable then
- begin
- LeftOversOnTable := false;
- ResponseString := LeftoverText + TheBuffer;
- TheBuffer := ResponseString;
- LeftoverText := '';
- end;
- if LeftoversInPan then
- begin
- LeftoversInPan := false;
- LeftoversOnTable := true;
- end;
- { Get first number character }
- ResponseChar := TheBuffer[ 1 ];
- { Get the value of the number from 1 to 5 }
- if (( ResponseChar = '+' ) or ( ResponseChar = '-' )) then
- begin
- Finished := true;
- if ResponseChar = '+' then Result := TCPIP_STATUS_COMPLETED
- else Result := TCPIP_STATUS_FATAL_ERROR;
- end;
- end
- else
- begin
- end;
- until ( Finished and ( not LeftoversOnTable ));
- { Return buffer as response string }
- ResponseString := TheBuffer;
- ResponseString := Copy( ResponseString , 1, Length( ResponseString ) - 2 );
- end;
-
- { Boilerplate error routine }
- procedure TPOP3SMTPComponent.POP3SMTPSocketsErrorOccurred( Sender : TObject;
- ErrorCode : Integer;
- TheMessage : String );
- begin
- CCInetCCForm.SocketsErrorOccurred( Sender,ErrorCode,TheMessage );
- end;
-
- { This is the POP3SMTP components POP3 initial connection routine }
- function TPOP3SMTPComponent.EstablishPOP3Connection(
- PCRPointer : PConnectionsRecord ) : Boolean;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- begin
- { Set default FTP Port value }
- Socket1.PortName := '110';
- { Get the ip address from the record }
- Socket1.IPAddressName := PCRPointer^.CIPAddress;
- { Set blocking mode }
- Socket1.AsynchMode := False;
- { Clear condition variables }
- GlobalErrorCode := 0;
- GlobalAbortedFlag := false;
- { Actually attempt to connect }
- Socket1.CCSockConnect;
- { Check if connected }
- if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 ) or
- ( Socket1.TheSocket = INVALID_SOCKET )) then
- begin { Didn't connect; signal error and abort }
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'POP3 Host %s Connection Failed!' ,
- [ PCRPointer^.CIPAddress ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := False;
- { leave }
- exit;
- end
- else
- begin
- Connection_Established := true;
- { Signal successful connection }
- TheReturnString := DoCStyleFormat(
- 'Connected on Local port: %s with IP: %s',
- [ Socket1.GetSocketPort( Socket1.TheSocket ),
- Socket1.GetSocketIPAddress( Socket1.TheSocket )]);
- { Put result in progress and status line }
- CCINetCCForm.AddProgressText( TheReturnString );
- CCINetCCForm.ShowProgressText( TheReturnString );
- TheReturnString := DoCStyleFormat(
- 'Connected to Remote port: %s with IP: %s',
- [ Socket1.GetSocketPeerPort( Socket1.TheSocket ),
- Socket1.GetSocketPeerIPAddress( Socket1.TheSocket )]);
- { Put result in progress and status line }
- CCINetCCForm.AddProgressText( TheReturnString );
- CCINetCCForm.ShowProgressText( TheReturnString );
- TheReturnString := DoCStyleFormat( 'Successfully connected to %s',
- [ Socket1.IPAddressName ]);
- { Put result in progress and status line }
- CCINetCCForm.AddProgressText( TheReturnString );
- CCINetCCForm.ShowProgressText( TheReturnString );
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'POP3 Host %s Connection Failed!' ,
- [ PCRPointer^.CIPAddress ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := False;
- { leave }
- exit;
- end
- else Result := true; { Signal no problem }
- end;
- end;
-
- { This sends FTP progress text to the Inet form }
- procedure TPOP3SMTPComponent.AddProgressText( WhatText : String );
- begin
- CCInetCCForm.AddProgressText( WhatText );
- end;
-
- { This sends FTP progress text to the Inet form }
- procedure TPOP3SMTPComponent.ShowProgressText( WhatText : String );
- begin
- CCInetCCForm.ShowProgressText( WhatText );
- end;
-
- { This is a clever c-style formatting trick }
- function TPOP3SMTPComponent.DoCStyleFormat(
- TheText : string;
- const TheArguments : array of const ) : String;
- begin
- Result := Format( TheText , TheArguments ) + #13#10;
- end;
-
- { This is the FTP components USER login routine }
- function TPOP3SMTPComponent.LoginUser(
- PCRPointer : PConnectionsRecord ) : Boolean;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- begin
- TheReturnString :=
- DoCStyleFormat( 'USER %s' ,
- [ PCRPointer^.CUserName ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Begin login sequence with user name }
- TheResult := PerformPOP3Command( 'USER %s',
- [ PCRPointer^.CUserName ] );
- if TheResult <> TCPIP_STATUS_PRELIMINARY then
- begin
- POP3CommandInProgress := false;
- Result := false;
- exit;
- end;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'POP3 Host %s Login Failed!' ,
- [ PCRPointer^.CIPAddress ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := False;
- { leave }
- exit;
- end
- else Result := true; { Signal no problem }
- end;
-
- { This is the FTP components PASSWORD routine }
- function TPOP3SMTPComponent.SendPassword(
- PCRPointer : PConnectionsRecord ) : Boolean;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- begin
- TheReturnString := 'PASS XXXXXX' + #13#10;
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Send Password sequence }
- TheResult := PerformPOP3Command( 'PASS %s',
- [ PCRPointer^.CPassword ] );
- if TheResult <> TCPIP_STATUS_PRELIMINARY then
- begin
- Result := false;
- POP3CommandInProgress := false;
- exit;
- end;
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'POP3 Host %s Login Failed!' ,
- [ PCRPointer^.CIPAddress ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := False;
- { leave }
- exit;
- end
- else Result := true; { Signal no problem }
- end;
-
- { This is the FTP component constructor; it creates 2 sockets }
- constructor TPOP3SMTPComponent.Create( AOwner : TComponent );
- begin
- { do inherited create }
- inherited Create( AOwner );
- { Create sockets, put in their parents, and error procs }
- Socket1 := TCCSocket.Create( Self );
- Socket1.Parent := Self;
- Socket1.OnErrorOccurred := POP3SMTPSocketsErrorOccurred;
- { Set up booleans }
- Connection_Established := false;
- POP3CommandInProgress := false;
- end;
-
- { This is the FTP component destructor; it frees 2 sockets }
- destructor TPOP3SMTPComponent.Destroy;
- begin
- { Free the sockets }
- Socket1.Free;
- { and call inherited }
- inherited Destroy;
- end;
-
- { This is the POP3 components QUIT routine }
- function TPOP3SMTPComponent.POP3Disconnect : Boolean;
- var TheReturnString : String; { Internal string holder }
- TheResult : Integer; { Internal int holder }
- begin
- TheReturnString :=
- DoCStyleFormat( 'QUIT' ,
- [ nil ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString );
- { Begin login sequence with user name }
- PerformPOP3Command( 'QUIT', [ nil ] );
- repeat
- TheResult := GetPOP3ServerResponse( TheReturnString );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressText( TheReturnString + #13#10 );
- until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
- POP3CommandInProgress := false;
- if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
- begin
- { Do clever C formatting trick }
- TheReturnString :=
- DoCStyleFormat( 'EMail Host Connection Failed!' ,
- [ nil ] );
- { Put result in progress and status line }
- AddProgressText( TheReturnString );
- ShowProgressErrorText( TheReturnString );
- { Signal error }
- Result := False;
- { leave }
- exit;
- end
- else Result := true; { Signal no problem }
- end;
-
-
- procedure TPOP3SMTPComponent.UpdateGauge( BytesFinished , TotalToHandle : longint );
- begin
- CCInetCCForm.UpdateMailGauge( BytesFinished , TotalToHandle );
- end;
-
- end.
-