628 lines
18 KiB
Plaintext
628 lines
18 KiB
Plaintext
|
{
|
||
|
$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.39 1/7/05 3:29:12 PM RLebeau
|
||
|
Fix for AV in Notification()
|
||
|
|
||
|
Rev 1.38 12/21/04 1:51:42 AM RLebeau
|
||
|
Bug fix for Capa() method.
|
||
|
|
||
|
Rev 1.37 11/27/04 2:48:22 AM RLebeau
|
||
|
Fixed bug in ownership of SASLMechanisms property
|
||
|
|
||
|
Rev 1.36 10/26/2004 10:35:42 PM JPMugaas
|
||
|
Updated ref.
|
||
|
|
||
|
Rev 1.35 2004.04.18 1:39:26 PM czhower
|
||
|
Bug fix for .NET with attachments, and several other issues found along the
|
||
|
way.
|
||
|
|
||
|
Rev 1.34 2004.04.07 6:02:42 PM czhower
|
||
|
Implemented AutoLogin in a better manner.
|
||
|
|
||
|
Rev 1.33 2004.04.07 5:53:56 PM czhower
|
||
|
.NET overload
|
||
|
|
||
|
Rev 1.32 2004.03.06 1:31:48 PM czhower
|
||
|
To match Disconnect changes to core.
|
||
|
|
||
|
Rev 1.31 2004.02.03 5:44:12 PM czhower
|
||
|
Name changes
|
||
|
|
||
|
Rev 1.30 2004.02.03 2:12:18 PM czhower
|
||
|
$I path change
|
||
|
|
||
|
Rev 1.29 1/25/2004 3:11:36 PM JPMugaas
|
||
|
SASL Interface reworked to make it easier for developers to use.
|
||
|
SSL and SASL reenabled components.
|
||
|
|
||
|
Rev 1.28 1/21/2004 3:27:06 PM JPMugaas
|
||
|
InitComponent
|
||
|
|
||
|
Rev 1.27 1/12/04 12:22:40 PM RLebeau
|
||
|
Updated RetrieveMailboxSize() and RetrieveMsgSize() to support responses that
|
||
|
contain additional data after the octet values.
|
||
|
|
||
|
Rev 1.26 22/12/2003 00:45:12 CCostelloe
|
||
|
.NET fixes
|
||
|
|
||
|
Rev 1.25 10/19/2003 5:42:36 PM DSiders
|
||
|
Added localization comments.
|
||
|
|
||
|
Rev 1.24 10/11/2003 7:14:34 PM BGooijen
|
||
|
Changed IdCompilerDefines.inc path
|
||
|
|
||
|
Rev 1.23 10/10/2003 11:39:40 PM BGooijen
|
||
|
Compiles in DotNet now
|
||
|
|
||
|
Rev 1.22 6/15/2003 01:17:10 PM JPMugaas
|
||
|
Intermediate class no longer used. We use the SASL functionality right from
|
||
|
the TIdSASLList.
|
||
|
|
||
|
Rev 1.21 6/4/2003 04:10:36 PM JPMugaas
|
||
|
Removed hacked GetInternelResponse.
|
||
|
|
||
|
Updated to use Kudzu's new string reply code.
|
||
|
|
||
|
Rev 1.20 5/26/2003 04:28:16 PM JPMugaas
|
||
|
Removed GenerateReply and ParseResponse calls because those functions are
|
||
|
being removed.
|
||
|
|
||
|
Rev 1.19 5/26/2003 12:23:58 PM JPMugaas
|
||
|
|
||
|
Rev 1.18 5/25/2003 03:54:46 AM JPMugaas
|
||
|
|
||
|
Rev 1.17 5/25/2003 03:45:56 AM JPMugaas
|
||
|
|
||
|
Rev 1.16 5/22/2003 05:27:52 PM JPMugaas
|
||
|
|
||
|
Rev 1.16 5/20/2003 02:29:42 PM JPMugaas
|
||
|
Updated with POP3Reply object.
|
||
|
|
||
|
Rev 1.15 5/10/2003 10:10:46 PM JPMugaas
|
||
|
Bug fixes.
|
||
|
|
||
|
Rev 1.14 5/8/2003 08:44:16 PM JPMugaas
|
||
|
Moved some SASL authentication code down to an anscestor for reuse. WIll
|
||
|
clean up soon.
|
||
|
|
||
|
Rev 1.13 5/8/2003 03:18:14 PM JPMugaas
|
||
|
Flattened ou the SASL authentication API, made a custom descendant of SASL
|
||
|
enabled TIdMessageClient classes.
|
||
|
|
||
|
Rev 1.12 5/8/2003 11:28:10 AM JPMugaas
|
||
|
Moved feature negoation properties down to the ExplicitTLSClient level as
|
||
|
feature negotiation goes hand in hand with explicit TLS support.
|
||
|
|
||
|
Rev 1.11 5/8/2003 03:03:00 AM JPMugaas
|
||
|
Fixed a problem with SASL. It turns out that what was being processed with
|
||
|
something from a previous command. It also turned out that some charactors
|
||
|
were being removed from the SASL processing when they shouldn't have been.
|
||
|
|
||
|
Rev 1.10 5/8/2003 02:18:08 AM JPMugaas
|
||
|
Fixed an AV in IdPOP3 with SASL list on forms. Made exceptions for SASL
|
||
|
mechanisms missing more consistant, made IdPOP3 support feature feature
|
||
|
negotiation, and consolidated some duplicate code.
|
||
|
|
||
|
Rev 1.9 5/7/2003 04:58:34 AM JPMugaas
|
||
|
We now use the initial greeting message from the server when calculating the
|
||
|
parameter for the APOP command. Note that we were calling CAPA before APOP
|
||
|
and that could throw things off.
|
||
|
|
||
|
Rev 1.8 4/5/2003 02:06:24 PM JPMugaas
|
||
|
TLS handshake itself can now be handled.
|
||
|
|
||
|
Rev 1.7 3/27/2003 05:46:40 AM JPMugaas
|
||
|
Updated framework with an event if the TLS negotiation command fails.
|
||
|
Cleaned up some duplicate code in the clients.
|
||
|
|
||
|
Rev 1.6 3/19/2003 08:53:40 PM JPMugaas
|
||
|
Now should work with new framework.
|
||
|
|
||
|
Rev 1.5 3/17/2003 02:25:26 PM JPMugaas
|
||
|
Updated to use new TLS framework. Now can require that users use TLS. Note
|
||
|
that this setting create an incompatiability with Norton AntiVirus because
|
||
|
that does act as a "man in the middle" when intercepting E-Mail for virus
|
||
|
scanning.
|
||
|
|
||
|
Rev 1.4 3/13/2003 09:49:26 AM JPMugaas
|
||
|
Now uses an abstract SSL base class instead of OpenSSL so 3rd-party vendors
|
||
|
can plug-in their products.
|
||
|
|
||
|
Rev 1.3 2/24/2003 09:27:58 PM JPMugaas
|
||
|
|
||
|
Rev 1.2 12/15/2002 04:27:10 PM JPMugaas
|
||
|
POP3 now compiles and works in Indy 10.
|
||
|
|
||
|
Rev 1.1 12-15-2002 12:57:40 BGooijen
|
||
|
Added Top-command
|
||
|
|
||
|
Rev 1.0 11/13/2002 07:58:22 AM JPMugaas
|
||
|
|
||
|
2002-08-18 - J. Berg
|
||
|
- implement SASL, add CAPA and STLS
|
||
|
|
||
|
02 August 2002 - A. Neillans
|
||
|
- Bug fix:
|
||
|
[ 574171 ] TIdMessage not cleared before a retreive
|
||
|
|
||
|
11-10-2001 - J. Peter Mugaas
|
||
|
Added suggested code from Andrew P.Rybin that does the following:
|
||
|
-APOP Authentication Support
|
||
|
-unrecognized text header now displayed in exception message
|
||
|
-GetUIDL method
|
||
|
|
||
|
2001-AUG-31 DSiders
|
||
|
Changed TIdPOP3.Connect to use ATimeout when calling
|
||
|
inherited Connect.
|
||
|
|
||
|
2000-SEPT-28 SG
|
||
|
Added GetUIDL as from code by
|
||
|
|
||
|
2000-MAY-10 HH
|
||
|
Added RetrieveMailBoxSize and renamed RetrieveSize to RetrieveMsgSize.
|
||
|
Finished Connect.
|
||
|
|
||
|
2000-MARCH-03 HH
|
||
|
Converted to Indy
|
||
|
}
|
||
|
|
||
|
unit IdPOP3;
|
||
|
|
||
|
{ POP 3 (Post Office Protocol Version 3) }
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$i IdCompilerDefines.inc}
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
IdAssignedNumbers,
|
||
|
IdGlobal,
|
||
|
IdException,
|
||
|
IdExplicitTLSClientServerBase,
|
||
|
IdGlobalProtocols,
|
||
|
IdMessage,
|
||
|
IdMessageClient,
|
||
|
IdReply,
|
||
|
IdSASL,
|
||
|
IdSASLCollection,
|
||
|
IdBaseComponent,
|
||
|
IdUserPassProvider;
|
||
|
|
||
|
type
|
||
|
TIdPOP3AuthenticationType = (patUserPass, patAPOP, patSASL);
|
||
|
|
||
|
const
|
||
|
DEF_POP3USE_IMPLICIT_TLS = False;
|
||
|
DEF_ATYPE = patUserPass;
|
||
|
|
||
|
type
|
||
|
TIdPOP3 = class(TIdMessageClient)
|
||
|
protected
|
||
|
FAuthType : TIdPOP3AuthenticationType;
|
||
|
FAutoLogin: Boolean;
|
||
|
FAPOPToken : String;
|
||
|
FHasAPOP: Boolean;
|
||
|
FHasCAPA: Boolean;
|
||
|
FSASLMechanisms : TIdSASLEntries;
|
||
|
//
|
||
|
function GetReplyClass:TIdReplyClass; override;
|
||
|
function GetSupportsTLS: Boolean; override;
|
||
|
procedure SetSASLMechanisms(AValue: TIdSASLEntries);
|
||
|
procedure InitComponent; override;
|
||
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
||
|
public
|
||
|
function CheckMessages: Integer;
|
||
|
procedure Connect; override;
|
||
|
procedure Login; virtual;
|
||
|
destructor Destroy; override;
|
||
|
function Delete(const MsgNum: Integer): Boolean;
|
||
|
procedure DisconnectNotifyPeer; override;
|
||
|
procedure KeepAlive;
|
||
|
function List(const ADest: TStrings; const AMsgNum: Integer = -1): Boolean;
|
||
|
procedure ParseLIST(ALine: String; var VMsgNum, VMsgSize: Integer);
|
||
|
procedure ParseUIDL(ALine: String; var VMsgNum: Integer; var VUidl: String);
|
||
|
function Reset: Boolean;
|
||
|
function Retrieve(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
|
||
|
function RetrieveHeader(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
|
||
|
function RetrieveMsgSize(const MsgNum: Integer): Integer;
|
||
|
function RetrieveMailBoxSize: Int64;
|
||
|
function RetrieveRaw(const aMsgNo: Integer; const aDest: TStrings): boolean; overload;
|
||
|
function RetrieveRaw(const aMsgNo: Integer; const aDest: TStream): boolean; overload;
|
||
|
function RetrieveStats(var VMsgCount: Integer; var VMailBoxSize: Int64): Boolean;
|
||
|
function UIDL(const ADest: TStrings; const AMsgNum: Integer = -1): Boolean;
|
||
|
function Top(const AMsgNum: Integer; const ADest: TStrings; const AMaxLines: Integer = 0): boolean;
|
||
|
function CAPA: Boolean;
|
||
|
property HasAPOP: boolean read FHasAPOP;
|
||
|
property HasCAPA: boolean read FHasCAPA;
|
||
|
published
|
||
|
property AuthType : TIdPOP3AuthenticationType read FAuthType write FAuthType default DEF_ATYPE;
|
||
|
property AutoLogin: Boolean read FAutoLogin write FAutoLogin;
|
||
|
property Host;
|
||
|
property Username;
|
||
|
property UseTLS;
|
||
|
property Password;
|
||
|
property Port default IdPORT_POP3;
|
||
|
property SASLMechanisms : TIdSASLEntries read FSASLMechanisms write SetSASLMechanisms;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
EIdPOP3Exception = class(EIdException);
|
||
|
EIdDoesNotSupportAPOP = class(EIdPOP3Exception);
|
||
|
EIdUnrecognizedReply = class(EIdPOP3Exception);
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
IdFIPS,
|
||
|
IdHash,
|
||
|
IdHashMessageDigest,
|
||
|
IdTCPConnection,
|
||
|
IdSSL,
|
||
|
IdResourceStringsProtocols,
|
||
|
IdReplyPOP3,
|
||
|
IdCoderMIME,
|
||
|
SysUtils;
|
||
|
|
||
|
{ TIdPOP3 }
|
||
|
|
||
|
function TIdPOP3.CheckMessages: Integer;
|
||
|
var
|
||
|
LIgnore: Int64;
|
||
|
begin
|
||
|
// RLebeau: for backwards compatibility, raise an exception if STAT fails
|
||
|
if not RetrieveStats(Result, LIgnore) then begin
|
||
|
RaiseExceptionForLastCmdResult;
|
||
|
end;
|
||
|
// Only gets here if exception is not raised
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.Login;
|
||
|
var
|
||
|
S: String;
|
||
|
LMD5: TIdHashMessageDigest5;
|
||
|
begin
|
||
|
if UseTLS in ExplicitTLSVals then begin
|
||
|
if SupportsTLS then begin
|
||
|
if SendCmd('STLS','') = ST_OK then begin {Do not translate}
|
||
|
TLSHandshake;
|
||
|
end else begin
|
||
|
ProcessTLSNegCmdFailed;
|
||
|
end;
|
||
|
end else begin
|
||
|
ProcessTLSNotAvail;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
case FAuthType of
|
||
|
patAPOP: //APR
|
||
|
begin
|
||
|
if FHasAPOP then begin
|
||
|
CheckMD5Permitted;
|
||
|
LMD5 := TIdHashMessageDigest5.Create;
|
||
|
try
|
||
|
S := LowerCase(LMD5.HashStringAsHex(FAPOPToken+Password));
|
||
|
finally
|
||
|
LMD5.Free;
|
||
|
end;//try
|
||
|
SendCmd('APOP ' + Username + ' ' + S, ST_OK); {Do not Localize}
|
||
|
end else begin
|
||
|
raise EIdDoesNotSupportAPOP.Create(RSPOP3ServerDoNotSupportAPOP);
|
||
|
end;
|
||
|
end;
|
||
|
patUserPass:
|
||
|
begin //classic method
|
||
|
SendCmd('USER ' + Username, ST_OK); {Do not Localize}
|
||
|
SendCmd('PASS ' + Password, ST_OK); {Do not Localize}
|
||
|
end;//if APOP
|
||
|
patSASL:
|
||
|
begin
|
||
|
// SASL in POP3 did not originally support Initial-Response. It was added
|
||
|
// in RFC 2449 along with the CAPA command. If a server supports the CAPA
|
||
|
// command then it *should* also support Initial-Response as well, however
|
||
|
// many POP3 servers support CAPA but do not support Initial-Response
|
||
|
// (which was formalized in RFC 5034). So, until we can handle that
|
||
|
// descrepency better, we will simply disable Initial-Response for now.
|
||
|
|
||
|
FSASLMechanisms.LoginSASL('AUTH', FHost, IdGSKSSN_pop, [ST_OK], [ST_SASLCONTINUE], Self, Capabilities, 'SASL', False); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.InitComponent;
|
||
|
begin
|
||
|
inherited;
|
||
|
FAutoLogin := True;
|
||
|
FSASLMechanisms := TIdSASLEntries.Create(Self);
|
||
|
FRegularProtPort := IdPORT_POP3;
|
||
|
FImplicitTLSProtPort := IdPORT_POP3S;
|
||
|
Port := IdPORT_POP3;
|
||
|
FAuthType := DEF_ATYPE;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.Delete(const MsgNum: Integer): Boolean;
|
||
|
begin
|
||
|
Result := (SendCmd('DELE ' + IntToStr(MsgNum), '') = ST_OK); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.DisconnectNotifyPeer;
|
||
|
begin
|
||
|
inherited;
|
||
|
SendCmd('QUIT', ST_OK); {do not localize}
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.GetReplyClass:TIdReplyClass;
|
||
|
begin
|
||
|
Result := TIdReplyPOP3;
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.KeepAlive;
|
||
|
begin
|
||
|
SendCmd('NOOP', ST_OK); {Do not Localize}
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.Reset: Boolean;
|
||
|
begin
|
||
|
Result := (SendCmd('RSET', '') = ST_OK); {Do not Localize}
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveRaw(const aMsgNo: Integer; const aDest: TStrings): boolean;
|
||
|
var
|
||
|
LEncoding: IIdTextEncoding;
|
||
|
begin
|
||
|
Result := (SendCmd('RETR ' + IntToStr(aMsgNo), '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
LEncoding := IndyTextEncoding_8Bit;
|
||
|
IOHandler.Capture(aDest, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveRaw(const aMsgNo: Integer; const aDest: TStream): boolean;
|
||
|
var
|
||
|
LEncoding: IIdTextEncoding;
|
||
|
begin
|
||
|
Result := (SendCmd('RETR ' + IntToStr(aMsgNo), '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
LEncoding := IndyTextEncoding_8Bit;
|
||
|
IOHandler.Capture(aDest, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.Retrieve(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
|
||
|
begin
|
||
|
Result := (SendCmd('RETR ' + IntToStr(MsgNum), '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
AMsg.Clear;
|
||
|
// This is because of a bug in Exchange? with empty messages. See comment in ReceiveHeader
|
||
|
if ReceiveHeader(AMsg) = '' then begin
|
||
|
// Only retreive the body if we do not already have a full RFC
|
||
|
ReceiveBody(AMsg);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveHeader(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
|
||
|
begin
|
||
|
// Result := False;
|
||
|
AMsg.Clear;
|
||
|
SendCmd('TOP ' + IntToStr(MsgNum) + ' 0', ST_OK); {Do not Localize}
|
||
|
// Only gets here if no exception is raised
|
||
|
ReceiveHeader(AMsg,'.');
|
||
|
Result := True;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveMailBoxSize: Int64;
|
||
|
var
|
||
|
LIgnore: Integer;
|
||
|
begin
|
||
|
// RLebeau: for backwards compatibility, return -1 if STAT fails
|
||
|
try
|
||
|
if not RetrieveStats(LIgnore, Result) then begin
|
||
|
RaiseExceptionForLastCmdResult;
|
||
|
end;
|
||
|
except
|
||
|
Result := -1;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveMsgSize(const MsgNum: Integer): Integer;
|
||
|
var
|
||
|
s: string;
|
||
|
begin
|
||
|
Result := -1;
|
||
|
// Returns the size of the message. if an error ocurrs, returns -1.
|
||
|
SendCmd('LIST ' + IntToStr(MsgNum), ST_OK); {Do not Localize}
|
||
|
s := LastCmdResult.Text[0];
|
||
|
if Length(s) > 0 then begin
|
||
|
// RL - ignore the message number, grab just the octets,
|
||
|
// and ignore everything else that may be present
|
||
|
Fetch(s);
|
||
|
Result := IndyStrToInt(Fetch(s), -1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.RetrieveStats(var VMsgCount: Integer; var VMailBoxSize: Int64): Boolean;
|
||
|
var
|
||
|
s: string;
|
||
|
begin
|
||
|
VMsgCount := 0;
|
||
|
VMailBoxSize := 0;
|
||
|
Result := (SendCmd('STAT', '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
s := LastCmdResult.Text[0];
|
||
|
if Length(s) > 0 then begin
|
||
|
VMsgCount := IndyStrToInt(Fetch(s));
|
||
|
VMailBoxSize := IndyStrToInt64(Fetch(s));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.List(const ADest: TStrings; const AMsgNum: Integer = -1): Boolean;
|
||
|
var
|
||
|
LEncoding: IIdTextEncoding;
|
||
|
begin
|
||
|
if AMsgNum >= 0 then begin
|
||
|
Result := (SendCmd('LIST ' + IntToStr(AMsgNum), '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
ADest.Assign(LastCmdResult.Text);
|
||
|
end;
|
||
|
end
|
||
|
else begin
|
||
|
Result := (SendCmd('LIST', '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
LEncoding := IndyTextEncoding_8Bit;
|
||
|
IOHandler.Capture(ADest, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.ParseLIST(ALine: String; var VMsgNum, VMsgSize: Integer);
|
||
|
begin
|
||
|
VMsgNum := IndyStrToInt(Fetch(ALine), -1);
|
||
|
VMsgSize := IndyStrToInt(Fetch(ALine), -1);
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.UIDL(const ADest: TStrings; const AMsgNum: Integer = -1): Boolean;
|
||
|
var
|
||
|
LEncoding: IIdTextEncoding;
|
||
|
begin
|
||
|
if AMsgNum >= 0 then begin
|
||
|
Result := (SendCmd('UIDL ' + IntToStr(AMsgNum), '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
ADest.Assign(LastCmdResult.Text);
|
||
|
end;
|
||
|
end
|
||
|
else begin
|
||
|
Result := (SendCmd('UIDL', '') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
LEncoding := IndyTextEncoding_8Bit;
|
||
|
IOHandler.Capture(ADest, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.ParseUIDL(ALine: String; var VMsgNum: Integer; var VUidl: String);
|
||
|
begin
|
||
|
VMsgNum := IndyStrToInt(Fetch(ALine), -1);
|
||
|
VUidl := Fetch(ALine);
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.Top(const AMsgNum: Integer; const ADest: TStrings; const AMaxLines: Integer = 0): boolean;
|
||
|
var
|
||
|
Cmd: String;
|
||
|
LEncoding: IIdTextEncoding;
|
||
|
begin
|
||
|
Cmd := 'TOP ' + IntToStr(AMsgNum); {Do not Localize}
|
||
|
if AMaxLines <> 0 then begin
|
||
|
Cmd := Cmd + ' ' + IntToStr(AMaxLines); {Do not Localize}
|
||
|
end;
|
||
|
Result := (SendCmd(Cmd,'') = ST_OK);
|
||
|
if Result then begin
|
||
|
LEncoding := IndyTextEncoding_8Bit;
|
||
|
IOHandler.Capture(ADest, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
destructor TIdPOP3.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(FSASLMechanisms);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.CAPA: Boolean;
|
||
|
begin
|
||
|
FCapabilities.Clear;
|
||
|
Result := (SendCmd('CAPA','') = ST_OK); {Do not Localize}
|
||
|
if Result then begin
|
||
|
IOHandler.Capture(FCapabilities);
|
||
|
end;
|
||
|
// RLebeau - do not delete here! The +OK reply line is handled
|
||
|
// by SendCmd() above. Deleting here is removing an actual capability entry.
|
||
|
{
|
||
|
if FCapabilities.Count >0 then
|
||
|
begin
|
||
|
//dete the initial OK reply line
|
||
|
FCapabilities.Delete(0);
|
||
|
end;
|
||
|
FHasCapa := Result;
|
||
|
}
|
||
|
FHasCapa := (FCapabilities.Count > 0);
|
||
|
// ParseCapaReply(FCapabilities,'SASL');
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.Notification(AComponent: TComponent; Operation: TOperation);
|
||
|
begin
|
||
|
if (Operation = opRemove) and (FSASLMechanisms <> nil) then begin
|
||
|
FSASLMechanisms.RemoveByComp(AComponent);
|
||
|
end;
|
||
|
inherited Notification(AComponent,Operation);
|
||
|
end;
|
||
|
|
||
|
function TIdPOP3.GetSupportsTLS: Boolean;
|
||
|
begin
|
||
|
Result := ( FCapabilities.IndexOf('STLS') > -1 ); //do not localize
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.SetSASLMechanisms(AValue: TIdSASLEntries);
|
||
|
begin
|
||
|
FSASLMechanisms.Assign(AValue);
|
||
|
end;
|
||
|
|
||
|
procedure TIdPOP3.Connect;
|
||
|
var
|
||
|
S: String;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
FHasAPOP := False;
|
||
|
FHasCAPA := False;
|
||
|
FAPOPToken := '';
|
||
|
|
||
|
if (IOHandler is TIdSSLIOHandlerSocketBase) then begin
|
||
|
(IOHandler as TIdSSLIOHandlerSocketBase).PassThrough := (FUseTLS <> utUseImplicitTLS);
|
||
|
end;
|
||
|
|
||
|
inherited Connect;
|
||
|
try
|
||
|
GetResponse(ST_OK);
|
||
|
|
||
|
// the initial greeting text is needed to determine APOP availability
|
||
|
S := LastCmdResult.Text.Strings[0]; //read response
|
||
|
I := Pos('<', S); {Do not Localize}
|
||
|
if i > 0 then begin
|
||
|
S := Copy(S, I, MaxInt); //?: System.Delete(S,1,i-1);
|
||
|
I := Pos('>', S); {Do not Localize}
|
||
|
if I > 0 then begin
|
||
|
FAPOPToken := Copy(S, 1, I);
|
||
|
end;
|
||
|
end;
|
||
|
FHasAPOP := (Length(FAPOPToken) > 0);
|
||
|
CAPA;
|
||
|
if FAutoLogin then begin
|
||
|
Login;
|
||
|
end;
|
||
|
except
|
||
|
Disconnect(False);
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|
||
|
|
||
|
|