{ $Project$ $Workfile$ $Revision$ $DateUTC$ $Id$ This file is part of the Indy (Internet Direct) project, and is offered under the dual-licensing agreement described on the Indy website. (http://www.indyproject.org/) Copyright: (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved. } { $Log$ } { Rev 1.6 2/8/05 5:58:32 PM RLebeau Updated InitComponent() to call TIdReply.SetReply() instead of setting the Code and Text properties individually Rev 1.5 11/15/04 11:31:20 AM RLebeau Bug fix for OutboundConnect() assigning the IOHandler.ConnectTimeout property before the IOHandler has been assigned. Rev 1.4 11/14/04 11:39:24 AM RLebeau Updated OutboundConnect() to send the Greeting Rev 1.3 5/18/04 1:02:02 PM RLebeau Removed GetReplyClass() and GetRepliesClass() overrides. Rev 1.2 5/16/04 5:28:40 PM RLebeau Added GetReplyClass() and GetRepliesClass() overrides. Rev 1.1 2004.02.03 5:45:52 PM czhower Name changes Rev 1.0 2/2/2004 4:11:36 PM JPMugaas Recased to be consistant with IdPOP3 and IdPOP3Server. I also fixed several bugs that could cause AV's. Rev 1.0 2/1/2004 4:22:48 AM JPMugaas Components from IdMappedPort are now in their own units. } unit IdMappedPOP3; interface {$i IdCompilerDefines.inc} uses {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} Classes, {$ENDIF} IdAssignedNumbers, IdMappedPortTCP, IdMappedTelnet, IdReplyPOP3, IdTCPServer; type TIdMappedPOP3Context = class (TIdMappedTelnetContext) protected FErrorMsg: String; FGreeting: String; FUserName: String; procedure OutboundConnect; override; public property ErrorMsg: String read FErrorMsg; property Greeting: String read FGreeting; property UserName: String read FUsername write FUserName; end; TIdMappedPOP3 = class (TIdMappedTelnet) protected FReplyUnknownCommand: TIdReplyPOP3; FGreeting: TIdReplyPOP3; FUserHostDelimiter: String; procedure InitComponent; override; procedure SetGreeting(AValue: TIdReplyPOP3); procedure SetReplyUnknownCommand(const AValue: TIdReplyPOP3); public {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} constructor Create(AOwner: TComponent); reintroduce; overload; {$ENDIF} destructor Destroy; override; published property Greeting : TIdReplyPOP3 read FGreeting write SetGreeting; property ReplyUnknownCommand: TIdReplyPOP3 read FReplyUnknownCommand write SetReplyUnknownCommand; property DefaultPort default IdPORT_POP3; property MappedPort default IdPORT_POP3; property UserHostDelimiter: String read FUserHostDelimiter write FUserHostDelimiter; end; implementation uses IdGlobal, IdException, IdIOHandlerSocket, IdResourceStringsProtocols, IdTCPClient, IdTCPConnection, SysUtils; { TIdMappedPOP3 } {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS} constructor TIdMappedPOP3.Create(AOwner: TComponent); begin inherited Create(AOwner); end; {$ENDIF} destructor TIdMappedPOP3.Destroy; begin FreeAndNil(FReplyUnknownCommand); FreeAndNil(FGreeting); inherited Destroy; end; procedure TIdMappedPOP3.InitComponent; Begin inherited InitComponent; FUserHostDelimiter := '#';//standard {Do not Localize} FGreeting := TIdReplyPOP3.Create(nil); FGreeting.SetReply('+OK', RSPop3ProxyGreeting); {Do not Localize} FReplyUnknownCommand := TIdReplyPOP3.Create(nil); FReplyUnknownCommand.SetReply('-ERR', RSPop3UnknownCommand); {Do not Localize} DefaultPort := IdPORT_POP3; MappedPort := IdPORT_POP3; FContextClass := TIdMappedPOP3Context; end; procedure TIdMappedPOP3.SetGreeting(AValue: TIdReplyPOP3); begin FGreeting.Assign(AValue); end; procedure TIdMappedPOP3.SetReplyUnknownCommand(const AValue: TIdReplyPOP3); begin FReplyUnknownCommand.Assign(AValue); end; { TIdMappedPOP3Context } procedure TIdMappedPOP3Context.OutboundConnect; var LHostPort, LPop3Cmd: String; LServer: TIdMappedPOP3; Begin //don`t call inherited, NEW behavior LServer := TIdMappedPOP3(Server); Connection.IOHandler.Write(LServer.Greeting.FormattedReply); FOutboundClient := TIdTCPClient.Create(nil); TIdTcpClient(FOutboundClient).Port := LServer.MappedPort; TIdTcpClient(FOutboundClient).Host := LServer.MappedHost; FAllowedConnectAttempts := LServer.AllowedConnectAttempts; LServer.DoLocalClientConnect(Self); repeat if FAllowedConnectAttempts > 0 then begin Dec(FAllowedConnectAttempts); end; try // Greeting LHostPort := Trim(Connection.IOHandler.ReadLn);//USER username#host OR QUIT LPop3Cmd := Fetch(LHostPort, ' ', True); {Do not Localize} if TextIsSame(LPop3Cmd, 'QUIT') then {Do not Localize} begin Connection.IOHandler.WriteLn('+OK ' + RSPop3QuitMsg); {Do not Localize} Connection.Disconnect; Break; end else if TextIsSame(LPop3Cmd, 'USER') then {Do not Localize} begin FUserName := Fetch(LHostPort, LServer.FUserHostDelimiter, True, False);//?:CaseSensetive LHostPort := TrimLeft(LHostPort); //TrimRight above LServer.ExtractHostAndPortFromLine(Self, LHostPort); end else begin Connection.IOHandler.Write(LServer.ReplyUnknownCommand.FormattedReply); Continue; end;//if if Length(TIdTCPClient(FOutboundClient).Host) < 1 then begin raise EIdException.Create(RSEmptyHost); end; TIdTCPClient(FOutboundClient).ConnectTimeout := FConnectTimeOut; TIdTCPClient(FOutboundClient).Connect; //Read Pop3 Banner for OnOutboundClientConnect FGreeting := FOutboundClient.IOHandler.ReadLn; FOutboundClient.IOHandler.WriteLn('USER ' + FUserName); {Do not Localize} except on E: Exception do // DONE: Handle connect failures begin FErrorMsg := '[' + E.ClassName + '] ' + E.Message; {Do not Localize} DoException(E); Connection.IOHandler.WriteLn('-ERR ' + FErrorMsg); end; end;//trye until FOutboundClient.Connected or (FAllowedConnectAttempts < 1); if FOutboundClient.Connected then begin LServer.DoOutboundClientConnect(Self); end else begin Connection.Disconnect; //prevent all next work end; end; end.