| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 |
- { $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: 10253: IdMessageClient.pas
- {
- { Rev 1.13 7/23/04 6:11:26 PM RLebeau
- { TFileStream access right tweak for ProcessMessage()
- }
- {
- { Rev 1.12 5/12/04 9:52:06 AM RLebeau
- { Updated ProcessMessage() to call ReceiveBody() only if ReceiveHeader() does
- { not receive the message terminator first
- }
- {
- { Rev 1.11 5/2/04 7:58:08 PM RLebeau
- { Updated TIdIOHandlerStreamMsg.Recv() to not use a local buffer anymore
- }
- {
- { Rev 1.10 5/1/04 3:04:16 AM RLebeau
- { Bug fix for TIdIOHandlerStreamMsg, and also updated to keep track of the last
- { character received from the stream so that extra CR LF characters are not
- { added to the end of the message data unnecessarily.
- }
- {
- { Rev 1.9 4/23/04 1:54:22 PM RLebeau
- { Added support for TIdIOHandlerStreamMsg class
- }
- {
- { Rev 1.8 2/3/04 11:59:20 AM RLebeau
- { Updated SendBody() to output the TIdMessagePart.ContentID property if it is
- { assigned.
- }
- {
- { Rev 1.7 10/17/03 11:50:46 AM RLebeau
- { Updated ReceiveBody() to copy all available header values from the message
- { decoder when creating TIdText and TIdAttachment instances rather than just
- { select values.
- }
- {
- { Rev 1.6 2003.07.03 11:52:08 AM czhower
- { DeleteTempFiles addition.
- { Fix of old property IsTempFile, changed to DeleteTempFile so as not to change
- { broken but old functionality that could otherwise cause data loss.
- }
- {
- { Rev 1.5 2003.06.15 3:00:34 PM czhower
- { -Fixed IdIOHandlerStream to function as originally designed and needed.
- { -Change ReadStream, WriteStream to Input/Output to be consistent with other
- { areas.
- }
- {
- { Rev 1.4 21/2/2003 1:53:10 PM SGrobety
- { Fixed a problem when the message contained only a single text part
- }
- {
- { Rev 1.3 11-30-2002 11:49:50 BGooijen
- { Fixed double if keywork in if-statement, which caused to file not to compile
- }
- {
- { Rev 1.2 11/23/2002 03:23:08 AM JPMugaas
- { Reverted back to old way because the fix turned out to be problematic.
- }
- {
- { Rev 1.1 11/19/2002 05:24:10 PM JPMugaas
- { Fixed problem with a . starting a line causing a duplicate period where it
- { shouldn't.
- }
- {
- { Rev 1.0 2002.11.12 10:45:48 PM czhower
- }
- unit IdMessageClient;
- {
- 2001-Oct-29 Don Siders
- Modified TIdMessageClient.SendMsg to use AHeadersOnly argument.
- 2001-Dec-1 Don Siders
- Save ContentDisposition in TIdMessageClient.ProcessAttachment
- }
- interface
- uses
- Classes,
- IdGlobal, IdIOHandlerStream, IdMessage, IdTCPClient, IdHeaderList;
- type
- TIdIOHandlerStreamMsg = class(TIdIOHandlerStream)
- protected
- FTerminator: String;
- FTerminatorIndex: Integer;
- FLastCharRecv: Char;
- public
- constructor Create(AOwner: TComponent); override;
- function Readable(AMSec: integer = IdTimeoutDefault): boolean; override;
- function Recv(var ABuf; ALen: integer): integer; override;
- end;
- TIdMessageClient = class(TIdTCPClient)
- protected
- // The length of the folded line
- FMsgLineLength: integer;
- // The string to be pre-pended to the next line
- FMsgLineFold: string;
- //
- procedure ReceiveBody(AMsg: TIdMessage; const ADelim: string = '.'); virtual;
- function ReceiveHeader(AMsg: TIdMessage; const AAltTerm: string = ''): string; virtual;
- procedure SendBody(AMsg: TIdMessage); virtual;
- procedure SendHeader(AMsg: TIdMessage); virtual;
- procedure WriteBodyText(AMsg: TIdMessage); virtual;
- procedure WriteFoldedLine(const ALine : string);
- public
- constructor Create(AOwner : TComponent); override;
- procedure ProcessMessage(AMsg: TIdMessage; AHeaderOnly: Boolean = False); overload;
- procedure ProcessMessage(AMsg: TIdMessage; const AStream: TStream; AHeaderOnly: Boolean = False); overload;
- procedure ProcessMessage(AMsg: TIdMessage; const AFilename: string; AHeaderOnly: Boolean = False); overload;
- procedure SendMsg(AMsg: TIdMessage; const AHeadersOnly: Boolean = False); virtual;
- //
- property MsgLineLength: integer read FMsgLineLength write FMsgLineLength;
- property MsgLineFold: string read FMsgLineFold write FMsgLineFold;
- end;
- implementation
- uses
- //TODO: Remove these references and make it completely pluggable. Check other spots in Indy as well
- IdCoderQuotedPrintable, IdMessageCoderMIME, IdMessageCoderUUE, IdMessageCoderXXE,
- //
- IdCoder, IdCoder3to4,
- IdCoderHeader, IdMessageCoder, IdComponent, IdException, IdResourceStrings, IdTCPConnection,
- IdTCPStream, IdIOHandler,
- SysUtils;
- const
- SMsgTerminator = #13#10'.'#13#10; {do not localize}
- function GetLongestLine(var ALine : String; ADelim : String) : String;
- var
- i, fnd, lineLen, delimLen : Integer;
- begin
- i := 0;
- fnd := -1;
- delimLen := length(ADelim);
- lineLen := length(ALine);
- while i < lineLen do
- begin
- if ALine[i] = ADelim[1] then
- begin
- if Copy(ALine, i, delimLen) = ADelim then
- begin
- fnd := i;
- end;
- end;
- Inc(i);
- end;
- if fnd = -1 then
- begin
- result := '';
- end
- else begin
- result := Copy(ALine, 1, fnd - 1);
- ALine := Copy(ALine, fnd + delimLen, lineLen);
- end;
- end;
- ////////////////////////
- // TIdIOHandlerStreamMsg
- ////////////////////////
- constructor TIdIOHandlerStreamMsg.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FTerminator := SMsgTerminator;
- FTerminatorIndex := 0;
- FLastCharRecv := #0;
- end;
- function TIdIOHandlerStreamMsg.Readable(AMSec: integer = IdTimeoutDefault): boolean;
- begin
- // if the terminator is not started yet, check the source data first...
- if FTerminatorIndex = 0 then begin
- Result := inherited Readable(AMSec);
- if Result then begin
- Exit;
- end;
- end;
- // check the terminator next...
- if InputStream <> nil then begin
- Result := (FTerminatorIndex <= Length(FTerminator));
- end else begin
- Result := False
- end;
- end;
- function TIdIOHandlerStreamMsg.Recv(var ABuf; ALen: integer): integer;
- begin
- // if the terminator is not started yet, check the source data first...
- if FTerminatorIndex = 0 then begin
- Result := inherited Recv(ABuf, ALen);
- if Result > 0 then begin
- // save the last character received for later use, see below
- FLastCharRecv := PChar(@ABuf)[Result-1];
- Exit;
- end;
- if (ALen <= 0) then begin
- // buffer size not specified, just return now without starting the terminator yet...
- Exit;
- end;
- // determine whether the stream ended with a line
- // break, adding an extra CR and/or LF if needed...
- if (FLastCharRecv = LF) then begin
- // don't add an extra line break
- FTerminatorIndex := 3;
- end else if (FLastCharRecv = CR) then begin
- // add extra LF
- FTerminatorIndex := 2;
- end else begin
- // add extra CRLF
- FTerminatorIndex := 1;
- end;
- end;
- // return the appropriate piece of the terminator...
- ALen := Min(ALen, (Length(FTerminator)-FTerminatorIndex)+1);
- if ALen > 0 then begin
- Move(FTerminator[FTerminatorIndex], ABuf, ALen);
- Inc(FTerminatorIndex, ALen);
- end;
- Result := ALen;
- end;
- ///////////////////
- // TIdMessageClient
- ///////////////////
- constructor TIdMessageClient.Create;
- begin
- inherited;
- FMsgLineLength := 79;
- FMsgLineFold := TAB;
- end;
- procedure TIdMessageClient.WriteFoldedLine;
- var
- ins, s, line, spare : String;
- msgLen, insLen : Word;
- begin
- s := ALine;
- // To give an amount of thread-safety
- ins := FMsgLineFold;
- insLen := Length(ins);
- msgLen := FMsgLineLength;
- // Do first line
- if length(s) > FMsgLineLength then
- begin
- spare := Copy(s, 1, msgLen);
- line := GetLongestLine(spare, ' ');
- s := spare + Copy(s, msgLen + 1, length(s));
- WriteLn(line);
- // continue with the folded lines
- while length(s) > (msgLen - insLen) do
- begin
- spare := Copy(s, 1, (msgLen - insLen));
- line := GetLongestLine(spare, ' ');
- s := ins + spare + Copy(s, (msgLen - insLen) + 1, length(s));
- WriteLn(line);
- end;
- // complete the output with what's left
- if Trim(s) <> '' then
- begin
- WriteLn(ins + s);
- end;
- end
- else begin
- WriteLn(s);
- end;
- end;
- procedure TIdMessageClient.ReceiveBody(AMsg: TIdMessage; const ADelim: string = '.');
- var
- LMsgEnd: Boolean;
- LActiveDecoder: TIdMessageDecoder;
- LLine: string;
- function ProcessTextPart(ADecoder: TIdMessageDecoder): TIdMessageDecoder;
- var
- LDestStream: TStringStream;
- begin
- LDestStream := TStringStream.Create('');
- try
- Result := ADecoder.ReadBody(LDestStream, LMsgEnd);
- with TIdText.Create(AMsg.MessageParts) do
- begin
- {
- ContentType := ADecoder.Headers.Values['Content-Type'];
- ContentTransfer := ADecoder.Headers.Values['Content-Transfer-Encoding'];
- }
- // RLebeau 10/17/2003
- Headers.AddStdValues(ADecoder.Headers);
- Body.Text := LDestStream.DataString;
- end;
- ADecoder.Free;
- finally
- FreeAndNil(LDestStream);
- end;
- end;
- function ProcessAttachment(ADecoder: TIdMessageDecoder): TIdMessageDecoder;
- var
- LDestStream: TFileStream;
- LTempPathname: string;
- begin
- LTempPathname := MakeTempFilename;
- LDestStream := TFileStream.Create(LTempPathname, fmCreate);
- try
- Result := ADecoder.ReadBody(LDestStream, LMsgEnd);
- with TIdAttachment.Create(AMsg.MessageParts) do
- begin
- DeleteTempFile := AMsg.DeleteTempFiles;
- {
- ContentType := ADecoder.Headers.Values['Content-Type'];
- ContentTransfer := ADecoder.Headers.Values['Content-Transfer-Encoding'];
- // dsiders 2001.12.01
- ContentDisposition := ADecoder.Headers.Values['Content-Disposition'];
- }
- // RLebeau 10/17/2003
- Headers.AddStdValues(ADecoder.Headers);
- Filename := ADecoder.Filename;
- StoredPathname := LTempPathname;
- end;
- ADecoder.Free;
- finally
- FreeAndNil(LDestStream);
- end;
- end;
- const
- wDoublePoint = ord('.') shl 8 + ord('.');
- Begin
- LMsgEnd := False;
- if AMsg.NoDecode then
- begin
- Capture(AMsg.Body, ADelim);
- end
- else begin
- BeginWork(wmRead);
- try
- LActiveDecoder := nil;
- repeat
- LLine := ReadLn;
- if LLine = ADelim then
- begin
- Break;
- end;
- if LActiveDecoder = nil then
- begin
- LActiveDecoder := TIdMessageDecoderList.CheckForStart(AMsg, LLine);
- end;
- if LActiveDecoder = nil then begin
- if PWord(PChar(LLine))^= wDoublePoint then begin
- Delete(LLine,1,1);
- end;//if '..'
- AMsg.Body.Add(LLine);
- end else begin
- while LActiveDecoder <> nil do begin
- LActiveDecoder.SourceStream := TIdTCPStream.Create(Self);
- LActiveDecoder.ReadHeader;
- case LActiveDecoder.PartType of
- mcptUnknown:
- begin
- raise EIdException.Create(RSMsgClientUnkownMessagePartType);
- end;
- mcptText:
- begin
- LActiveDecoder := ProcessTextPart(LActiveDecoder);
- end;
- mcptAttachment:
- begin
- LActiveDecoder := ProcessAttachment(LActiveDecoder);
- end;
- end;
- end;
- end;
- until LMsgEnd;
- finally
- EndWork(wmRead);
- end;
- end;
- end;
- procedure TIdMessageClient.SendHeader(AMsg: TIdMessage);
- var
- LHeaders: TIdHeaderList;
- begin
- LHeaders := AMsg.GenerateHeader;
- try
- WriteStrings(LHeaders);
- finally
- FreeAndNil(LHeaders);
- end;
- end;
- procedure TIdMessageClient.SendBody(AMsg: TIdMEssage);
- var
- i: Integer;
- LAttachment: TIdAttachment;
- LBoundary: string;
- LDestStream: TIdTCPStream;
- LMIMEAttachments: boolean;
- ISOCharset: string;
- HeaderEncoding: Char; { B | Q }
- TransferEncoding: TTransfer;
- procedure WriteTextPart(ATextPart: TIdText);
- var
- Data: string;
- i: Integer;
- begin
- if Length(ATextPart.ContentType) = 0 then
- ATextPart.ContentType := 'text/plain'; {do not localize}
- if Length(ATextPart.ContentTransfer) = 0 then
- ATextPart.ContentTransfer := 'quoted-printable'; {do not localize}
- WriteLn('Content-Type: ' + ATextPart.ContentType); {do not localize}
- WriteLn('Content-Transfer-Encoding: ' + ATextPart.ContentTransfer); {do not localize}
- if Length(ATextPart.ContentID) <> 0 then
- begin
- WriteLn('Content-Id: ' + ATextPart.ContentID);
- end;
- WriteStrings(ATextPart.ExtraHeaders);
- WriteLn('');
- // TODO: Provide B64 encoding later
- // if AnsiSameText(ATextPart.ContentTransfer, 'base64') then begin
- // LEncoder := TIdEncoder3to4.Create(nil);
- if AnsiSameText(ATextPart.ContentTransfer, 'quoted-printable') then
- begin
- for i := 0 to ATextPart.Body.Count - 1 do
- begin
- if Copy(ATextPart.Body[i], 1, 1) = '.' then
- begin
- ATextPart.Body[i] := '.' + ATextPart.Body[i];
- end;
- Data := TIdEncoderQuotedPrintable.EncodeString(ATextPart.Body[i] + EOL);
- if TransferEncoding = iso2022jp then
- Write(Encode2022JP(Data))
- else
- Write(Data);
- end;
- end
- else begin
- WriteStrings(ATextPart.Body);
- end;
- WriteLn('');
- end;
- begin
- LMIMEAttachments := AMsg.Encoding = meMIME;
- LBoundary := '';
- InitializeISO(TransferEncoding, HeaderEncoding, ISOCharSet);
- BeginWork(wmWrite);
- try
- if AMsg.MessageParts.AttachmentCount > 0 then
- begin
- if LMIMEAttachments then
- begin
- WriteLn('This is a multi-part message in MIME format'); {do not localize}
- WriteLn('');
- if AMsg.MessageParts.RelatedPartCount > 0 then
- begin
- LBoundary := IndyMultiPartRelatedBoundary;
- end
- else begin
- LBoundary := IndyMIMEBoundary;
- end;
- WriteLn('--' + LBoundary);
- end
- else begin
- // It's UU, write the body
- WriteBodyText(AMsg);
- WriteLn('');
- end;
- if AMsg.MessageParts.TextPartCount > 1 then
- begin
- WriteLn('Content-Type: multipart/alternative; '); {do not localize}
- WriteLn(' boundary="' + IndyMultiPartAlternativeBoundary + '"'); {do not localize}
- WriteLn('');
- for i := 0 to AMsg.MessageParts.Count - 1 do
- begin
- if AMsg.MessageParts.Items[i] is TIdText then
- begin
- WriteLn('--' + IndyMultiPartAlternativeBoundary);
- DoStatus(hsStatusText, [RSMsgClientEncodingText]);
- WriteTextPart(AMsg.MessageParts.Items[i] as TIdText);
- WriteLn('');
- end;
- end;
- WriteLn('--' + IndyMultiPartAlternativeBoundary + '--');
- end
- // RLebeau 2/3/2006: If the user added a single texpart message without filling the body
- // RLebeau 2/3/2003: we still need to send that out
- else if AMsg.MessageParts.TextPartCount = 1 then
- begin
- for i := 0 to AMsg.MessageParts.Count - 1 do
- begin
- if AMsg.MessageParts.Items[i] is TIdText then
- begin
- DoStatus(hsStatusText, [RSMsgClientEncodingText]);
- WriteTextPart(AMsg.MessageParts.Items[i] as TIdText);
- Break;
- end;
- end;
- end
- else begin
- if LMIMEAttachments then
- begin
- WriteLn('Content-Type: text/plain'); {do not localize}
- WriteLn('Content-Transfer-Encoding: 7bit'); {do not localize}
- WriteLn('');
- WriteBodyText(AMsg);
- end;
- end;
- // Send the attachments
- for i := 0 to AMsg.MessageParts.Count - 1 do
- begin
- if AMsg.MessageParts[i] is TIdAttachment then
- begin
- LAttachment := TIdAttachment(AMsg.MessageParts[i]);
- DoStatus(hsStatusText, [RSMsgClientEncodingAttachment]);
- if LMIMEAttachments then
- begin
- WriteLn('');
- WriteLn('--' + LBoundary);
- if Length(LAttachment.ContentTransfer) = 0 then
- begin
- LAttachment.ContentTransfer := 'base64'; {do not localize}
- end;
- if Length(LAttachment.ContentDisposition) = 0 then
- begin
- LAttachment.ContentDisposition := 'attachment'; {do not localize}
- end;
- if (LAttachment.ContentTransfer = 'base64') {do not localize}
- and (Length(LAttachment.ContentType) = 0) then
- begin
- LAttachment.ContentType := 'application/octet-stream'; {do not localize}
- end;
- WriteLn('Content-Type: ' + LAttachment.ContentType + ';'); {do not localize}
- WriteLn(' name="' + ExtractFileName(LAttachment.FileName) + '"'); {do not localize}
- WriteLn('Content-Transfer-Encoding: ' + LAttachment.ContentTransfer); {do not localize}
- WriteLn('Content-Disposition: ' + LAttachment.ContentDisposition +';'); {do not localize}
- WriteLn(' filename="' + ExtractFileName(LAttachment.FileName) + '"'); {do not localize}
- if Length(LAttachment.ContentID) <> 0 then
- begin
- WriteLn('Content-Id: ' + LAttachment.ContentID);
- end;
- WriteStrings(LAttachment.ExtraHeaders);
- WriteLn('');
- end;
- LDestStream := TIdTCPStream.Create(Self, 8192);
- try
- TIdAttachment(AMsg.MessageParts[i]).Encode(LDestStream);
- finally
- FreeAndNil(LDestStream);
- end;
- WriteLn('');
- end;
- end;
- if LMIMEAttachments then
- begin
- WriteLn('--' + LBoundary + '--');
- end;
- end
- // S.G. 21/2/2003: If the user added a single texpart message without filling the body
- // S.G. 21/2/2003: we still need to send that out
- else
- if (AMsg.MessageParts.TextPartCount > 1) or
- ((AMsg.MessageParts.TextPartCount = 1) and (AMsg.Body.Count = 0)) then
- begin
- WriteLn('This is a multi-part message in MIME format'); {do not localize}
- WriteLn('');
- for i := 0 to AMsg.MessageParts.Count - 1 do
- begin
- if AMsg.MessageParts.Items[i] is TIdText then
- begin
- WriteLn('--' + IndyMIMEBoundary);
- DoStatus(hsStatusText, [RSMsgClientEncodingText]);
- WriteTextPart(AMsg.MessageParts.Items[i] as TIdText);
- end;
- end;
- WriteLn('--' + IndyMIMEBoundary + '--');
- end
- else begin
- DoStatus(hsStatusText, [RSMsgClientEncodingText]);
- // Write out Body
- //TODO: Why just iso2022jp? Why not someting generic for all MBCS? Or is iso2022jp special?
- if TransferEncoding = iso2022jp then
- begin
- for i := 0 to AMsg.Body.Count - 1 do
- begin
- if Copy(AMsg.Body[i], 1, 1) = '.' then
- begin
- WriteLn('.' + Encode2022JP(AMsg.Body[i]));
- end
- else begin
- WriteLn(Encode2022JP(AMsg.Body[i]));
- end;
- end;
- end
- else begin
- WriteBodyText(AMsg);
- end;
- end;
- finally
- EndWork(wmWrite);
- end;
- end;
- { 2001-Oct-29 Don Siders
- procedure TIdMessageClient.SendMsg(AMsg: TIdMessage);
- begin
- SendHeader(AMsg);
- WriteLn('');
- SendBody(AMsg);
- end; }
- // 2001-Oct-29 Don Siders Added AHeadersOnly parameter
- // TODO: Override TIdMessageClient.SendMsg to provide socket, stream, and file
- // versions like TIdMessageClient.ProcessMessage?
- procedure TIdMessageClient.SendMsg(AMsg: TIdMessage; const AHeadersOnly: Boolean = False);
- begin
- if AMsg.NoEncode then begin
- WriteStringS(AMsg.Headers);
- WriteLn('');
- if not AHeadersOnly then begin
- WriteStrings(AMsg.Body);
- end;
- end else begin
- SendHeader(AMsg);
- WriteLn('');
- if (not AHeadersOnly) then SendBody(AMsg);
- end;
- end;
- function TIdMessageClient.ReceiveHeader(AMsg: TIdMessage; const AAltTerm: string = ''): string;
- begin
- BeginWork(wmRead); try
- repeat
- Result := ReadLn;
- // Exchange Bug: Exchange sometimes returns . when getting a message instead of
- // '' then a . - That is there is no seperation between the header and the message for an
- // empty message.
- if ((Length(AAltTerm) = 0) and (Result = '.')) or
- ({APR: why? (Length(AAltTerm) > 0) and }(Result = AAltTerm)) then begin
- Break;
- end else if Result <> '' then begin
- AMsg.Headers.Append(Result);
- end;
- until False;
- AMsg.ProcessHeaders;
- finally EndWork(wmRead); end;
- end;
- procedure TIdMessageClient.ProcessMessage(AMsg: TIdMessage; AHeaderOnly: Boolean = False);
- begin
- if IOHandler <> nil then
- begin
- if Length(ReceiveHeader(AMsg)) = 0 then begin
- // Only retreive the body if we do not already have a full RFC
- if (not AHeaderOnly) then begin
- ReceiveBody(AMsg);
- end;
- end;
- end;
- end;
- procedure TIdMessageClient.ProcessMessage(AMsg: TIdMessage; const AStream: TStream; AHeaderOnly: Boolean = False);
- var
- LIOHSM: TIdIOHandlerStreamMsg;
- begin
- LIOHSM := TIdIOHandlerStreamMsg.Create(nil); try
- LIOHSM.InputStream := AStream;
- LIOHSM.FreeStreams := False;
- IOHandler := LIOHSM; try
- Connect; try
- ProcessMessage(AMsg, AHeaderOnly);
- finally Disconnect; end;
- finally IOHandler := nil; end;
- finally FreeAndNil(LIOHSM); end;
- end;
- procedure TIdMessageClient.ProcessMessage(AMsg: TIdMessage; const AFilename: string; AHeaderOnly: Boolean = False);
- var
- LStream: TFileStream;
- begin
- LStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
- try
- ProcessMessage(AMsg, LStream, AHeaderOnly);
- finally
- FreeAndNil(LStream);
- end;
- end;
- procedure TIdMessageClient.WriteBodyText(AMsg: TIdMessage);
- var
- i: integer;
- begin
- for i := 0 to AMsg.Body.Count - 1 do
- begin
- if Copy(AMsg.Body[i], 1, 1) = '.' then
- begin
- WriteLn('.' + AMsg.Body[i]);
- end
- else begin
- WriteLn(AMsg.Body[i]);
- end;
- end;
- end;
- end.
|