📄 idimap4.pas
字号:
{ $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: 10205: IdIMAP4.pas
{
{ Rev 1.7 10/06/2003 21:04:20 CCostelloe
{ ReceiveBody added to resolve problems with some servers and
{ (UID)Receive(Peek) functions. See comments starting "CC6".
}
{
{ Rev 1.6 29/05/2003 22:47:02 CCostelloe
{ Major update, most of code rewritten. See comments in source. Tested
{ against CommuniGate and Cyrus IMAP servers.
}
{
{ Rev 1.5 12/05/2003 00:03:52 CCostelloe
{ Bug fix between Windows 98 and Windows 2000 resolved
}
{
{ Rev 1.4 11/05/2003 23:14:18 CCostelloe
{ More bug fixes plus IMAP-specific code moved up from TIdRFCReply.
}
{
{ Rev 1.3 08/05/2003 02:31:28 CCostelloe
}
{
{ Rev 1.2 15/04/2003 00:46:50 CCostelloe
}
{
{ Rev 1.1 01/04/2003 21:54:10 CCostelloe
}
{
{ Rev 1.0 2002.11.12 10:42:04 PM czhower
}
unit IdIMAP4;
{ ########********########********########********########********########********
WARNING:
KNOWN ISSUES AND WORKAROUNDS AS OF 27TH MAY 2003:
AppendMsg is erratic with some IMAP servers, if called with invalid
parameters, you may be better using CopyMsgs instead, particularly
while you are in the debugging stage.
(UID)RetrievePart(Peek) functions occasionally cause erratic crashes,
again if invalid parameters are used (e.g. calling them with the
wrong encoding specified).
The RetrievePartToFile versions are more resilient.
These functions were not part of the Indy 9 release anyway.
UIDRetrieveAllHeaders does nothing (it never did), but this is of
little practical use - you are better off using a "for" loop on the
number of messages in the mailbox and using GetUID to get all the
UIDs quickly, before someone else deletes one, then using
UIDRetrieveHeader on those UIDs.
This is only for Windows, no work has been done on a Linux version.
Ciaran Costelloe, 27th May 2003.
ccostelloe@flogas.ie
########********########********########********########********########********
}
{*
IMAP 4 (Internet Message Access Protocol - Version 4 Rev 1)
By Idan Cohen i_cohen@yahoo.com
2001-FEB-27 IC: First version most of the IMAP features are implemented and
the core IdPOP3 features are implemented to allow a seamless
switch.
The unit is currently oriented to a session connection and not
to constant connection, because of that server events that are
raised from another user actions are not supported.
2001-APR-18 IC: Added support for the session's connection state with a
special exception for commands preformed in wrong connection
states. Exceptions were also added for response errors.
2001-MAY-05 IC:
2001-Mar-13 DS: Fixed Bug # 494813 in CheckMsgSeen where LastCmdResult.Text
was not using the Ln index variable to access server
responses.
2002-Apr-12 DS: fixed bug # 506026 in TIdIMAP4.ListSubscribedMailBoxes. Call
ParseLSubResut instead of ParseListResult.
2003-Mar-31 CC: Added GetUID and UIDSearchMailBox, sorted out some bugs (details
shown in comments in those functions which start with "CC:").
2003-Apr-15 CC2:Sorted out some more bugs (details shown in comments in those
functions which start with "CC2:"). Set FMailBoxSeparator
in ParseListResult and ParseLSubResult.
Some IMAP servers generally return "OK completed" even if they
returned no data, such as passing a non-existent message
number to them: they possibly should return NO or BAD; the
functions here have been changed to return FALSE unless they
get good data back, even if the server answers OK. Similar
change made for other functions.
There are a few exceptions, e.g. ListMailBoxes may only return
"OK completed" if the user has no mailboxes, these are noted.
Also, RetrieveStructure(), UIDRetrieveStructure, RetrievePart,
UIDRetrievePart, RetrievePartPeek and UIDRetrievePartPeek
added to allow user to find the structure of a message and
just retrieve the part or parts he needs.
2003-Apr-30 CC3:Added functionality to retrieve the text of a message (only)
via RetrieveText / UIDRetrieveText / RetrieveTextPeek /
UIDRetrieveTextPeek.
Return codes now generally reflect if the function succeeded
instead of returning True even though function fails.
2003-May-15 CC4:Added functionality to retrieve individual parts of a message
to a file, including the decoding of those parts.
2003-May-29 CC5:Response of some servers to UID version of commands varies,
code changed to deal with those (UID position varies).
Some servers return NO such as when you request an envelope
for a message number that does not exist: functions return
False instead of throwing an exception, as was done for other
servers. The general logic is that if a valid result is
returned from the IMAP server, return True; if there is no
result (but the command is validly structured), return FALSE;
if the command is badly structured or if it gives a response
that this code does not expect, throw an exception (typically
when we get a BAD response instead of OK or NO).
Added IsNumberValid, IsUIDValid to prevent rubbishy parameters
being passed through to IMAP functions.
Sender field now filled in correctly in ParseEnvelope
functions.
All fields in ParseEnvelopeAddress are cleared out first,
avoids an unwitting error where some entries, such as CC list,
will append entries to existing entries.
Full test script now used that tests every TIdIMAP command,
more bugs eradicated.
First version to pass testing against both CommuniGate and
Cyrus IMAP servers.
Not tested against Microsoft Exchange, don't have an Exchange
account to test it against.
2003-Jun-10 CC6:Added (UID)RetrieveEnvelopeRaw, in case the user wants to do
their own envelope parsing.
Code in RetrievePart altered to make it more consistent.
Altered to incorporate Indy 10's use of IdReplyIMAP4 (not
complete at this stage).
ReceiveBody added to IdIMAP4, due to the response of some
servers, which gets (UID)Receive(Peek) functions to work on
more servers.
*}
{ TODO -oIC :
Change the mailbox list commands so that they receive TMailBoxTree
structures and so they can store in them the mailbox name and it's attributes. }
{ TODO -oIC :
Add support for \* special flag in messages, and check for \Recent
flag in STORE command because it cant be stored (will get no reply!!!) }
{ TODO -oIC :
5.1.2. Mailbox Namespace Naming Convention
By convention, the first hierarchical element of any mailbox name
which begins with "#" identifies the "namespace" of the remainder of
the name. This makes it possible to disambiguate between different
types of mailbox stores, each of which have their own namespaces.
For example, implementations which offer access to USENET
newsgroups MAY use the "#news" namespace to partition the USENET
newsgroup namespace from that of other mailboxes. Thus, the
comp.mail.misc newsgroup would have an mailbox name of
"#news.comp.mail.misc", and the name "comp.mail.misc" could refer
to a different object (e.g. a user's private mailbox). } {Do not Localize}
{ TO BE CONSIDERED -CC :
Double-quotes in mailbox names can cause major but subtle failures. Maybe
add the automatic stripping of double-quotes if passed in mailbox names,
to avoid ending up with ""INBOX""
}
interface
{CC3: WARNING - if the following gives a "File not found" error on compilation,
you need to add the path "C:\Program Files\Borland\Delphi7\Source\Indy" in
Project -> Options -> Directories/Conditionals -> Search Path}
{$I IdCompilerDefines.inc}
uses
IdMessage,
Classes,
SysUtils, {CC3: SysUtils added to support Exception}
IdAssignedNumbers,
IdGlobal,
IdMailBox,
IdTCPStream,
{$IFDEF INDY100}
IdAttachment,
IdIOHandler,
IdCoreGlobal,
IdMessageParts,
IdMessageClient,
IdCoreResourceStrings,
IdMessageSASLClient,
{$ELSE}
IdMessageClient,
{$ENDIF}
IdComponent, {CC6: Now needed for ReceiveBody}
IdMessageCoder, {CC2: Now needed for parsing BODYSTRUCTURE}
IdCoderMIME,
IdCoderQuotedPrintable,
IdMessageCollection;
const
wsOk = 1;
wsNo = 2;
wsBad = 3;
wsPreAuth = 4;
wsBye = 5;
{CC4: For consistency, change wsSASLContinue to wsContinue..}
{wsSASLContinue = 10;}
wsContinue = 6;
{$IFDEF INDY100}
const DEF_IMAP4_AUTH = atUserPass;
{$ENDIF}
{CC6: Moved to IdReplyIMAP4 for Indy 10...}
{$IFNDEF INDY100}
const
VALID_TAGGEDREPLIES : array [0..5] of string =
('OK', 'NO', 'BAD', 'PREAUTH', 'BYE', '+');
VALID_UNTAGGEDREPLIES : array [0..5] of string =
('* OK','* NO','* BAD','* PREAUTH','* BYE','* +');
{$ENDIF}
type
{CC3: TIdImapMessagePart and TIdImapMessageParts added for retrieving
individual parts of a message via IMAP}
TIdImapMessagePart = class(TCollectionItem)
protected
FBodyType: string;
FBodySubType: string;
FFileName: string;
FDescription: string;
FEncoding: string;
FSize: integer;
public
property BodyType : String read FBodyType write FBodyType;
property BodySubType : String read FBodySubType write FBodySubType;
property FileName : String read FFileName write FFileName;
property Description : String read FDescription write FDescription;
property Encoding : String read FEncoding write FEncoding;
property Size : integer read FSize write FSize;
end;
type
{CC3: Added for validating message number}
EIdNumberInvalid = class(Exception);
TIdImapMessageParts = class(TOwnedCollection)
protected
function GetItem(Index: Integer): TIdImapMessagePart;
procedure SetItem(Index: Integer; const Value: TIdImapMessagePart);
public
function Add: TIdImapMessagePart;
property Items[Index: Integer]: TIdImapMessagePart read GetItem write SetItem; default;
end;
type
TIdIMAP4Commands =
( cmdCAPABILITY,
cmdNOOP,
cmdLOGOUT,
cmdAUTHENTICATE,
cmdLOGIN,
cmdSELECT,
cmdEXAMINE,
cmdCREATE,
cmdDELETE,
cmdRENAME,
cmdSUBSCRIBE,
cmdUNSUBSCRIBE,
cmdLIST,
cmdLSUB,
cmdSTATUS,
cmdAPPEND,
cmdCHECK,
cmdCLOSE,
cmdEXPUNGE,
cmdSEARCH,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -