| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- { $HDR$}
- {**********************************************************************}
- { Unit archived using Team Coherence }
- { Team Coherence is Copyright 2002 by Quality Software Components }
- { }
- { For further information / comments, visit our WEB site at }
- { http://www.TeamCoherence.com }
- {**********************************************************************}
- {}
- { $Log: 10279: IdPOP3Server.pas
- {
- Rev 1.1 2/19/2003 5:59:48 PM BGooijen
- Now an error is returned when the parameters of APOP and TOP are wrong.
- before the change the connection was closed on such error.
- }
- {
- { Rev 1.0 2002.11.12 10:48:00 PM czhower
- }
- unit IdPOP3Server;
- interface
- {
- Indy POP3 Server
- Original Programmer: Luke Croteau
- Current Maintainer: Andrew Neillans
- No Copyright. Code is given to the Indy Pit Crew.
- Quick Notes:
- A few of the methods return a default message number if a number isn't entered.
- The LIST, DELE, RETR, UIDL, and TOP command will return a -1 in the parameters
- if the value isn't specified by the client.
- Some functions require this capability. For example, the LIST command can operate
- either by a certain message number or a with no arguments. See RFC1939 for details.
- Revision History:
- 02-May-2002: Andy Neillans
- - Bug Fix 551116 - StrToIntDef needed 'trimming#
- 30-Apr-2002: Allen O'Neill.
- - Failsafe .. added check for ParamCount in reading Username and password - previously
- if either were sent in blank we got an IndexOutOfBounds error.
- 13-Apr-2002:
- - Corrections :) And some Greeting.Text / And other response, glitches
- 3-Apr-2002:
- - Minor changes. (Greeting.Text)
- 1-Apr-2002:
- - Completed rewrite! At Last!
- 15-Feb-2002: Andy
- - Started rewrite for use of CommandHandlers
- 13-Jan-2002:
- -Fixed formatting bug.
- 26-Dec-2000:
- -Andrew Neillans found a bug on line 157. Originally it was
- If Assigned(OnCommandLIST) then OnCommandRETR(...).
- Changed to OnCommandLIST(...). Thanks Andrew!
- 29-Oct-2000:
- -I discovered I really shouldn't program at night.
- The error wasn't that it shouldn't be Succ (Because it should), but
- because I forgot to implement LIST
- 27-Oct-2000:
- -Fixed a dumb bug. Originally coded command parsing as Succ(PosInStrArray)
- Should be just PosInStrArray b/c it is not a dynamic array. The bounds
- are constant.
- 25-Oct-2000:
- -Created Unit.
- -Created new IdPOP3Server Server Component according to RFC 1939
- }
- uses
- Classes,
- IdAssignedNumbers,
- IdGlobal,
- IdTCPServer,
- IdMailBox;
- type
- TIdPOP3ServerState = (Auth, Trans, Update);
- TIdPOP3ServerThread = class(TIdPeerThread)
- protected
- // what needs to be stored...
- fUser : String;
- fPassword : String;
- fState :TIdPOP3ServerState;
- procedure BeforeRun; override;
- public
- constructor Create(ACreateSuspended: Boolean = True); override;
- destructor Destroy; override;
- // Any functions for vars
- property Username : String read fUser write fUser;
- property Password : String read fPassword write fPassword;
- property State : TIdPOP3ServerState read fState write fState;
- end;
- TIdPOP3ServerNoParamEvent = procedure (ASender: TIdCommand) of object;
- TIdPOP3ServerMessageNumberEvent = procedure (ASender: TIdCommand; AMessageNum :Integer) of object;
- TIdPOP3ServerLogin = procedure (AThread :TIdPeerThread; LThread : TIdPOP3ServerThread) of object;
- TIdPOP3ServerAPOPCommandEvent = procedure (ASender: TIdCommand; AMailboxID :String; ADigest :String) of object;
- TIdPOP3ServerTOPCommandEvent = procedure (ASender: TIdCommand; AMessageNum :Integer; ANumLines :Integer) of object;
- TIdPOP3Server = class(TIdTcpServer)
- protected
- fCommandLogin : TIdPOP3ServerLogin;
- fCommandList,
- fCommandRetr,
- fCommandDele,
- fCommandUIDL : TIdPOP3ServerMessageNumberEvent;
- fCommandTop : TIdPOP3ServerTOPCommandEvent;
- fCommandQuit,
- fCommandStat,
- fCommandRset : TIdPOP3ServerNoParamEvent;
- fCommandAPOP : TIdPOP3ServerAPOPCommandEvent;
- // CommandHandlers
- procedure CommandUser(ASender: TIdCommand); //
- procedure CommandPass(ASender: TIdCommand); //
- procedure CommandList(ASender: TIdCommand); //
- procedure CommandRetr(ASender: TIdCommand); //
- procedure CommandDele(ASender: TIdCommand); //
- procedure CommandQuit(ASender: TIdCommand); //
- procedure CommandAPOP(ASender: TIdCommand); //
- procedure CommandStat(ASender: TIdCommand); //
- procedure CommandRset(ASender: TIdCommand); //
- procedure CommandTop(ASender: TIdCommand); //
- procedure CommandUIDL(ASender: TIdCommand); //
- procedure InitializeCommandHandlers; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property DefaultPort default IdPORT_POP3;
- // These procedures / functions are exposed
- property CheckUser : TIdPOP3ServerLogin read fCommandLogin write fCommandLogin;
- property OnLIST : TIdPOP3ServerMessageNumberEvent read fCommandList write fCommandList;
- property OnRETR : TIdPOP3ServerMessageNumberEvent read fCommandRetr write fCommandRetr;
- property OnDELE : TIdPOP3ServerMessageNumberEvent read fCommandDele write fCommandDele;
- property OnUIDL : TIdPOP3ServerMessageNumberEvent read fCommandUidl write fCommandUidl;
- property OnSTAT : TIdPOP3ServerNoParamEvent read fCommandStat write fCommandStat;
- property OnTOP : TIdPOP3ServerTOPCommandEvent read fCommandTop write fCommandTop;
- property OnRSET : TIdPOP3ServerNoParamEvent read fCommandRset write fCommandRset;
- property OnQUIT : TIdPOP3ServerNoParamEvent read fCommandQuit write fCommandQuit;
- property OnAPOP : TIdPOP3ServerAPOPCommandEvent read fCommandApop write fCommandApop;
- End;
- implementation
- uses
- IdResourceStrings,
- IdRFCReply,
- SysUtils;
- procedure TIdPOP3Server.InitializeCommandHandlers;
- begin
- inherited;
- with CommandHandlers.Add do begin
- Command := 'USER';
- OnCommand := CommandUSER;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'PASS';
- OnCommand := CommandPass;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'LIST';
- OnCommand := CommandList;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'RETR';
- OnCommand := CommandRetr;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'DELE';
- OnCommand := CommandDele;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'UIDL';
- OnCommand := CommandUIDL;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'STAT';
- OnCommand := CommandSTAT;
- ParseParams := False;
- end;
- with CommandHandlers.Add do begin
- Command := 'TOP';
- OnCommand := CommandTOP;
- ParseParams := True;
- end;
- with CommandHandlers.Add do begin
- Command := 'NOOP';
- ReplyNormal.Text.Text := '+OK NOOP';
- ParseParams := False;
- end;
- with CommandHandlers.Add do begin
- Command := 'APOP';
- OnCommand := CommandAPOP;
- ParseParams := True;
- End;
- with CommandHandlers.Add do begin
- Command := 'RSET';
- ReplyNormal.Text.Text := '+OK Reset';
- OnCommand := CommandRset;
- ParseParams := False;
- end;
- with CommandHandlers.Add do begin
- Command := 'QUIT';
- OnCommand := CommandQuit;
- Disconnect := True;
- ReplyNormal.Text.Text := '+OK Closing communication channel'; // USE ResourceString ??
- ParseParams := False;
- end;
- end;
- { Command Handler Functions here }
- procedure TIdPOP3Server.CommandUser(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- if ASender.Params.Count > 0 then
- LThread.Username := ASender.Params.Strings[0];
- ASender.Thread.Connection.WriteLn('+OK Password required');
- end;
- procedure TIdPOP3Server.CommandPass(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- if ASender.Params.Count > 0 then
- LThread.Password := ASender.Params.Strings[0];
- if Assigned(CheckUser) then
- CheckUser(ASender.Thread, LThread);
- // User to set return state of LThread.State as required.
- If LThread.State <> Trans Then
- ASender.Thread.Connection.Writeln('-ERR Login failed')
- Else
- ASender.Thread.Connection.Writeln('+OK Login OK');
- end;
- procedure TIdPOP3Server.CommandList(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandList) Then
- OnList(ASender, StrToIntDef(Trim(ASender.Params.Text), -1))
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['LIST']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandRetr(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandRetr) Then
- OnRetr(ASender, StrToIntDef(Trim(ASender.Params.Text), -1))
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['RETR']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandDele(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandDele) Then
- Begin
- Try
- StrToInt(Trim(ASender.Params.Text));
- OnDele(ASender, StrToInt(Trim(ASender.Params.Text)))
- Except
- ASender.Thread.Connection.WriteLn('-ERR Invalid Message Number'); // RS
- End;
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['DELE']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandQuit(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandQuit) Then OnQuit(ASender)
- End;
- end;
- procedure TIdPOP3Server.CommandAPOP(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Auth Then
- Begin
- If Assigned(fCommandAPOP) Then
- Begin
- if ASender.Params.Count = 2 then begin
- OnAPOP(ASender, ASender.Params.Strings[0], ASender.Params.Strings[1]);
- // User to set return state of LThread.State as required.
- If LThread.State <> Trans Then begin
- ASender.Thread.Connection.Writeln('-ERR Login failed');
- End
- end else begin
- ASender.Thread.Connection.WriteLn('-ERR Invalid Syntax'); //RS
- end
- end
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['APOP']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Wrong State');
- end;
- procedure TIdPOP3Server.CommandStat(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandStat) Then
- OnStat(ASender)
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['STAT']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandRset(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandRSET) Then
- OnRset(ASender)
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['RSET']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandTop(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then Begin
- If Assigned(fCommandTop) Then Begin
- if ASender.Params.Count = 2 then begin
- If (StrToIntDef(Trim(ASender.Params.Strings[0]), -1) <> -1) AND (StrToIntDef(Trim(ASender.Params.Strings[1]), -1) <> -1) Then begin
- OnTop(ASender, StrToInt(ASender.Params.Strings[0]), StrToInt(ASender.Params.Strings[1]))
- end Else begin
- ASender.Thread.Connection.WriteLn('-ERR Invalid Syntax'); //RS
- End;
- end else begin
- ASender.Thread.Connection.WriteLn('-ERR Invalid Syntax'); //RS
- end
- End Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['TOP']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- procedure TIdPOP3Server.CommandUIDL(ASender: TIdCommand);
- Var
- LThread: TIdPOP3ServerThread;
- begin
- LThread := TIdPOP3ServerThread(ASender.Thread);
- If LThread.State = Trans Then
- Begin
- If Assigned(fCommandUidl) Then
- OnUidl(ASender, StrToIntDef(Trim(ASender.Params.Text), -1))
- Else
- ASender.Thread.Connection.WriteLn('-ERR ' + Format(RSPOP3SVRNotHandled, ['UIDL']));
- End
- Else
- ASender.Thread.Connection.WriteLn('-ERR Please login first'); // RS
- end;
- { Constructor / Destructors }
- constructor TIdPOP3Server.Create(AOwner: TComponent);
- begin
- inherited;
- ThreadClass := TIdPOP3ServerThread;
- DefaultPort := IdPORT_POP3;
- Greeting.Text.Text := '+OK Welcome to Indy POP3 Server'; // RS
- ReplyUnknownCommand.Text.Text := '-ERR Sorry, Unknown Command'; // RS
- end;
- destructor TIdPOP3Server.Destroy;
- begin
- inherited;
- end;
- { TIdPOP3ServerThread }
- constructor TIdPOP3ServerThread.Create(ACreateSuspended: Boolean);
- begin
- inherited;
- FUser := '';
- fState := Auth;
- end;
- procedure TIdPOP3ServerThread.BeforeRun;
- begin
- FUser := '';
- fState := Auth;
- fPassword := '';
- inherited BeforeRun;
- end;
- destructor TIdPOP3ServerThread.Destroy;
- begin
- inherited;
- end;
- end.
|