"Vern Six" <
XXXX@XXXXX.COM>writes
Quote
s := '+OK ' + IntToStr(TVsMsgInfo(MsgList.Items[AMessageNum-1]).Size)
+
' octets';
ASender.thread.Connection.WriteLn(s);
I would not recommend you call WriteLn() until after you have already loaded
and prepared the TIdMessage for sending. Otherwise you are going to be
sending an incomplete response to the client. Also, whenever you are
catching exceptions, you are simply calling 'Exit' without letting the
exception make its way back to TIdPOP3Server. You should let exceptions
make their way back so that it can know that something wrong happened and
return an error response to the client. In back, to make sure that you do
not send an incomplete respnse, you should buffer the response using
OpenWriteBuffer() and CloseWriteBuffer(), with CancelWriteBuffer() in case
an error occurs.
Quote
AMsg.NoEncode := true;
AMsg.NoDecode := true;
Since you are essentially loading and message file without any extra
processing whatever, then why not just load the file into a stream, such as
TFileStream, and send it directly without using TIdMessage at all?
Quote
if ( lowercase(trim(e.Message)) <>'socket error # 0' ) then
begin
An easier way to test the error would be to cast the exception to
EIdSocketError (or just catch EIdSocketError to begin with) and then use its
ErrorCode property:
except
on e: EIdSocketError do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
if ( e.ErrorCode <>0 ) then exit;
end;
on e: exception do begin
AddToLog('ASender.Thread.Connection.WriteStream exception: ' +
e.Message );
exit;
end;
end;
With all that said, try this instead (untested):
procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TMemoryStream;
AMsg : TIdMessage;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );
sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );
try
try
AMsg := TIdMessage.create(nil);
AMsg.NoEncode := true;
AMsg.NoDecode := true;
except
on e: Exception do AddToLog('TIdMessage.create
exception: ' + e.Message);
Raise; // so TIdPop3Server knows something went wrong
end;
try
AMsg.LoadFromFile(sMsgFile, false);
except
on e: exception do AddToLog('TIdMessage.LoadFromFile
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;
try
AStream := TMemoryStream.Create;
except
on e: Exception do AddToLog('TMemoryStream.create
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;
try
AMsg.SaveToStream(AStream, false);
AStream.Seek(0, soFromBeginning);
except
on e: Exception do AddToLog('TIdMessage.SaveToStream
exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;
ASender.Thread.Connection.OpenWriteBuffer;
try
ASender.Thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.Thread.Connection.CloseWriteBuffer;
except
on e: Exception do begin
ASender.Thread.Connection.ClearWriteBuffer;
AddToLog('ASender.Thread.Connection exception: ' +
e.Message );
Raise; // so TIdPop3Server knows something went
wrong
end;
AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
finally
if Assigned(AStream) then FreeAndNil(AStream);
if Assigned(AMsg) then FreeAndNil(AMsg);
end;
end;
end; // RETR
Or simply:
procedure TMainForm.PopServerRETR(ASender: TIdCommand; AMessageNum:
Integer);
var
sMsgFile: string;
AStream: TFileStream;
begin
with TVsUserData(ASender.Thread.Data) do
begin
AddToLog( 'C: RETR ' + IntToStr(AMessageNum) );
sMsgFile := MsgPath +
TVsMsgInfo(MsgList.Items[AMessageNum-1]).FileName;
AddToLog( 'About to send contents of ' + sMsgFile );
try
AStream := TFileStream.Create(sMsgFile, fmOpenRead or
fmShareDenyWrite);
try
ASender.thread.Connection.OpenWriteBuffer;
try
ASender.thread.Connection.WriteLn('+OK ' +
IntToStr(AStream.Size) + ' octets');
ASender.Thread.Connection.WriteStream(AStream);
ASender.thread.Connection.CloseWriteBuffer;
AddToLog( 'S: <contents of ' + sMsgFile + ' sent
successfully>' );
except
ASender.thread.Connection.ClearWriteBuffer;
Raise;
end;
finally
FreeAndNil(AStream);
end;
except
on e: Exception do begin
AddToLog('Exception: ' + e.Message );
Raise; // so TIdPop3Server knows something went wrong
end;
end;
end;
end; // RETR
Gambit